From 99b8f856242346a046152ebe9033846e06c35f3b Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Tue, 28 Aug 2018 19:38:28 +0000 Subject: [PATCH 001/428] Poke is fixed (#5689) * Fix: Poke hasn't worked. It does work now partially * Poke are now displayed good again * removed code --- include/conversation.php | 3 +-- mod/poke.php | 37 ++++++++++++++++++------------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/include/conversation.php b/include/conversation.php index ca01997f6a..f10c79d4be 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -229,12 +229,11 @@ function localize_item(&$item) $xmlhead = "<" . "?xml version='1.0' encoding='UTF-8' ?" . ">"; $obj = XML::parseString($xmlhead.$item['object']); - $links = XML::parseString($xmlhead."".unxmlify($obj->link).""); $Bname = $obj->title; $Blink = ""; $Bphoto = ""; - foreach ($links->link as $l) { + foreach ($obj->link as $l) { $atts = $l->attributes(); switch ($atts['rel']) { case "alternate": $Blink = $atts['href']; diff --git a/mod/poke.php b/mod/poke.php index a9dfc73f4e..91f33c0def 100644 --- a/mod/poke.php +++ b/mod/poke.php @@ -24,19 +24,20 @@ use Friendica\Model\Item; require_once 'include/security.php'; require_once 'include/items.php'; -function poke_init(App $a) { - +function poke_init(App $a) +{ if (!local_user()) { return; } $uid = local_user(); - $verb = notags(trim($_GET['verb'])); - if (!$verb) { + if (empty($_GET['verb'])) { return; } + $verb = notags(trim($_GET['verb'])); + $verbs = get_poke_verbs(); if (!array_key_exists($verb, $verbs)) { @@ -99,7 +100,7 @@ function poke_init(App $a) { $arr['guid'] = System::createGUID(32); $arr['uid'] = $uid; $arr['uri'] = $uri; - $arr['parent-uri'] = ($parent_uri ? $parent_uri : $uri); + $arr['parent-uri'] = (!empty($parent_uri) ? $parent_uri : $uri); $arr['wall'] = 1; $arr['contact-id'] = $poster['id']; $arr['owner-name'] = $poster['name']; @@ -121,7 +122,7 @@ function poke_init(App $a) { $arr['origin'] = 1; $arr['body'] = '[url=' . $poster['url'] . ']' . $poster['name'] . '[/url]' . ' ' . L10n::t($verbs[$verb][0]) . ' ' . '[url=' . $target['url'] . ']' . $target['name'] . '[/url]'; - $arr['object'] = '' . ACTIVITY_OBJ_PERSON . '' . $target['name'] . '' . System::baseUrl() . '/contact/' . $target['id'] . ''; + $arr['object'] = '' . ACTIVITY_OBJ_PERSON . '' . $target['name'] . '' . $target['url'] . ''; $arr['object'] .= '' . xmlify('' . "\n"); $arr['object'] .= xmlify('' . "\n"); @@ -137,10 +138,8 @@ function poke_init(App $a) { return; } - - -function poke_content(App $a) { - +function poke_content(App $a) +{ if (!local_user()) { notice(L10n::t('Permission denied.') . EOL); return; @@ -149,17 +148,17 @@ function poke_content(App $a) { $name = ''; $id = ''; - if (intval($_GET['c'])) { - $r = q("SELECT `id`,`name` FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", - intval($_GET['c']), - intval(local_user()) - ); - if (DBA::isResult($r)) { - $name = $item['name']; - $id = $item['id']; - } + if (empty($_GET['c'])) { + return; } + $contact = DBA::selectFirst('contact', ['id', 'name'], ['id' => $_GET['c'], 'uid' => local_user()]); + if (!DBA::isResult($contact)) { + return; + } + + $name = $contact['name']; + $id = $contact['id']; $base = System::baseUrl(); From d489712824a8f3fe9840ae793a2be16149afcfcb Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 29 Aug 2018 11:48:40 +0000 Subject: [PATCH 002/428] The post update version can now be set. --- src/Core/Console/PostUpdate.php | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Core/Console/PostUpdate.php b/src/Core/Console/PostUpdate.php index 97c19b0c1e..2ae640d483 100644 --- a/src/Core/Console/PostUpdate.php +++ b/src/Core/Console/PostUpdate.php @@ -3,6 +3,7 @@ namespace Friendica\Core\Console; use Friendica\Core\L10n; +use Friendica\Core\Config; /** * @brief tool to block an account from the node @@ -17,12 +18,39 @@ use Friendica\Core\L10n; */ class PostUpdate extends \Asika\SimpleConsole\Console { + protected $helpOptions = ['h', 'help', '?']; + + protected function getHelp() + { + $help = <<] + +Options + -h|--help|-? Show help information + --reset Reset the post update version +HELP; + return $help; + } + protected function doExecute() { $a = get_app(); - if (count($this->args) > 0) { - throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); + if ($this->getOption($this->helpOptions)) { + $this->out($this->getHelp()); + return 0; + } + + $reset_version = $this->getOption('reset'); + if (is_bool($reset_version)) { + $this->out($this->getHelp()); + return 0; + } elseif ($reset_version) { + Config::set('system', 'post_update_version', $reset_version); + echo L10n::t('Post update version number has been set to %s.', $reset_version) . "\n"; + return 0; } if ($a->isInstallMode()) { From 601851f3d0b5439f75c6e984733e850c7beed40c Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Wed, 29 Aug 2018 13:00:01 +0000 Subject: [PATCH 003/428] Removed notice - pokes do now work mostly (#5693) --- include/conversation.php | 3 ++- src/Protocol/DFRN.php | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/conversation.php b/include/conversation.php index f10c79d4be..45e5d1caa3 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -231,8 +231,9 @@ function localize_item(&$item) $obj = XML::parseString($xmlhead.$item['object']); $Bname = $obj->title; - $Blink = ""; + $Blink = $obj->id; $Bphoto = ""; + foreach ($obj->link as $l) { $atts = $l->attributes(); switch ($atts['rel']) { diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 0b228b045b..759f7f5f28 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -2252,6 +2252,11 @@ class DFRN if ($Blink && link_compare($Blink, System::baseUrl() . "/profile/" . $importer["nickname"])) { $author = DBA::selectFirst('contact', ['name', 'thumb', 'url'], ['id' => $item['author-id']]); + $item['id'] = $posted_id; + + $parent = Item::selectFirst(['id'], ['uri' => $item['parent-uri'], 'uid' => $importer["importer_uid"]]); + $item["parent"] = $parent['id']; + // send a notification notification( [ From 67227570d8e9e769fdc5c0383cf56b207372302c Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 29 Aug 2018 13:06:56 +0000 Subject: [PATCH 004/428] "Does" is now "perform" --- src/Core/Console/DatabaseStructure.php | 4 ++-- src/Core/Console/PostUpdate.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Core/Console/DatabaseStructure.php b/src/Core/Console/DatabaseStructure.php index 1b64622dbf..13ed29b9df 100644 --- a/src/Core/Console/DatabaseStructure.php +++ b/src/Core/Console/DatabaseStructure.php @@ -11,7 +11,7 @@ require_once 'boot.php'; require_once 'include/dba.php'; /** - * @brief Does database updates from the command line + * @brief Performs database updates from the command line * * @author Hypolite Petovan */ @@ -22,7 +22,7 @@ class DatabaseStructure extends \Asika\SimpleConsole\Console protected function getHelp() { $help = << [-h|--help|-?] [-v] diff --git a/src/Core/Console/PostUpdate.php b/src/Core/Console/PostUpdate.php index 2ae640d483..3162a725c0 100644 --- a/src/Core/Console/PostUpdate.php +++ b/src/Core/Console/PostUpdate.php @@ -23,7 +23,7 @@ class PostUpdate extends \Asika\SimpleConsole\Console protected function getHelp() { $help = <<] From c7f8f190b9f14c28fe811a2f244534027344e7cc Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Wed, 29 Aug 2018 18:28:13 +0000 Subject: [PATCH 005/428] Oh no, even more notices ... (#5697) --- mod/videos.php | 3 ++- src/Model/User.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mod/videos.php b/mod/videos.php index e622e17f0f..e00df10a24 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -367,11 +367,12 @@ function videos_content(App $a) foreach ($r as $rr) { $alt_e = $rr['filename']; /// @todo The album isn't part of the above query. This seems to be some unfinished code that needs to be reworked completely. + $rr['album'] = ''; $name_e = $rr['album']; $videos[] = [ 'id' => $rr['id'], - 'link' => System::baseUrl() . '/videos/' . $a->data['user']['nickname'] . '/video/' . $rr['resource-id'], + 'link' => System::baseUrl() . '/videos/' . $a->data['user']['nickname'] . '/video/' . $rr['hash'], 'title' => L10n::t('View Video'), 'src' => System::baseUrl() . '/attach/' . $rr['id'] . '?attachment=0', 'alt' => $alt_e, diff --git a/src/Model/User.php b/src/Model/User.php index a43ef06f97..d65e7d8f96 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -730,7 +730,7 @@ class User DBA::insert('userd', ['username' => $user['nickname']]); // The user and related data will be deleted in "cron_expire_and_remove_users" (cronjobs.php) - DBA::update('user', ['account_removed' => true, 'account_expires_on' => DateTimeFormat::utc($t . " + 7 day")], ['uid' => $uid]); + DBA::update('user', ['account_removed' => true, 'account_expires_on' => DateTimeFormat::utc(DateTimeFormat::utcNow() . " + 7 day")], ['uid' => $uid]); Worker::add(PRIORITY_HIGH, "Notifier", "removeme", $uid); // Send an update to the directory From b8e8b771d4ead88ae08b062fa9fce9352ba3b5b4 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 29 Aug 2018 18:52:48 +0000 Subject: [PATCH 006/428] Issue 5696: Removed old forum link --- doc/Developers-Intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Developers-Intro.md b/doc/Developers-Intro.md index 1e077902d6..5deaf98ff0 100644 --- a/doc/Developers-Intro.md +++ b/doc/Developers-Intro.md @@ -33,7 +33,7 @@ If you don't want to translate the UI, or it is already done to your satisfactio Are you good at designing things? If you have seen Friendica you probably have ideas to improve it, haven't you? -* If you would like to work with us on enhancing the user interface, please join the [UX Watchdogs forum](https://fc.oscp.info/profile/ux-watchdogs) +* If you would like to work with us on enhancing the user interface, please join the [forum for Friendica development](https://forum.friendi.ca/profile/developers). * Make plans for a better Friendica interface design and share them with us. * Tell us if you are able to realize your ideas or what kind of help you need. We can't promise we have the right skills in the group but we'll try. From 9bff31f18f35acba405724f0dacdf20b0c6e8ba4 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 29 Aug 2018 19:11:43 +0000 Subject: [PATCH 007/428] Issue 5691: Post dates of feeds sometimes had been wrong --- src/Protocol/Feed.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php index c9c750a83f..0709a9550e 100644 --- a/src/Protocol/Feed.php +++ b/src/Protocol/Feed.php @@ -271,9 +271,14 @@ class Feed { } $updated = XML::getFirstNodeValue($xpath, 'atom:updated/text()', $entry); - if (empty($updated)) { + if (empty($updated) && !empty($published)) { $updated = $published; } + + if (empty($published) && !empty($updated)) { + $published = $updated; + } + if ($published != "") { $item["created"] = $published; } From c72d1bc8fda4f1088657885fbb47d128a9f4bcad Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 29 Aug 2018 20:46:52 +0000 Subject: [PATCH 008/428] Issue 5653: The mastodonemoji addon hadn't got all needed data. --- src/Model/Item.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index d235f0a7f9..d10a211a59 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1462,15 +1462,6 @@ class Item extends BaseObject return 0; } - // These fields aren't stored anymore in the item table, they are fetched upon request - unset($item['author-link']); - unset($item['author-name']); - unset($item['author-avatar']); - - unset($item['owner-link']); - unset($item['owner-name']); - unset($item['owner-avatar']); - if ($item['network'] == Protocol::PHANTOM) { logger('Missing network. Called by: '.System::callstack(), LOGGER_DEBUG); @@ -1708,6 +1699,15 @@ class Item extends BaseObject unset($item['postopts']); unset($item['inform']); + // These fields aren't stored anymore in the item table, they are fetched upon request + unset($item['author-link']); + unset($item['author-name']); + unset($item['author-avatar']); + + unset($item['owner-link']); + unset($item['owner-name']); + unset($item['owner-avatar']); + DBA::transaction(); $ret = DBA::insert('item', $item); From 02da8275602ab7b360ebfab8e0e2072d2c39aa42 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 30 Aug 2018 04:05:32 +0000 Subject: [PATCH 009/428] and now for something completely different: A removed notice --- src/Protocol/OStatus.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index 7052205e17..551b4ad887 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -351,7 +351,7 @@ class OStatus $header["origin"] = 0; $header["gravity"] = GRAVITY_COMMENT; - if (!is_object($doc->firstChild)) { + if (!is_object($doc->firstChild) || empty($doc->firstChild->tagName)) { return false; } From a3570d00273b974270620ccbd5e080d628f422ec Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 30 Aug 2018 09:52:38 +0000 Subject: [PATCH 010/428] Fix: Missing gserver entries - show correct server platform --- src/Model/Contact.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 3e70a5cbde..d53126f6ff 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1076,6 +1076,11 @@ class Contact extends BaseObject if (empty($data)) { $data = Probe::uri($url, "", $uid); + + // Ensure that there is a gserver entry + if (!empty($data['baseurl']) && ($data['network'] != Protocol::PHANTOM)) { + PortableContact::checkServer($data['baseurl']); + } } // Last try in gcontact for unsupported networks From e480da788e7d44f0704441f8879c5ff93d98eaf0 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 30 Aug 2018 08:27:31 -0400 Subject: [PATCH 011/428] Fix unfollow for sharing-only contacts - Add removal when unfollowing sharing-only contacts --- mod/unfollow.php | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/mod/unfollow.php b/mod/unfollow.php index 5c00726e27..5942171247 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -27,29 +27,37 @@ function unfollow_post(App $a) $url = notags(trim($_REQUEST['url'])); $return_url = $_SESSION['return_url']; - $condition = ["`uid` = ? AND `rel` = ? AND (`nurl` = ? OR `alias` = ? OR `alias` = ?) AND `network` != ?", - $uid, Contact::FRIEND, normalise_link($url), + $condition = ["`uid` = ? AND (`rel` = ? OR `rel` = ?) AND (`nurl` = ? OR `alias` = ? OR `alias` = ?) AND `network` != ?", + $uid, Contact::SHARING, Contact::FRIEND, normalise_link($url), normalise_link($url), $url, Protocol::STATUSNET]; $contact = DBA::selectFirst('contact', [], $condition); if (!DBA::isResult($contact)) { notice(L10n::t("Contact wasn't found or can't be unfollowed.")); - } else { - if (in_array($contact['network'], [Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN])) { - $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` - WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1", - intval($uid) - ); - if (DBA::isResult($r)) { - Contact::terminateFriendship($r[0], $contact); - } - } - DBA::update('contact', ['rel' => Contact::FOLLOWER], ['id' => $contact['id']]); - - info(L10n::t('Contact unfollowed').EOL); - goaway(System::baseUrl().'/contacts/'.$contact['id']); + goaway($return_url); } - goaway($return_url); + + if (in_array($contact['network'], [Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN])) { + $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` + WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1", + intval($uid) + ); + if (DBA::isResult($r)) { + Contact::terminateFriendship($r[0], $contact); + } + } + + // Sharing-only contacts get deleted as there no relationship any more + if ($contact['rel'] == Contact::SHARING) { + Contact::remove($contact['id']); + $return_path = 'contacts'; + } else { + DBA::update('contact', ['rel' => Contact::FOLLOWER], ['id' => $contact['id']]); + $return_path = 'contacts/' . $contact['id']; + } + + info(L10n::t('Contact unfollowed')); + goaway($return_path); // NOTREACHED } @@ -66,8 +74,8 @@ function unfollow_content(App $a) $submit = L10n::t('Submit Request'); - $condition = ["`uid` = ? AND `rel` = ? AND (`nurl` = ? OR `alias` = ? OR `alias` = ?) AND `network` != ?", - local_user(), Contact::FRIEND, normalise_link($url), + $condition = ["`uid` = ? AND (`rel` = ? OR `rel` = ?) AND (`nurl` = ? OR `alias` = ? OR `alias` = ?) AND `network` != ?", + local_user(), Contact::SHARING, Contact::FRIEND, normalise_link($url), normalise_link($url), $url, Protocol::STATUSNET]; $contact = DBA::selectFirst('contact', ['url', 'network', 'addr', 'name'], $condition); From b81eaec88576dbbfa5f447df18a36a1866d19a1d Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 30 Aug 2018 08:52:15 -0400 Subject: [PATCH 012/428] Enable unfollowing contacts from all networks (but Statusnet) --- mod/contacts.php | 2 +- mod/unfollow.php | 29 ++++++++++++++++++----------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/mod/contacts.php b/mod/contacts.php index 4e87697172..38896a611a 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -595,7 +595,7 @@ function contacts_content(App $a, $update = 0) /// @todo Only show the following link with DFRN when the remote version supports it $follow = ''; $follow_text = ''; - if (in_array($contact['network'], [Protocol::DIASPORA, Protocol::OSTATUS, Protocol::DFRN])) { + if ($contact['network'] != Protocol::STATUSNET) { if (in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) { $follow = System::baseUrl(true) . "/unfollow?url=" . urlencode($contact["url"]); $follow_text = L10n::t("Disconnect/Unfollow"); diff --git a/mod/unfollow.php b/mod/unfollow.php index 5942171247..4bc64e4fc3 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -28,13 +28,20 @@ function unfollow_post(App $a) $return_url = $_SESSION['return_url']; $condition = ["`uid` = ? AND (`rel` = ? OR `rel` = ?) AND (`nurl` = ? OR `alias` = ? OR `alias` = ?) AND `network` != ?", - $uid, Contact::SHARING, Contact::FRIEND, normalise_link($url), - normalise_link($url), $url, Protocol::STATUSNET]; + $uid, Contact::SHARING, Contact::FRIEND, normalise_link($url), + normalise_link($url), $url]; $contact = DBA::selectFirst('contact', [], $condition); if (!DBA::isResult($contact)) { - notice(L10n::t("Contact wasn't found or can't be unfollowed.")); + notice(L10n::t("You aren't following this contact.")); goaway($return_url); + // NOTREACHED + } + + if ($contact['network'] == Protocol::STATUSNET) { + notice(L10n::t('Unfollowing is currently not supported by your network.')); + goaway($return_url); + // NOTREACHED } if (in_array($contact['network'], [Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN])) { @@ -74,21 +81,21 @@ function unfollow_content(App $a) $submit = L10n::t('Submit Request'); - $condition = ["`uid` = ? AND (`rel` = ? OR `rel` = ?) AND (`nurl` = ? OR `alias` = ? OR `alias` = ?) AND `network` != ?", - local_user(), Contact::SHARING, Contact::FRIEND, normalise_link($url), - normalise_link($url), $url, Protocol::STATUSNET]; + $condition = ["`uid` = ? AND (`rel` = ? OR `rel` = ?) AND (`nurl` = ? OR `alias` = ? OR `alias` = ?)", + local_user(), Contact::SHARING, Contact::FRIEND, normalise_link($url), + normalise_link($url), $url]; $contact = DBA::selectFirst('contact', ['url', 'network', 'addr', 'name'], $condition); if (!DBA::isResult($contact)) { - notice(L10n::t("You aren't a friend of this contact.").EOL); - $submit = ""; + notice(L10n::t("You aren't following this contact.")); + goaway('contacts'); // NOTREACHED } - if (!in_array($contact['network'], [Protocol::DIASPORA, Protocol::OSTATUS, Protocol::DFRN])) { - notice(L10n::t("Unfollowing is currently not supported by your network.").EOL); - $submit = ""; + if ($contact['network'] == Protocol::STATUSNET) { + notice(L10n::t('Unfollowing is currently not supported by your network.')); + goaway('contacts/' . $contact['id']); // NOTREACHED } From 55c676d8b0074bf534049cd54dd1eae646a6c590 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 30 Aug 2018 08:54:12 -0400 Subject: [PATCH 013/428] Source cleaning mod/unfollow.php - Normalize quotes - Remove unneeded EOL - Use DBA method where tasteful --- mod/unfollow.php | 89 +++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/mod/unfollow.php b/mod/unfollow.php index 4bc64e4fc3..f82796a6b7 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -11,21 +11,22 @@ use Friendica\Database\DBA; use Friendica\Model\Contact; use Friendica\Model\Profile; -function unfollow_post(App $a) +function unfollow_post() { + $return_url = $_SESSION['return_url']; + if (!local_user()) { - notice(L10n::t('Permission denied.') . EOL); - goaway($_SESSION['return_url']); + notice(L10n::t('Permission denied.')); + goaway($return_url); // NOTREACHED } if ($_REQUEST['cancel']) { - goaway($_SESSION['return_url']); + goaway($return_url); } $uid = local_user(); - $url = notags(trim($_REQUEST['url'])); - $return_url = $_SESSION['return_url']; + $url = notags(trim(defaults($_REQUEST, 'url', ''))); $condition = ["`uid` = ? AND (`rel` = ? OR `rel` = ?) AND (`nurl` = ? OR `alias` = ? OR `alias` = ?) AND `network` != ?", $uid, Contact::SHARING, Contact::FRIEND, normalise_link($url), @@ -70,8 +71,8 @@ function unfollow_post(App $a) function unfollow_content(App $a) { - if (! local_user()) { - notice(L10n::t('Permission denied.') . EOL); + if (!local_user()) { + notice(L10n::t('Permission denied.')); goaway($_SESSION['return_url']); // NOTREACHED } @@ -79,8 +80,6 @@ function unfollow_content(App $a) $uid = local_user(); $url = notags(trim($_REQUEST['url'])); - $submit = L10n::t('Submit Request'); - $condition = ["`uid` = ? AND (`rel` = ? OR `rel` = ?) AND (`nurl` = ? OR `alias` = ? OR `alias` = ?)", local_user(), Contact::SHARING, Contact::FRIEND, normalise_link($url), normalise_link($url), $url]; @@ -99,58 +98,56 @@ function unfollow_content(App $a) // NOTREACHED } - $request = System::baseUrl()."/unfollow"; + $request = System::baseUrl() . '/unfollow'; $tpl = get_markup_template('auto_request.tpl'); - $r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1", intval($uid)); + $self = DBA::selectFirst('contact', ['url'], ['uid' => $uid, 'self' => true]); - if (!$r) { - notice(L10n::t('Permission denied.') . EOL); + if (!DBA::isResult($self)) { + notice(L10n::t('Permission denied.')); goaway($_SESSION['return_url']); // NOTREACHED } - $myaddr = $r[0]["url"]; - // Makes the connection request for friendica contacts easier - $_SESSION["fastlane"] = $contact["url"]; + $_SESSION['fastlane'] = $contact['url']; - $header = L10n::t("Disconnect/Unfollow"); + $header = L10n::t('Disconnect/Unfollow'); - $o = replace_macros($tpl, [ - '$header' => htmlentities($header), - '$desc' => "", - '$pls_answer' => "", - '$does_know_you' => "", - '$add_note' => "", - '$page_desc' => "", - '$friendica' => "", - '$statusnet' => "", - '$diaspora' => "", - '$diasnote' => "", - '$your_address' => L10n::t('Your Identity Address:'), - '$invite_desc' => "", - '$emailnet' => "", - '$submit' => $submit, - '$cancel' => L10n::t('Cancel'), - '$nickname' => "", - '$name' => $contact["name"], - '$url' => $contact["url"], - '$zrl' => Contact::magicLink($contact["url"]), - '$url_label' => L10n::t("Profile URL"), - '$myaddr' => $myaddr, - '$request' => $request, - '$keywords' => "", - '$keywords_label' => "" + $o = replace_macros($tpl, [ + '$header' => htmlentities($header), + '$desc' => '', + '$pls_answer' => '', + '$does_know_you' => '', + '$add_note' => '', + '$page_desc' => '', + '$friendica' => '', + '$statusnet' => '', + '$diaspora' => '', + '$diasnote' => '', + '$your_address' => L10n::t('Your Identity Address:'), + '$invite_desc' => '', + '$emailnet' => '', + '$submit' => L10n::t('Submit Request'), + '$cancel' => L10n::t('Cancel'), + '$nickname' => '', + '$name' => $contact['name'], + '$url' => $contact['url'], + '$zrl' => Contact::magicLink($contact['url']), + '$url_label' => L10n::t('Profile URL'), + '$myaddr' => $self['url'], + '$request' => $request, + '$keywords' => '', + '$keywords_label'=> '' ]); - $a->page['aside'] = ""; - Profile::load($a, "", 0, Contact::getDetailsByURL($contact["url"])); + $a->page['aside'] = ''; + Profile::load($a, '', 0, Contact::getDetailsByURL($contact['url'])); $o .= replace_macros(get_markup_template('section_title.tpl'), ['$title' => L10n::t('Status Messages and Posts')]); // Show last public posts - $o .= Contact::getPostsFromUrl($contact["url"]); + $o .= Contact::getPostsFromUrl($contact['url']); return $o; } From 804cfa03200456116db0c96b7f2ae6e3b7bdbfd8 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 30 Aug 2018 17:47:48 -0400 Subject: [PATCH 014/428] Reorganize Protocol constants - Add ActivityPub protocol constant - Add Protocol::NATIVE_SUPPORT - Sort/group constant names --- src/Core/Protocol.php | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/src/Core/Protocol.php b/src/Core/Protocol.php index 4467bf0027..9e96b7db2f 100644 --- a/src/Core/Protocol.php +++ b/src/Core/Protocol.php @@ -13,27 +13,33 @@ use Friendica\Util\Network; */ class Protocol { - const DFRN = 'dfrn'; // Friendica, Mistpark, other DFRN implementations - const DIASPORA = 'dspr'; // Diaspora - const DIASPORA2 = 'dspc'; // Diaspora connector - const STATUSNET = 'stac'; // Statusnet connector - const OSTATUS = 'stat'; // GNU-social, Pleroma, Mastodon, other OStatus implementations - const FEED = 'feed'; // RSS/Atom feeds with no known "post/notify" protocol - const MAIL = 'mail'; // IMAP/POP - const XMPP = 'xmpp'; // XMPP - Currently unsupported + // Native support + const ACTIVITYPUB = 'apub'; // ActivityPub + const DFRN = 'dfrn'; // Friendica, Mistpark, other DFRN implementations + const DIASPORA = 'dspr'; // Diaspora + const FEED = 'feed'; // RSS/Atom feeds with no known "post/notify" protocol + const MAIL = 'mail'; // IMAP/POP + const OSTATUS = 'stat'; // GNU-social, Pleroma, Mastodon, other OStatus implementations - const FACEBOOK = 'face'; // Facebook API - const LINKEDIN = 'lnkd'; // LinkedIn - const MYSPACE = 'mysp'; // MySpace - Currently unsupported - const GPLUS = 'goog'; // Google+ - const PUMPIO = 'pump'; // pump.io - const TWITTER = 'twit'; // Twitter + const NATIVE_SUPPORT = [self::DFRN, self::DIASPORA, self::OSTATUS, self::FEED, self::MAIL, self::ACTIVITYPUB]; + + // Supported through a connector const APPNET = 'apdn'; // app.net - Dead protocol + const DIASPORA2 = 'dspc'; // Diaspora connector + const FACEBOOK = 'face'; // Facebook API + const GPLUS = 'goog'; // Google+ + const LINKEDIN = 'lnkd'; // LinkedIn + const PUMPIO = 'pump'; // pump.io + const STATUSNET = 'stac'; // Statusnet connector + const TWITTER = 'twit'; // Twitter - const NEWS = 'nntp'; // Network News Transfer Protocol - Currently unsupported - const ICALENDAR = 'ical'; // iCalendar - Currently unsupported - const PNUT = 'pnut'; // pnut.io - Currently unsupported - const ZOT = 'zot!'; // Zot! - Currently unsupported + // Currently unsupported + const ICALENDAR = 'ical'; // iCalendar + const MYSPACE = 'mysp'; // MySpace + const NEWS = 'nntp'; // Network News Transfer Protocol + const PNUT = 'pnut'; // pnut.io + const XMPP = 'xmpp'; // XMPP + const ZOT = 'zot!'; // Zot! const PHANTOM = 'unkn'; // Place holder From 92c4ca091193e571d76a9db7b2d4078e2b3dc473 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 30 Aug 2018 17:53:23 -0400 Subject: [PATCH 015/428] Prevent unfollowing contacts from networks not supported natively --- mod/unfollow.php | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/mod/unfollow.php b/mod/unfollow.php index f82796a6b7..30aca5688e 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -39,20 +39,18 @@ function unfollow_post() // NOTREACHED } - if ($contact['network'] == Protocol::STATUSNET) { + if (!in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { notice(L10n::t('Unfollowing is currently not supported by your network.')); goaway($return_url); // NOTREACHED } - if (in_array($contact['network'], [Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN])) { - $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` - WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1", - intval($uid) - ); - if (DBA::isResult($r)) { - Contact::terminateFriendship($r[0], $contact); - } + $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` + WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1", + intval($uid) + ); + if (DBA::isResult($r)) { + Contact::terminateFriendship($r[0], $contact); } // Sharing-only contacts get deleted as there no relationship any more @@ -92,7 +90,7 @@ function unfollow_content(App $a) // NOTREACHED } - if ($contact['network'] == Protocol::STATUSNET) { + if (!in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { notice(L10n::t('Unfollowing is currently not supported by your network.')); goaway('contacts/' . $contact['id']); // NOTREACHED From e25c579c76b0721b06c477f82356cc2e824ce53a Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 30 Aug 2018 21:03:57 -0400 Subject: [PATCH 016/428] Add Protocol::NATIVE_SUPPORT constant usage to mod/contacts --- mod/contacts.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/mod/contacts.php b/mod/contacts.php index 38896a611a..227a48b965 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -595,17 +595,12 @@ function contacts_content(App $a, $update = 0) /// @todo Only show the following link with DFRN when the remote version supports it $follow = ''; $follow_text = ''; - if ($contact['network'] != Protocol::STATUSNET) { - if (in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) { + if (in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) { + if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { $follow = System::baseUrl(true) . "/unfollow?url=" . urlencode($contact["url"]); $follow_text = L10n::t("Disconnect/Unfollow"); - } else { - $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]); - $follow_text = L10n::t("Connect/Follow"); } - } - - if ($contact['uid'] == 0) { + } else { $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]); $follow_text = L10n::t("Connect/Follow"); } From 380eeaab88febb7f76e69bb6cdf4b44bf2618f13 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 31 Aug 2018 05:08:22 +0000 Subject: [PATCH 017/428] Still there had been notices - must have a good camouflage --- mod/contacts.php | 5 +++-- src/Module/Proxy.php | 4 ++++ src/Object/Image.php | 2 +- src/Protocol/DFRN.php | 5 ++++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/mod/contacts.php b/mod/contacts.php index 4e87697172..cfe968226d 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -122,11 +122,12 @@ function contacts_init(App $a) function contacts_batch_actions(App $a) { - $contacts_id = $_POST['contact_batch']; - if (!is_array($contacts_id)) { + if (empty($_POST['contact_batch']) || !is_array($_POST['contact_batch'])) { return; } + $contacts_id = $_POST['contact_batch']; + $orig_records = q("SELECT * FROM `contact` WHERE `id` IN (%s) AND `uid` = %d AND `self` = 0", implode(",", $contacts_id), intval(local_user()) diff --git a/src/Module/Proxy.php b/src/Module/Proxy.php index ccd00c6040..7983e01f7a 100644 --- a/src/Module/Proxy.php +++ b/src/Module/Proxy.php @@ -133,6 +133,10 @@ class Proxy extends BaseModule $direct_cache = false; } + if (empty($_REQUEST['url'])) { + System::httpExit(400, ["title" => L10n::t('Bad Request.')]); + } + if (!$direct_cache) { $urlhash = 'pic:' . sha1($_REQUEST['url']); diff --git a/src/Object/Image.php b/src/Object/Image.php index 9506aedc22..620929df51 100644 --- a/src/Object/Image.php +++ b/src/Object/Image.php @@ -792,7 +792,7 @@ class Image try { if (function_exists("getimagesizefromstring")) { - $data = getimagesizefromstring($img_str); + $data = @getimagesizefromstring($img_str); } else { $tempfile = tempnam(get_temppath(), "cache"); diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 759f7f5f28..c435550313 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -2407,8 +2407,11 @@ class DFRN break; case "enclosure": $enclosure = $href; - if (strlen($item["attach"])) { + + if (!empty($item["attach"])) { $item["attach"] .= ","; + } else { + $item["attach"] = ""; } $item["attach"] .= '[attach]href="' . $href . '" length="' . $length . '" type="' . $type . '" title="' . $title . '"[/attach]'; From 38fd21019be46189ac7cccadca0159f6a34c56c0 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 31 Aug 2018 07:48:44 +0000 Subject: [PATCH 018/428] Invalid pictures could lead to notices, this is removed now --- include/items.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/items.php b/include/items.php index 2d7597dcd6..9fd557a778 100644 --- a/include/items.php +++ b/include/items.php @@ -72,7 +72,8 @@ function add_page_info_data(array $data, $no_photos = false) $text .= " title='".$data["title"]."'"; } - if (!empty($data["images"])) { + // Only embedd a picture link when it seems to be a valid picture ("width" is set) + if (!empty($data["images"]) && !empty($data["images"][0]["width"])) { $preview = str_replace(["[", "]"], ["[", "]"], htmlentities($data["images"][0]["src"], ENT_QUOTES, 'UTF-8', false)); // if the preview picture is larger than 500 pixels then show it in a larger mode // But only, if the picture isn't higher than large (To prevent huge posts) From 76b40cf05ec201811aedb22df0217bd027ebcbd1 Mon Sep 17 00:00:00 2001 From: Benjamin Lorteau Date: Fri, 31 Aug 2018 11:22:51 -0400 Subject: [PATCH 019/428] Use User::getOwnerDataById in mod/unfollow --- mod/unfollow.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/mod/unfollow.php b/mod/unfollow.php index 30aca5688e..0af16ec671 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -10,6 +10,7 @@ use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model\Contact; use Friendica\Model\Profile; +use Friendica\Model\User; function unfollow_post() { @@ -45,12 +46,9 @@ function unfollow_post() // NOTREACHED } - $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` - WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1", - intval($uid) - ); - if (DBA::isResult($r)) { - Contact::terminateFriendship($r[0], $contact); + $owner = User::getOwnerDataById($uid); + if ($owner) { + Contact::terminateFriendship($owner, $contact); } // Sharing-only contacts get deleted as there no relationship any more From 4fcae18289aecfd9bd4abd2df15381eaf64403ca Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 1 Sep 2018 03:23:12 +0000 Subject: [PATCH 020/428] Issue 5262: Comments to a forum post aren't distributed via push --- src/Worker/Notifier.php | 45 +++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index 401178ec26..6d2733b8ee 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -217,24 +217,16 @@ class Notifier } // Special treatment for forum posts - if (($target_item['author-id'] != $target_item['owner-id']) && - ($owner['id'] != $target_item['contact-id']) && - ($target_item['uri'] === $target_item['parent-uri'])) { - - $fields = ['forum', 'prv']; - $condition = ['id' => $target_item['contact-id']]; - $contact = DBA::selectFirst('contact', $fields, $condition); - if (!DBA::isResult($contact)) { - // Should never happen - return false; - } - - // Is the post from a forum? - if ($contact['forum'] || $contact['prv']) { - $relay_to_owner = true; - $direct_forum_delivery = true; - } + if (self::isForumPost($target_item, $owner)) { + $relay_to_owner = true; + $direct_forum_delivery = true; } + + // Avoid that comments in a forum thread are sent to OStatus + if (self::isForumPost($parent, $owner)) { + $direct_forum_delivery = true; + } + if ($relay_to_owner) { // local followup to remote post $followup = true; @@ -504,4 +496,23 @@ class Notifier return; } + + private static function isForumPost($item, $owner) { + if (($item['author-id'] == $item['owner-id']) || + ($owner['id'] == $item['contact-id']) || + ($item['uri'] != $item['parent-uri'])) { + return false; + } + + $fields = ['forum', 'prv']; + $condition = ['id' => $item['contact-id']]; + $contact = DBA::selectFirst('contact', $fields, $condition); + if (!DBA::isResult($contact)) { + // Should never happen + return false; + } + + // Is the post from a forum? + return ($contact['forum'] || $contact['prv']); + } } From 4bb45f611f1a43294859dae1c81bf0aff923cf20 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 2 Sep 2018 07:20:04 +0000 Subject: [PATCH 021/428] Fix for timeout issues when posting to the API --- include/api.php | 38 +++++++++++++++++++++----------------- mod/item.php | 10 +++++++--- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/include/api.php b/include/api.php index f40674b894..18027c2434 100644 --- a/include/api.php +++ b/include/api.php @@ -1056,10 +1056,10 @@ function api_statuses_mediap($type) // now that we have the img url in bbcode we can add it to the status and insert the wall item. $_REQUEST['body'] = $txt . "\n\n" . '[url=' . $picture["albumpage"] . '][img]' . $picture["preview"] . "[/img][/url]"; - item_post($a); + $item_id = item_post($a); - // this should output the last post (the one we just posted). - return api_status_show($type); + // output the post that we just posted. + return api_status_show($type, $item_id); } /// @TODO move this to top of file or somewhere better! @@ -1075,7 +1075,6 @@ api_register_func('api/statuses/mediap', 'api_statuses_mediap', true, API_METHOD */ function api_statuses_update($type) { - $a = get_app(); if (api_user() === false) { @@ -1129,7 +1128,7 @@ function api_statuses_update($type) if ($throttle_day > 0) { $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60); - $condition = ["`uid` = ? AND `wall` AND `created` > ? AND `id` = `parent`", api_user(), $datefrom]; + $condition = ["`uid` = ? AND `wall` AND `changed` > ? AND `gravity` = ?", api_user(), $datefrom, GRAVITY_PARENT]; $posts_day = DBA::count('item', $condition); if ($posts_day > $throttle_day) { @@ -1143,7 +1142,7 @@ function api_statuses_update($type) if ($throttle_week > 0) { $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*7); - $condition = ["`uid` = ? AND `wall` AND `created` > ? AND `id` = `parent`", api_user(), $datefrom]; + $condition = ["`uid` = ? AND `wall` AND `changed` > ? AND `gravity` = ?", api_user(), $datefrom, GRAVITY_PARENT]; $posts_week = DBA::count('item', $condition); if ($posts_week > $throttle_week) { @@ -1157,7 +1156,7 @@ function api_statuses_update($type) if ($throttle_month > 0) { $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*30); - $condition = ["`uid` = ? AND `wall` AND `created` > ? AND `id` = `parent`", api_user(), $datefrom]; + $condition = ["`uid` = ? AND `wall` AND `changed` > ? AND `gravity` = ?", api_user(), $datefrom, GRAVITY_PARENT]; $posts_month = DBA::count('item', $condition); if ($posts_month > $throttle_month) { @@ -1200,10 +1199,10 @@ function api_statuses_update($type) } // call out normal post function - item_post($a); + $item_id = item_post($a); - // this should output the last post (the one we just posted). - return api_status_show($type); + // output the post that we just posted. + return api_status_show($type, $item_id); } /// @TODO move to top of file or somewhere better @@ -1260,7 +1259,7 @@ api_register_func('api/media/upload', 'api_media_upload', true, API_METHOD_POST) * * @return array|string */ -function api_status_show($type) +function api_status_show($type, $item_id = 0) { $a = get_app(); @@ -1274,9 +1273,14 @@ function api_status_show($type) $privacy_sql = ""; } - // get last public wall message - $condition = ['owner-id' => $user_info['pid'], 'uid' => api_user(), - 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]]; + if (!empty($item_id)) { + // Get the item with the given id + $condition = ['id' => $item_id]; + } else { + // get last public wall message + $condition = ['owner-id' => $user_info['pid'], 'uid' => api_user(), + 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]]; + } $lastwall = Item::selectFirst(Item::ITEM_FIELDLIST, $condition, ['order' => ['id' => true]]); if (DBA::isResult($lastwall)) { @@ -1993,14 +1997,14 @@ function api_statuses_repeat($type) $_REQUEST["source"] = api_source(); } - item_post($a); + $item_id = item_post($a); } else { throw new ForbiddenException(); } - // this should output the last post (the one we just posted). + // output the last post tha we just posted. $called_api = []; - return api_status_show($type); + return api_status_show($type, $item_id); } /// @TODO move to top of file or somewhere better diff --git a/mod/item.php b/mod/item.php index 733c6aee85..213a990789 100644 --- a/mod/item.php +++ b/mod/item.php @@ -39,7 +39,7 @@ require_once 'include/items.php'; function item_post(App $a) { if (!local_user() && !remote_user()) { - return; + return 0; } require_once 'include/security.php'; @@ -154,7 +154,7 @@ function item_post(App $a) { if (($message_id != '') && ($profile_uid != 0)) { if (Item::exists(['uri' => $message_id, 'uid' => $profile_uid])) { logger("Message with URI ".$message_id." already exists for user ".$profile_uid, LOGGER_DEBUG); - return; + return 0; } } @@ -183,7 +183,7 @@ function item_post(App $a) { $user = DBA::selectFirst('user', [], ['uid' => $profile_uid]); if (!DBA::isResult($user) && !$parent) { - return; + return 0; } $categories = ''; @@ -843,6 +843,10 @@ function item_post(App $a) { logger('post_complete'); + if ($api_source) { + return $post_id; + } + item_post_return(System::baseUrl(), $api_source, $return_path); // NOTREACHED } From 394526db747eb7419e07ae2ba8d8d63f44788ebb Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 2 Sep 2018 07:35:12 +0000 Subject: [PATCH 022/428] Typo corrected / use the thread table instead --- include/api.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/api.php b/include/api.php index 18027c2434..c8cb57f54d 100644 --- a/include/api.php +++ b/include/api.php @@ -1128,8 +1128,8 @@ function api_statuses_update($type) if ($throttle_day > 0) { $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60); - $condition = ["`uid` = ? AND `wall` AND `changed` > ? AND `gravity` = ?", api_user(), $datefrom, GRAVITY_PARENT]; - $posts_day = DBA::count('item', $condition); + $condition = ["`uid` = ? AND `wall` AND `created` > ?", api_user(), $datefrom]; + $posts_day = DBA::count('thread', $condition); if ($posts_day > $throttle_day) { logger('Daily posting limit reached for user '.api_user(), LOGGER_DEBUG); @@ -1142,8 +1142,8 @@ function api_statuses_update($type) if ($throttle_week > 0) { $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*7); - $condition = ["`uid` = ? AND `wall` AND `changed` > ? AND `gravity` = ?", api_user(), $datefrom, GRAVITY_PARENT]; - $posts_week = DBA::count('item', $condition); + $condition = ["`uid` = ? AND `wall` AND `created` > ?", api_user(), $datefrom]; + $posts_week = DBA::count('thread', $condition); if ($posts_week > $throttle_week) { logger('Weekly posting limit reached for user '.api_user(), LOGGER_DEBUG); @@ -1156,8 +1156,8 @@ function api_statuses_update($type) if ($throttle_month > 0) { $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*30); - $condition = ["`uid` = ? AND `wall` AND `changed` > ? AND `gravity` = ?", api_user(), $datefrom, GRAVITY_PARENT]; - $posts_month = DBA::count('item', $condition); + $condition = ["`uid` = ? AND `wall` AND `created` > ?", api_user(), $datefrom]; + $posts_month = DBA::count('thread', $condition); if ($posts_month > $throttle_month) { logger('Monthly posting limit reached for user '.api_user(), LOGGER_DEBUG); @@ -2002,7 +2002,7 @@ function api_statuses_repeat($type) throw new ForbiddenException(); } - // output the last post tha we just posted. + // output the post that we just posted. $called_api = []; return api_status_show($type, $item_id); } From fd7e45042a66ce9c2d1465044014033efe04dbae Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 2 Sep 2018 07:47:48 +0000 Subject: [PATCH 023/428] The days are getting shorter, like the list of removed notices ... --- src/Util/Emailer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Util/Emailer.php b/src/Util/Emailer.php index 4fa5e29057..1dd513c42f 100644 --- a/src/Util/Emailer.php +++ b/src/Util/Emailer.php @@ -49,7 +49,7 @@ class Emailer .rand(10000, 99999); // generate a multipart/alternative message header - $messageHeader = $params['additionalMailHeader'] . + $messageHeader = defaults($params, 'additionalMailHeader', '') . "From: $fromName <{$params['fromEmail']}>\n" . "Reply-To: $fromName <{$params['replyTo']}>\n" . "MIME-Version: 1.0\n" . From 703c668a37781f0d976c7e8c4de893b48c6da78d Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 2 Sep 2018 08:01:13 +0000 Subject: [PATCH 024/428] More notices ... --- include/api.php | 7 +++++-- mod/notifications.php | 3 +-- mod/ping.php | 2 +- src/Model/Profile.php | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/api.php b/include/api.php index f40674b894..3bae11e57d 100644 --- a/include/api.php +++ b/include/api.php @@ -581,7 +581,10 @@ function api_get_user(App $a, $contact_id = null) if (is_null($user) && ($a->argc > (count($called_api) - 1)) && (count($called_api) > 0)) { $argid = count($called_api); if (!empty($a->argv[$argid])) { - list($user, $null) = explode(".", $a->argv[$argid]); + $data = explode(".", $a->argv[$argid]); + if (count($data) > 1) { + list($user, $null) = $data; + } } if (is_numeric($user)) { $user = DBA::escape(api_unique_id_to_nurl(intval($user))); @@ -4396,7 +4399,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $ if ($filetype == "") { $filetype=Image::guessType($filename); } - $imagedata = getimagesize($src); + $imagedata = @getimagesize($src); if ($imagedata) { $filetype = $imagedata['mime']; } diff --git a/mod/notifications.php b/mod/notifications.php index 145c384350..bc581b6dd3 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -115,7 +115,6 @@ function notifications_content(App $a) } elseif (($a->argc > 1) && ($a->argv[1] == 'home')) { $notif_header = L10n::t('Home Notifications'); $notifs = $nm->homeNotifs($show, $startrec, $perpage); - } @@ -134,7 +133,7 @@ function notifications_content(App $a) $notif_tpl = get_markup_template('notifications.tpl'); if (!isset($notifs['ident'])) { - logger('Missing data in notifs: ' . System::callstack(20), LOGGER_DEBUG); + logger('Missing data in notifs: ' . json_encode($a->argv), LOGGER_DEBUG); } // Process the data for template creation diff --git a/mod/ping.php b/mod/ping.php index 99ebde70c1..9867f03f9a 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -519,7 +519,7 @@ function ping_get_notifications($uid) * @param int $forums_unseen Number of unseen forum items * @return array XML-transform ready data array */ -function ping_format_xml_data($data, $sysnotify, $notifs, $sysmsgs, $sysmsgs_info, $groups_unseen, $forums_unseen) +function ping_format_xml_data($data, $sysnotify_count, $notifs, $sysmsgs, $sysmsgs_info, $groups_unseen, $forums_unseen) { $notifications = []; foreach ($notifs as $key => $notif) { diff --git a/src/Model/Profile.php b/src/Model/Profile.php index f6e116fa79..29bc7e680d 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -492,7 +492,7 @@ class Profile if (isset($p['address'])) { $p['address'] = BBCode::convert($p['address']); - } else { + } elseif (isset($p['location'])) { $p['address'] = BBCode::convert($p['location']); } From 58148905f14398895b7a1960beb67a98ec137561 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 2 Sep 2018 17:48:07 +0000 Subject: [PATCH 025/428] Changed documention --- mod/ping.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mod/ping.php b/mod/ping.php index 9867f03f9a..968751a7da 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -510,13 +510,14 @@ function ping_get_notifications($uid) * @brief Backward-compatible XML formatting for ping.php output * @deprecated * - * @param array $data The initial ping data array - * @param int $sysnotify Number of unseen system notifications - * @param array $notifs Complete list of notification - * @param array $sysmsgs List of system notice messages - * @param array $sysmsgs_info List of system info messages - * @param int $groups_unseen Number of unseen group items - * @param int $forums_unseen Number of unseen forum items + * @param array $data The initial ping data array + * @param int $sysnotify_count Number of unseen system notifications + * @param array $notifs Complete list of notification + * @param array $sysmsgs List of system notice messages + * @param array $sysmsgs_info List of system info messages + * @param int $groups_unseen Number of unseen group items + * @param int $forums_unseen Number of unseen forum items + * * @return array XML-transform ready data array */ function ping_format_xml_data($data, $sysnotify_count, $notifs, $sysmsgs, $sysmsgs_info, $groups_unseen, $forums_unseen) From 5250552fe28cd4a5d2b148ca7a431233191e92c9 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 2 Sep 2018 17:48:25 +0000 Subject: [PATCH 026/428] Removed obsolete post update that sometimes never finishes --- src/Database/PostUpdate.php | 85 ------------------------------------- 1 file changed, 85 deletions(-) diff --git a/src/Database/PostUpdate.php b/src/Database/PostUpdate.php index 674fe05531..dbadcbbb1b 100644 --- a/src/Database/PostUpdate.php +++ b/src/Database/PostUpdate.php @@ -27,9 +27,6 @@ class PostUpdate if (!self::update1194()) { return false; } - if (!self::update1198()) { - return false; - } if (!self::update1206()) { return false; } @@ -111,88 +108,6 @@ class PostUpdate logger("Done", LOGGER_DEBUG); } - /** - * @brief set the author-id and owner-id in all item entries - * - * This job has to be started multiple times until all entries are set. - * It isn't started in the update function since it would consume too much time and can be done in the background. - * - * @return bool "true" when the job is done - */ - private static function update1198() - { - // Was the script completed? - if (Config::get("system", "post_update_version") >= 1198) { - return true; - } - - logger("Start", LOGGER_DEBUG); - - // Check if the first step is done (Setting "author-id" and "owner-id" in the item table) - $fields = ['author-link', 'author-name', 'author-avatar', 'owner-link', 'owner-name', 'owner-avatar', 'network', 'uid']; - $r = DBA::select('item', $fields, ['author-id' => 0, 'owner-id' => 0], ['limit' => 1000]); - if (!$r) { - // Are there unfinished entries in the thread table? - $r = q("SELECT COUNT(*) AS `total` FROM `thread` - INNER JOIN `item` ON `item`.`id` =`thread`.`iid` - WHERE `thread`.`author-id` = 0 AND `thread`.`owner-id` = 0 AND - (`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)"); - - if ($r && ($r[0]["total"] == 0)) { - Config::set("system", "post_update_version", 1198); - logger("Done", LOGGER_DEBUG); - return true; - } - - // Update the thread table from the item table - $r = q("UPDATE `thread` INNER JOIN `item` ON `item`.`id`=`thread`.`iid` - SET `thread`.`author-id` = `item`.`author-id`, - `thread`.`owner-id` = `item`.`owner-id` - WHERE `thread`.`author-id` = 0 AND `thread`.`owner-id` = 0 AND - (`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)"); - - logger("Updated threads", LOGGER_DEBUG); - if (DBA::isResult($r)) { - Config::set("system", "post_update_version", 1198); - logger("Done", LOGGER_DEBUG); - return true; - } - return false; - } - - logger("Query done", LOGGER_DEBUG); - - $item_arr = []; - foreach ($r as $item) { - $index = $item["author-link"]."-".$item["owner-link"]."-".$item["uid"]; - $item_arr[$index] = ["author-link" => $item["author-link"], - "owner-link" => $item["owner-link"], - "uid" => $item["uid"]]; - } - - // Set the "author-id" and "owner-id" in the item table and add a new public contact entry if needed - foreach ($item_arr as $item) { - $default = ['url' => $item['author-link'], 'name' => $item['author-name'], - 'photo' => $item['author-avatar'], 'network' => $item['network']]; - $author_id = Contact::getIdForURL($item["author-link"], 0, false, $default); - - $default = ['url' => $item['owner-link'], 'name' => $item['owner-name'], - 'photo' => $item['owner-avatar'], 'network' => $item['network']]; - $owner_id = Contact::getIdForURL($item["owner-link"], 0, false, $default); - - if ($author_id == 0) { - $author_id = -1; - } - if ($owner_id == 0) { - $owner_id = -1; - } - DBA::update('item', ['author-id' => $author_id, 'owner-id' => $owner_id], ['uid' => $item['uid'], 'author-link' => $item['author-link'], 'owner-link' => $item['owner-link'], 'author-id' => 0, 'owner-id' => 0]); - } - - logger("Updated items", LOGGER_DEBUG); - return false; - } - /** * @brief update the "last-item" field in the "self" contact * From 475d3f8f3a71afb94315bbc3264a950a61b26b52 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 2 Sep 2018 17:24:56 -0400 Subject: [PATCH 027/428] Fix formatting in mod/parse_url --- mod/parse_url.php | 102 +++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/mod/parse_url.php b/mod/parse_url.php index 3309a74b9f..ebe34875b7 100644 --- a/mod/parse_url.php +++ b/mod/parse_url.php @@ -8,128 +8,127 @@ * information and does format this information to BBCode * * @see ParseUrl::getSiteinfo() for more information about scraping embeddable content -*/ - + */ use Friendica\App; use Friendica\Core\Addon; use Friendica\Util\Network; use Friendica\Util\ParseUrl; -require_once("include/items.php"); - -function parse_url_content(App $a) { +require_once 'include/items.php'; +function parse_url_content(App $a) +{ $text = null; - $str_tags = ""; + $str_tags = ''; $br = "\n"; - if (!empty($_GET["binurl"])) { - $url = trim(hex2bin($_GET["binurl"])); + if (!empty($_GET['binurl'])) { + $url = trim(hex2bin($_GET['binurl'])); } else { - $url = trim($_GET["url"]); + $url = trim($_GET['url']); } - if (!empty($_GET["title"])) { - $title = strip_tags(trim($_GET["title"])); + if (!empty($_GET['title'])) { + $title = strip_tags(trim($_GET['title'])); } - if (!empty($_GET["description"])) { - $text = strip_tags(trim($_GET["description"])); + if (!empty($_GET['description'])) { + $text = strip_tags(trim($_GET['description'])); } - if (!empty($_GET["tags"])) { - $arr_tags = ParseUrl::convertTagsToArray($_GET["tags"]); + if (!empty($_GET['tags'])) { + $arr_tags = ParseUrl::convertTagsToArray($_GET['tags']); if (count($arr_tags)) { - $str_tags = $br . implode(" ", $arr_tags) . $br; + $str_tags = $br . implode(' ', $arr_tags) . $br; } } // Add url scheme if it is missing $arrurl = parse_url($url); - if (!x($arrurl, "scheme")) { - if (x($arrurl, "host")) { - $url = "http:".$url; + if (!x($arrurl, 'scheme')) { + if (x($arrurl, 'host')) { + $url = 'http:' . $url; } else { - $url = "http://".$url; + $url = 'http://' . $url; } } - logger("prse_url: " . $url); + logger($url); // Check if the URL is an image, video or audio file. If so format // 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]); - if($result["success"]) { + $result = Network::curl($url, false, $redirects, ['novalidate' => true, 'nobody' => true]); + + if ($result['success']) { // Convert the header fields into an array $hdrs = []; - $h = explode("\n", $result["header"]); + $h = explode("\n", $result['header']); foreach ($h as $l) { - $header = array_map("trim", explode(":", trim($l), 2)); + $header = array_map('trim', explode(':', trim($l), 2)); if (count($header) == 2) { - list($k,$v) = $header; + list($k, $v) = $header; $hdrs[$k] = $v; } } - if (array_key_exists("Content-Type", $hdrs)) { - $type = $hdrs["Content-Type"]; + if (array_key_exists('Content-Type', $hdrs)) { + $type = $hdrs['Content-Type']; } if ($type) { - if(stripos($type, "image/") !== false) { - echo $br . "[img]" . $url . "[/img]" . $br; - killme(); + if (stripos($type, 'image/') !== false) { + echo $br . '[img]' . $url . '[/img]' . $br; + exit(); } - if (stripos($type, "video/") !== false) { - echo $br . "[video]" . $url . "[/video]" . $br; - killme(); + if (stripos($type, 'video/') !== false) { + echo $br . '[video]' . $url . '[/video]' . $br; + exit(); } - if (stripos($type, "audio/") !== false) { - echo $br . "[audio]" . $url . "[/audio]" . $br; - killme(); + if (stripos($type, 'audio/') !== false) { + echo $br . '[audio]' . $url . '[/audio]' . $br; + exit(); } } } - $template = "[bookmark=%s]%s[/bookmark]%s"; + $template = '[bookmark=%s]%s[/bookmark]%s'; - $arr = ["url" => $url, "text" => ""]; + $arr = ['url' => $url, 'text' => '']; - Addon::callHooks("parse_link", $arr); + Addon::callHooks('parse_link', $arr); - if (strlen($arr["text"])) { - echo $arr["text"]; - killme(); + if (strlen($arr['text'])) { + echo $arr['text']; + exit(); } // If there is already some content information submitted we don't // need to parse the url for content. if (!empty($url) && !empty($title) && !empty($text)) { + $title = str_replace(["\r", "\n"], ['', ''], $title); - $title = str_replace(["\r","\n"],["",""],$title); - - $text = "[quote]" . trim($text) . "[/quote]" . $br; + $text = '[quote]' . trim($text) . '[/quote]' . $br; $result = sprintf($template, $url, ($title) ? $title : $url, $text) . $str_tags; - logger("parse_url (unparsed): returns: " . $result); + logger('(unparsed): returns: ' . $result); echo $result; - killme(); + exit(); } // Fetch the information directly from the webpage $siteinfo = ParseUrl::getSiteinfo($url); - unset($siteinfo["keywords"]); + unset($siteinfo['keywords']); // Format it as BBCode attachment $info = add_page_info_data($siteinfo); echo $info; - killme(); + exit(); } /** @@ -151,7 +150,8 @@ function parse_url_content(App $a) { * @todo Remove this function after all Addons has been changed to use * ParseUrl::getSiteinfoCached */ -function parseurl_getsiteinfo_cached($url, $no_guessing = false, $do_oembed = true) { +function parseurl_getsiteinfo_cached($url, $no_guessing = false, $do_oembed = true) +{ $siteinfo = ParseUrl::getSiteinfoCached($url, $no_guessing, $do_oembed); return $siteinfo; } From 69e7c7fecac5d315930c52bfa9fb21954dcf8b5e Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 2 Sep 2018 17:26:05 -0400 Subject: [PATCH 028/428] Fix photo attachment display - Remove double image display - Add domain link display to all attachments --- src/Content/Text/BBCode.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 41f89e65dc..55fc24273d 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -578,9 +578,7 @@ class BBCode extends BaseObject $return .= sprintf('
', $data["url"], self::proxyUrl($data["preview"], $simplehtml), $data["title"]); } - if (($data["type"] == "photo") && !empty($data["url"]) && !empty($data["image"])) { - $return .= sprintf('', $data["url"], self::proxyUrl($data["image"], $simplehtml), $data["title"]); - } else { + if (!empty($data['title']) && !empty($data['url'])) { $return .= sprintf('

%s

', $data['url'], $data['title']); } @@ -589,7 +587,8 @@ class BBCode extends BaseObject $bbcode = HTML::toBBCode($data["description"]); $return .= sprintf('
%s
', trim(self::convert($bbcode))); } - if ($data["type"] == "link") { + + if (!empty($data['url'])) { $return .= sprintf('%s', $data['url'], parse_url($data['url'], PHP_URL_HOST)); } From 8bcc3c68602cb7df05ccf8241dff5d53cfa71afb Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 2 Sep 2018 17:35:55 -0400 Subject: [PATCH 029/428] Fix formatting in Util/ParseUrl - Remove commented out code - Replace double quotes with simple quotes - Remove parentheses for language construct - Add spaces around operators - Rename variables --- src/Util/ParseUrl.php | 265 +++++++++++++++++++++--------------------- 1 file changed, 132 insertions(+), 133 deletions(-) diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index 3be372767b..b897c54ee7 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -118,13 +118,13 @@ class ParseUrl // Check if the URL does contain a scheme $scheme = parse_url($url, PHP_URL_SCHEME); - if ($scheme == "") { - $url = "http://".trim($url, "/"); + if ($scheme == '') { + $url = 'http://' . trim($url, '/'); } if ($count > 10) { - logger("parseurl_getsiteinfo: Endless loop detected for ".$url, LOGGER_DEBUG); - return($siteinfo); + logger('Endless loop detected for ' . $url, LOGGER_DEBUG); + return $siteinfo; } $url = trim($url, "'"); @@ -132,220 +132,217 @@ class ParseUrl $url = Network::stripTrackingQueryParams($url); - $siteinfo["url"] = $url; - $siteinfo["type"] = "link"; + $siteinfo['url'] = $url; + $siteinfo['type'] = 'link'; $data = Network::curl($url); if (!$data['success']) { - return($siteinfo); + return $siteinfo; } // If the file is too large then exit - if ($data["info"]["download_content_length"] > 1000000) { - return($siteinfo); + if ($data['info']['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")) { - return($siteinfo); + if (($data['info']['content_type'] != '') && !strstr(strtolower($data['info']['content_type']), 'html')) { + return $siteinfo; } - $header = $data["header"]; - $body = $data["body"]; + $header = $data['header']; + $body = $data['body']; if ($do_oembed) { $oembed_data = OEmbed::fetchURL($url); if (!empty($oembed_data->type)) { - if (!in_array($oembed_data->type, ["error", "rich", ""])) { - $siteinfo["type"] = $oembed_data->type; + if (!in_array($oembed_data->type, ['error', 'rich', ''])) { + $siteinfo['type'] = $oembed_data->type; } - if (($oembed_data->type == "link") && ($siteinfo["type"] != "photo")) { + if (($oembed_data->type == 'link') && ($siteinfo['type'] != 'photo')) { if (isset($oembed_data->title)) { - $siteinfo["title"] = trim($oembed_data->title); + $siteinfo['title'] = trim($oembed_data->title); } if (isset($oembed_data->description)) { - $siteinfo["text"] = trim($oembed_data->description); + $siteinfo['text'] = trim($oembed_data->description); } if (isset($oembed_data->thumbnail_url)) { - $siteinfo["image"] = $oembed_data->thumbnail_url; + $siteinfo['image'] = $oembed_data->thumbnail_url; } } } } // Fetch the first mentioned charset. Can be in body or header - $charset = ""; - if (preg_match('/charset=(.*?)['."'".'"\s\n]/', $header, $matches)) { + $charset = ''; + if (preg_match('/charset=(.*?)[\'"\s\n]/', $header, $matches)) { $charset = trim(trim(trim(array_pop($matches)), ';,')); } - if ($charset == "") { - $charset = "utf-8"; + if ($charset == '') { + $charset = 'utf-8'; } - if (($charset != "") && (strtoupper($charset) != "UTF-8")) { - logger("parseurl_getsiteinfo: detected charset ".$charset, LOGGER_DEBUG); - //$body = mb_convert_encoding($body, "UTF-8", $charset); - $body = iconv($charset, "UTF-8//TRANSLIT", $body); + if (($charset != '') && (strtoupper($charset) != 'UTF-8')) { + logger('detected charset ' . $charset, LOGGER_DEBUG); + $body = iconv($charset, 'UTF-8//TRANSLIT', $body); } - $body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8"); + $body = mb_convert_encoding($body, 'HTML-ENTITIES', 'UTF-8'); $doc = new DOMDocument(); @$doc->loadHTML($body); - XML::deleteNode($doc, "style"); - XML::deleteNode($doc, "script"); - XML::deleteNode($doc, "option"); - XML::deleteNode($doc, "h1"); - XML::deleteNode($doc, "h2"); - XML::deleteNode($doc, "h3"); - XML::deleteNode($doc, "h4"); - XML::deleteNode($doc, "h5"); - XML::deleteNode($doc, "h6"); - XML::deleteNode($doc, "ol"); - XML::deleteNode($doc, "ul"); + XML::deleteNode($doc, 'style'); + XML::deleteNode($doc, 'script'); + XML::deleteNode($doc, 'option'); + XML::deleteNode($doc, 'h1'); + XML::deleteNode($doc, 'h2'); + XML::deleteNode($doc, 'h3'); + XML::deleteNode($doc, 'h4'); + XML::deleteNode($doc, 'h5'); + XML::deleteNode($doc, 'h6'); + XML::deleteNode($doc, 'ol'); + XML::deleteNode($doc, 'ul'); $xpath = new DOMXPath($doc); - $list = $xpath->query("//meta[@content]"); + $list = $xpath->query('//meta[@content]'); foreach ($list as $node) { - $attr = []; + $meta_tag = []; if ($node->attributes->length) { foreach ($node->attributes as $attribute) { - $attr[$attribute->name] = $attribute->value; + $meta_tag[$attribute->name] = $attribute->value; } } - if (@$attr["http-equiv"] == "refresh") { - $path = $attr["content"]; - $pathinfo = explode(";", $path); - $content = ""; + if (@$meta_tag['http-equiv'] == 'refresh') { + $path = $meta_tag['content']; + $pathinfo = explode(';', $path); + $content = ''; foreach ($pathinfo as $value) { - if (substr(strtolower($value), 0, 4) == "url=") { + if (substr(strtolower($value), 0, 4) == 'url=') { $content = substr($value, 4); } } - if ($content != "") { + if ($content != '') { $siteinfo = self::getSiteinfo($content, $no_guessing, $do_oembed, ++$count); - return($siteinfo); + return $siteinfo; } } } - $list = $xpath->query("//title"); + $list = $xpath->query('//title'); if ($list->length > 0) { - $siteinfo["title"] = trim($list->item(0)->nodeValue); + $siteinfo['title'] = trim($list->item(0)->nodeValue); } - //$list = $xpath->query("head/meta[@name]"); - $list = $xpath->query("//meta[@name]"); + $list = $xpath->query('//meta[@name]'); foreach ($list as $node) { - $attr = []; + $meta_tag = []; if ($node->attributes->length) { foreach ($node->attributes as $attribute) { - $attr[$attribute->name] = $attribute->value; + $meta_tag[$attribute->name] = $attribute->value; } } - if (!empty($attr["content"])) { - $attr["content"] = trim(html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8")); + if (!empty($meta_tag['content'])) { + $meta_tag['content'] = trim(html_entity_decode($meta_tag['content'], ENT_QUOTES, 'UTF-8')); - switch (strtolower($attr["name"])) { - case "fulltitle": - $siteinfo["title"] = trim($attr["content"]); + switch (strtolower($meta_tag['name'])) { + case 'fulltitle': + $siteinfo['title'] = trim($meta_tag['content']); break; - case "description": - $siteinfo["text"] = trim($attr["content"]); + case 'description': + $siteinfo['text'] = trim($meta_tag['content']); break; - case "thumbnail": - $siteinfo["image"] = $attr["content"]; + case 'thumbnail': + $siteinfo['image'] = $meta_tag['content']; break; - case "twitter:image": - $siteinfo["image"] = $attr["content"]; + case 'twitter:image': + $siteinfo['image'] = $meta_tag['content']; break; - case "twitter:image:src": - $siteinfo["image"] = $attr["content"]; + case 'twitter:image:src': + $siteinfo['image'] = $meta_tag['content']; break; - case "twitter:card": - if (($siteinfo["type"] == "") || ($attr["content"] == "photo")) { - $siteinfo["type"] = $attr["content"]; + case 'twitter:card': + if (($siteinfo['type'] == '') || ($meta_tag['content'] == 'photo')) { + $siteinfo['type'] = $meta_tag['content']; } break; - case "twitter:description": - $siteinfo["text"] = trim($attr["content"]); + case 'twitter:description': + $siteinfo['text'] = trim($meta_tag['content']); break; - case "twitter:title": - $siteinfo["title"] = trim($attr["content"]); + case 'twitter:title': + $siteinfo['title'] = trim($meta_tag['content']); break; - case "dc.title": - $siteinfo["title"] = trim($attr["content"]); + case 'dc.title': + $siteinfo['title'] = trim($meta_tag['content']); break; - case "dc.description": - $siteinfo["text"] = trim($attr["content"]); + case 'dc.description': + $siteinfo['text'] = trim($meta_tag['content']); break; - case "keywords": - $keywords = explode(",", $attr["content"]); + case 'keywords': + $keywords = explode(',', $meta_tag['content']); break; - case "news_keywords": - $keywords = explode(",", $attr["content"]); + case 'news_keywords': + $keywords = explode(',', $meta_tag['content']); break; } } - if ($siteinfo["type"] == "summary") { - $siteinfo["type"] = "link"; + if ($siteinfo['type'] == 'summary') { + $siteinfo['type'] = 'link'; } } if (isset($keywords)) { - $siteinfo["keywords"] = []; + $siteinfo['keywords'] = []; foreach ($keywords as $keyword) { - if (!in_array(trim($keyword), $siteinfo["keywords"])) { - $siteinfo["keywords"][] = trim($keyword); + if (!in_array(trim($keyword), $siteinfo['keywords'])) { + $siteinfo['keywords'][] = trim($keyword); } } } - //$list = $xpath->query("head/meta[@property]"); - $list = $xpath->query("//meta[@property]"); + $list = $xpath->query('//meta[@property]'); foreach ($list as $node) { - $attr = []; + $meta_tag = []; if ($node->attributes->length) { foreach ($node->attributes as $attribute) { - $attr[$attribute->name] = $attribute->value; + $meta_tag[$attribute->name] = $attribute->value; } } - if (!empty($attr["content"])) { - $attr["content"] = trim(html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8")); + if (!empty($meta_tag['content'])) { + $meta_tag['content'] = trim(html_entity_decode($meta_tag['content'], ENT_QUOTES, 'UTF-8')); - switch (strtolower($attr["property"])) { - case "og:image": - $siteinfo["image"] = $attr["content"]; + switch (strtolower($meta_tag['property'])) { + case 'og:image': + $siteinfo['image'] = $meta_tag['content']; break; - case "og:title": - $siteinfo["title"] = trim($attr["content"]); + case 'og:title': + $siteinfo['title'] = trim($meta_tag['content']); break; - case "og:description": - $siteinfo["text"] = trim($attr["content"]); + case 'og:description': + $siteinfo['text'] = trim($meta_tag['content']); break; } } } - if ((@$siteinfo["image"] == "") && !$no_guessing) { - $list = $xpath->query("//img[@src]"); + if ((@$siteinfo['image'] == '') && !$no_guessing) { + $list = $xpath->query('//img[@src]'); foreach ($list as $node) { - $attr = []; + $img_tag = []; if ($node->attributes->length) { foreach ($node->attributes as $attribute) { - $attr[$attribute->name] = $attribute->value; + $img_tag[$attribute->name] = $attribute->value; } } - $src = self::completeUrl($attr["src"], $url); + $src = self::completeUrl($img_tag['src'], $url); $photodata = Image::getInfoFromURL($src); if (($photodata) && ($photodata[0] > 150) && ($photodata[1] > 150)) { @@ -357,70 +354,72 @@ class ParseUrl $photodata[0] = round($photodata[0] * (300 / $photodata[1])); $photodata[1] = 300; } - $siteinfo["images"][] = ["src" => $src, - "width" => $photodata[0], - "height" => $photodata[1]]; + $siteinfo['images'][] = [ + 'src' => $src, + 'width' => $photodata[0], + 'height' => $photodata[1] + ]; } } - } elseif (!empty($siteinfo["image"])) { - $src = self::completeUrl($siteinfo["image"], $url); + } elseif (!empty($siteinfo['image'])) { + $src = self::completeUrl($siteinfo['image'], $url); - unset($siteinfo["image"]); + unset($siteinfo['image']); $photodata = Image::getInfoFromURL($src); if (($photodata) && ($photodata[0] > 10) && ($photodata[1] > 10)) { - $siteinfo["images"][] = ["src" => $src, - "width" => $photodata[0], - "height" => $photodata[1]]; + $siteinfo['images'][] = ['src' => $src, + 'width' => $photodata[0], + 'height' => $photodata[1]]; } } - if ((@$siteinfo["text"] == "") && (@$siteinfo["title"] != "") && !$no_guessing) { - $text = ""; + if ((@$siteinfo['text'] == '') && (@$siteinfo['title'] != '') && !$no_guessing) { + $text = ''; - $list = $xpath->query("//div[@class='article']"); + $list = $xpath->query('//div[@class="article"]'); foreach ($list as $node) { if (strlen($node->nodeValue) > 40) { - $text .= " ".trim($node->nodeValue); + $text .= ' ' . trim($node->nodeValue); } } - if ($text == "") { - $list = $xpath->query("//div[@class='content']"); + if ($text == '') { + $list = $xpath->query('//div[@class="content"]'); foreach ($list as $node) { if (strlen($node->nodeValue) > 40) { - $text .= " ".trim($node->nodeValue); + $text .= ' ' . trim($node->nodeValue); } } } // If none text was found then take the paragraph content - if ($text == "") { - $list = $xpath->query("//p"); + if ($text == '') { + $list = $xpath->query('//p'); foreach ($list as $node) { if (strlen($node->nodeValue) > 40) { - $text .= " ".trim($node->nodeValue); + $text .= ' ' . trim($node->nodeValue); } } } - if ($text != "") { - $text = trim(str_replace(["\n", "\r"], [" ", " "], $text)); + if ($text != '') { + $text = trim(str_replace(["\n", "\r"], [' ', ' '], $text)); - while (strpos($text, " ")) { - $text = trim(str_replace(" ", " ", $text)); + while (strpos($text, ' ')) { + $text = trim(str_replace(' ', ' ', $text)); } - $siteinfo["text"] = trim(html_entity_decode(substr($text, 0, 350), ENT_QUOTES, "UTF-8").'...'); + $siteinfo['text'] = trim(html_entity_decode(substr($text, 0, 350), ENT_QUOTES, 'UTF-8') . '...'); } } - logger("parseurl_getsiteinfo: Siteinfo for ".$url." ".print_r($siteinfo, true), LOGGER_DEBUG); + logger('Siteinfo for ' . $url . ' ' . print_r($siteinfo, true), LOGGER_DEBUG); - Addon::callHooks("getsiteinfo", $siteinfo); + Addon::callHooks('getsiteinfo', $siteinfo); - return($siteinfo); + return $siteinfo; } /** From 9744f0e7809873bf3bed76b72bcef25e34ebcdd6 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 2 Sep 2018 17:50:27 -0400 Subject: [PATCH 030/428] Update ParseUrl::getSiteinfo type recognition - Added obsolete twitter card type provision --- src/Util/ParseUrl.php | 96 +++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index b897c54ee7..2c134542a0 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -248,55 +248,61 @@ class ParseUrl } } - if (!empty($meta_tag['content'])) { - $meta_tag['content'] = trim(html_entity_decode($meta_tag['content'], ENT_QUOTES, 'UTF-8')); + if (empty($meta_tag['content'])) { + continue; + } - switch (strtolower($meta_tag['name'])) { - case 'fulltitle': - $siteinfo['title'] = trim($meta_tag['content']); - break; - case 'description': - $siteinfo['text'] = trim($meta_tag['content']); - break; - case 'thumbnail': - $siteinfo['image'] = $meta_tag['content']; - break; - case 'twitter:image': - $siteinfo['image'] = $meta_tag['content']; - break; - case 'twitter:image:src': - $siteinfo['image'] = $meta_tag['content']; - break; - case 'twitter:card': - if (($siteinfo['type'] == '') || ($meta_tag['content'] == 'photo')) { - $siteinfo['type'] = $meta_tag['content']; - } - break; - case 'twitter:description': - $siteinfo['text'] = trim($meta_tag['content']); - break; - case 'twitter:title': - $siteinfo['title'] = trim($meta_tag['content']); - break; - case 'dc.title': - $siteinfo['title'] = trim($meta_tag['content']); - break; - case 'dc.description': - $siteinfo['text'] = trim($meta_tag['content']); - break; - case 'keywords': - $keywords = explode(',', $meta_tag['content']); - break; - case 'news_keywords': - $keywords = explode(',', $meta_tag['content']); - break; - } - } - if ($siteinfo['type'] == 'summary') { - $siteinfo['type'] = 'link'; + $meta_tag['content'] = trim(html_entity_decode($meta_tag['content'], ENT_QUOTES, 'UTF-8')); + + switch (strtolower($meta_tag['name'])) { + case 'fulltitle': + $siteinfo['title'] = trim($meta_tag['content']); + break; + case 'description': + $siteinfo['text'] = trim($meta_tag['content']); + break; + case 'thumbnail': + $siteinfo['image'] = $meta_tag['content']; + break; + case 'twitter:image': + $siteinfo['image'] = $meta_tag['content']; + break; + case 'twitter:image:src': + $siteinfo['image'] = $meta_tag['content']; + break; + case 'twitter:card': + // Obsolete card type + if ($meta_tag['content'] == 'photo') { + $siteinfo['type'] = 'summary_large_image'; + } else { + $siteinfo['type'] = $meta_tag['content']; + } + break; + case 'twitter:description': + $siteinfo['text'] = trim($meta_tag['content']); + break; + case 'twitter:title': + $siteinfo['title'] = trim($meta_tag['content']); + break; + case 'dc.title': + $siteinfo['title'] = trim($meta_tag['content']); + break; + case 'dc.description': + $siteinfo['text'] = trim($meta_tag['content']); + break; + case 'keywords': + $keywords = explode(',', $meta_tag['content']); + break; + case 'news_keywords': + $keywords = explode(',', $meta_tag['content']); + break; } } + if ($siteinfo['type'] == 'summary' || $siteinfo['type'] == 'summary_large_image') { + $siteinfo['type'] = 'link'; + } + if (isset($keywords)) { $siteinfo['keywords'] = []; foreach ($keywords as $keyword) { From 821429fdf13ca1bcd442b389d390287921b65e0b Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 4 Sep 2018 17:48:09 +0000 Subject: [PATCH 031/428] Good news, everyone - again somce notices removed --- mod/events.php | 18 ++++++++++-------- mod/notifications.php | 11 ++++------- mod/unfollow.php | 2 +- src/App.php | 6 +++++- src/Util/HTTPSignature.php | 2 ++ 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/mod/events.php b/mod/events.php index 91474022fc..21cf70d20f 100644 --- a/mod/events.php +++ b/mod/events.php @@ -54,11 +54,11 @@ function events_post(App $a) { $cid = (x($_POST, 'cid') ? intval($_POST['cid']) : 0); $uid = local_user(); - $start_text = escape_tags($_REQUEST['start_text']); - $finish_text = escape_tags($_REQUEST['finish_text']); + $start_text = escape_tags(defaults($_REQUEST, 'start_text', '')); + $finish_text = escape_tags(defaults($_REQUEST, 'finish_text', '')); - $adjust = intval($_POST['adjust']); - $nofinish = intval($_POST['nofinish']); + $adjust = intval(defaults($_POST, 'adjust', 0)); + $nofinish = intval(defaults($_POST, 'nofinish', 0)); // The default setting for the `private` field in event_store() is false, so mirror that $private_event = false; @@ -91,9 +91,9 @@ function events_post(App $a) { // and we'll waste a bunch of time responding to it. Time that // could've been spent doing something else. - $summary = escape_tags(trim($_POST['summary'])); - $desc = escape_tags(trim($_POST['desc'])); - $location = escape_tags(trim($_POST['location'])); + $summary = escape_tags(trim(defaults($_POST, 'summary', ''))); + $desc = escape_tags(trim(defaults($_POST, 'desc', ''))); + $location = escape_tags(trim(defaults($_POST, 'location', ''))); $type = 'event'; $action = ($event_id == '') ? 'new' : "event/" . $event_id; @@ -117,7 +117,7 @@ function events_post(App $a) { goaway($onerror_url); } - $share = (intval($_POST['share']) ? intval($_POST['share']) : 0); + $share = intval(defaults($_POST, 'share', 0)); $c = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1", intval(local_user()) @@ -484,6 +484,8 @@ function events_content(App $a) { if ($mode === 'new' || $mode === 'copy') { $acl = ($cid ? '' : ACL::getFullSelectorHTML($a->user, false, $orig_event)); + } else { + $acl = ''; } // If we copy an old event, we need to remove the ID and URI diff --git a/mod/notifications.php b/mod/notifications.php index bc581b6dd3..091323d998 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -87,10 +87,11 @@ function notifications_content(App $a) $perpage = 20; $startrec = ($page * $perpage) - $perpage; + $notif_header = L10n::t('Notifications'); + // Get introductions if ((($a->argc > 1) && ($a->argv[1] == 'intros')) || (($a->argc == 1))) { Nav::setSelected('introductions'); - $notif_header = L10n::t('Notifications'); $all = (($a->argc > 2) && ($a->argv[2] == 'all')); @@ -132,12 +133,8 @@ function notifications_content(App $a) $notif_tpl = get_markup_template('notifications.tpl'); - if (!isset($notifs['ident'])) { - logger('Missing data in notifs: ' . json_encode($a->argv), LOGGER_DEBUG); - } - // Process the data for template creation - if ($notifs['ident'] === 'introductions') { + if (defaults($notifs, 'ident', '') === 'introductions') { $sugg = get_markup_template('suggestions.tpl'); $tpl = get_markup_template("intros.tpl"); @@ -280,7 +277,7 @@ function notifications_content(App $a) } // Normal notifications (no introductions) - } else { + } elseif (!empty($notifs['notifications'])) { // The template files we need in different cases for formatting the content $tpl_item_like = 'notifications_likes_item.tpl'; $tpl_item_dislike = 'notifications_dislikes_item.tpl'; diff --git a/mod/unfollow.php b/mod/unfollow.php index 0af16ec671..956b6fbdb7 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -22,7 +22,7 @@ function unfollow_post() // NOTREACHED } - if ($_REQUEST['cancel']) { + if (!empty($_REQUEST['cancel'])) { goaway($return_url); } diff --git a/src/App.php b/src/App.php index 2a5fba8541..488c2301b6 100644 --- a/src/App.php +++ b/src/App.php @@ -1074,7 +1074,11 @@ class App $meminfo = []; foreach ($memdata as $line) { - list($key, $val) = explode(':', $line); + $data = explode(':', $line); + if (count($data) != 2) { + continue; + } + list($key, $val) = $data; $meminfo[$key] = (int) trim(str_replace('kB', '', $val)); $meminfo[$key] = (int) ($meminfo[$key] / 1024); } diff --git a/src/Util/HTTPSignature.php b/src/Util/HTTPSignature.php index f88b0423c5..911de4308e 100644 --- a/src/Util/HTTPSignature.php +++ b/src/Util/HTTPSignature.php @@ -125,6 +125,8 @@ class HTTPSignature $key = $key($sig_block['keyId']); } + logger('Got keyID ' . $sig_block['keyId']); + // We don't use Activity Pub at the moment. // if (!$key) { // $result['signer'] = $sig_block['keyId']; From 635c8d7450866cb8b77a6d1d42260257e286a940 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 4 Sep 2018 21:24:30 +0000 Subject: [PATCH 032/428] Beautified the code --- mod/events.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mod/events.php b/mod/events.php index 21cf70d20f..c4d40252d3 100644 --- a/mod/events.php +++ b/mod/events.php @@ -482,8 +482,8 @@ function events_content(App $a) { $perms = ACL::getDefaultUserPermissions($orig_event); - if ($mode === 'new' || $mode === 'copy') { - $acl = ($cid ? '' : ACL::getFullSelectorHTML($a->user, false, $orig_event)); + if (!$cid && in_array($mode, ['new', 'copy'])) { + $acl = ACL::getFullSelectorHTML($a->user, false, $orig_event); } else { $acl = ''; } From 9de0d354506fdb20929e68d10cf3680181d4382c Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 4 Sep 2018 19:29:36 -0400 Subject: [PATCH 033/428] Remove extraneous SQL condition part in mod/unfollow --- mod/unfollow.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/unfollow.php b/mod/unfollow.php index 0af16ec671..f9b0a2fcba 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -29,7 +29,7 @@ function unfollow_post() $uid = local_user(); $url = notags(trim(defaults($_REQUEST, 'url', ''))); - $condition = ["`uid` = ? AND (`rel` = ? OR `rel` = ?) AND (`nurl` = ? OR `alias` = ? OR `alias` = ?) AND `network` != ?", + $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); From 9ef1d827f35dfcd779015003bc359e3dd7d6fef6 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 5 Sep 2018 05:02:06 +0000 Subject: [PATCH 034/428] Restore the behaviour to remove the remote contact upon termination --- mod/contacts.php | 2 +- mod/dfrn_notify.php | 4 ++-- mod/dirfind.php | 2 +- mod/unfollow.php | 6 ++++-- src/Model/Contact.php | 12 ++++++++---- src/Protocol/DFRN.php | 13 ++++++++----- src/Worker/Notifier.php | 2 +- 7 files changed, 25 insertions(+), 16 deletions(-) diff --git a/mod/contacts.php b/mod/contacts.php index 70a582c6ee..68f68fec3b 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -368,7 +368,7 @@ function _contact_drop($orig_record) return; } - Contact::terminateFriendship($r[0], $orig_record); + Contact::terminateFriendship($r[0], $orig_record, true); Contact::remove($orig_record['id']); } diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index 88f706385b..f653faca95 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -322,8 +322,8 @@ function dfrn_notify_content(App $a) { $encrypted_id = ''; $id_str = $my_id . '.' . mt_rand(1000,9999); - $prv_key = trim($importer['prvkey']); - $pub_key = trim($importer['pubkey']); + $prv_key = trim($importer['cprvkey']); + $pub_key = trim($importer['cpubkey']); $dplx = intval($importer['duplex']); if (($dplx && strlen($prv_key)) || (strlen($prv_key) && !strlen($pub_key))) { diff --git a/mod/dirfind.php b/mod/dirfind.php index f4ddba45d4..332fe90f6c 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -44,7 +44,7 @@ function dirfind_content(App $a, $prefix = "") { $local = Config::get('system','poco_local_search'); - $search = $prefix.notags(trim($_REQUEST['search'])); + $search = $prefix.notags(trim(defaults($_REQUEST, 'search', ''))); $header = ''; diff --git a/mod/unfollow.php b/mod/unfollow.php index 956b6fbdb7..0aa114759f 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -46,13 +46,15 @@ function unfollow_post() // NOTREACHED } + $dissolve = ($contact['rel'] == Contact::SHARING); + $owner = User::getOwnerDataById($uid); if ($owner) { - Contact::terminateFriendship($owner, $contact); + Contact::terminateFriendship($owner, $contact, $dissolve); } // Sharing-only contacts get deleted as there no relationship any more - if ($contact['rel'] == Contact::SHARING) { + if ($dissolve) { Contact::remove($contact['id']); $return_path = 'contacts'; } else { diff --git a/src/Model/Contact.php b/src/Model/Contact.php index d53126f6ff..1bbc0228a8 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -17,6 +17,7 @@ use Friendica\Model\Profile; use Friendica\Network\Probe; use Friendica\Object\Image; use Friendica\Protocol\Diaspora; +use Friendica\Protocol\DFRN; use Friendica\Protocol\OStatus; use Friendica\Protocol\PortableContact; use Friendica\Protocol\Salmon; @@ -528,13 +529,16 @@ class Contact extends BaseObject /** * @brief Sends an unfriend message. Does not remove the contact * - * @param array $user User unfriending - * @param array $contact Contact unfriended + * @param array $user User unfriending + * @param array $contact Contact unfriended + * @param boolean $dissolve Remove the contact on the remote side * @return void */ - public static function terminateFriendship(array $user, array $contact) + public static function terminateFriendship(array $user, array $contact, $dissolve = false) { - if (in_array($contact['network'], [Protocol::OSTATUS, Protocol::DFRN])) { + if (($contact['network'] == Protocol::DFRN) && $dissolve) { + DFRN::deliver($user, $contact, 'placeholder', true); + } elseif (in_array($contact['network'], [Protocol::OSTATUS, Protocol::DFRN])) { // create an unfollow slap $item = []; $item['verb'] = NAMESPACE_OSTATUS . "/unfollow"; diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index c435550313..b207c3ca87 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -81,7 +81,8 @@ class DFRN return []; } - $user['importer_uid'] = $user['uid']; + $user['importer_uid'] = $user['uid']; + $user['uprvkey'] = $user['prvkey']; } else { $user = ['importer_uid' => 0, 'uprvkey' => '', 'timezone' => 'UTC', 'nickname' => '', 'sprvkey' => '', 'spubkey' => '', @@ -1168,10 +1169,12 @@ class DFRN $a = get_app(); // At first try the Diaspora transport layer - $ret = self::transmit($owner, $contact, $atom); - if ($ret >= 200) { - logger('Delivery via Diaspora transport layer was successful with status ' . $ret); - return $ret; + if (!$dissolve) { + $ret = self::transmit($owner, $contact, $atom); + if ($ret >= 200) { + logger('Delivery via Diaspora transport layer was successful with status ' . $ret); + return $ret; + } } $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']); diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index 6d2733b8ee..61eaba388b 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -96,7 +96,7 @@ class Notifier return; } foreach ($r as $contact) { - Contact::terminateFriendship($user, $contact); + Contact::terminateFriendship($user, $contact, true); } return; } elseif ($cmd == Delivery::RELOCATION) { From 88d25f977a078dd3e5dfb7d0461cf231ff64358f Mon Sep 17 00:00:00 2001 From: rabuzarus Date: Wed, 5 Sep 2018 14:12:56 +0200 Subject: [PATCH 035/428] fix lockview for photos - use the private field only for items because other tables than the item table don't have the private field --- mod/lockview.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mod/lockview.php b/mod/lockview.php index 893764c4d9..7617d6f736 100644 --- a/mod/lockview.php +++ b/mod/lockview.php @@ -24,11 +24,12 @@ function lockview_content(App $a) { if (!in_array($type, ['item','photo','event'])) killme(); - $fields = ['uid', 'private', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid']; + $fields = ['uid', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid']; $condition = ['id' => $item_id]; if ($type != 'item') { $item = DBA::selectFirst($type, $fields, $condition); } else { + $fields[] = 'private'; $item = Item::selectFirst($fields, $condition); } From bd9d102da254f723436adc544f510a92a8935925 Mon Sep 17 00:00:00 2001 From: rabuzarus Date: Wed, 5 Sep 2018 14:24:51 +0200 Subject: [PATCH 036/428] apply coding standards to lockview module --- mod/lockview.php | 61 +++++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/mod/lockview.php b/mod/lockview.php index 7617d6f736..0d87e15510 100644 --- a/mod/lockview.php +++ b/mod/lockview.php @@ -8,24 +8,27 @@ use Friendica\Core\L10n; use Friendica\Database\DBA; use Friendica\Model\Item; -function lockview_content(App $a) { - +function lockview_content(App $a) +{ $type = (($a->argc > 1) ? $a->argv[1] : 0); if (is_numeric($type)) { $item_id = intval($type); - $type='item'; + $type = 'item'; } else { $item_id = (($a->argc > 2) ? intval($a->argv[2]) : 0); } - if (!$item_id) + if (!$item_id) { killme(); + } - if (!in_array($type, ['item','photo','event'])) + if (!in_array($type, ['item','photo','event'])) { killme(); + } $fields = ['uid', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid']; $condition = ['id' => $item_id]; + if ($type != 'item') { $item = DBA::selectFirst($type, $fields, $condition); } else { @@ -44,18 +47,20 @@ function lockview_content(App $a) { killme(); } - - if (($item['private'] == 1) && empty($item['allow_cid']) && empty($item['allow_gid']) - && empty($item['deny_cid']) && empty($item['deny_gid'])) { - + if ($item['private'] == 1 + && empty($item['allow_cid']) + && empty($item['allow_gid']) + && empty($item['deny_cid']) + && empty($item['deny_gid'])) + { echo L10n::t('Remote privacy information not available.') . '
'; killme(); } - $allowed_users = expand_acl($item['allow_cid']); + $allowed_users = expand_acl($item['allow_cid']); $allowed_groups = expand_acl($item['allow_gid']); - $deny_users = expand_acl($item['deny_cid']); - $deny_groups = expand_acl($item['deny_gid']); + $deny_users = expand_acl($item['deny_cid']); + $deny_groups = expand_acl($item['deny_gid']); $o = L10n::t('Visible to:') . '
'; $l = []; @@ -64,36 +69,44 @@ function lockview_content(App $a) { $r = q("SELECT `name` FROM `group` WHERE `id` IN ( %s )", DBA::escape(implode(', ', $allowed_groups)) ); - if (DBA::isResult($r)) - foreach($r as $rr) + if (DBA::isResult($r)) { + foreach ($r as $rr) { $l[] = '' . $rr['name'] . ''; + } + } } + if (count($allowed_users)) { $r = q("SELECT `name` FROM `contact` WHERE `id` IN ( %s )", - DBA::escape(implode(', ',$allowed_users)) + DBA::escape(implode(', ', $allowed_users)) ); - if (DBA::isResult($r)) - foreach($r as $rr) + if (DBA::isResult($r)) { + foreach ($r as $rr) { $l[] = $rr['name']; - + } + } } if (count($deny_groups)) { $r = q("SELECT `name` FROM `group` WHERE `id` IN ( %s )", DBA::escape(implode(', ', $deny_groups)) ); - if (DBA::isResult($r)) - foreach($r as $rr) + if (DBA::isResult($r)) { + foreach ($r as $rr) { $l[] = '' . $rr['name'] . ''; + } + } } + if (count($deny_users)) { $r = q("SELECT `name` FROM `contact` WHERE `id` IN ( %s )", - DBA::escape(implode(', ',$deny_users)) + DBA::escape(implode(', ', $deny_users)) ); - if (DBA::isResult($r)) - foreach($r as $rr) + if (DBA::isResult($r)) { + foreach ($r as $rr) { $l[] = '' . $rr['name'] . ''; - + } + } } echo $o . implode(', ', $l); From 85fed927c3e827d471a1c5f6b49d6e7da49a075c Mon Sep 17 00:00:00 2001 From: rabuzarus Date: Wed, 5 Sep 2018 17:30:07 +0200 Subject: [PATCH 037/428] Frio - addToModal() can now be used with an element ID as a parameter --- view/theme/frio/js/modal.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/view/theme/frio/js/modal.js b/view/theme/frio/js/modal.js index 2b3059eaf1..9a15cab52a 100644 --- a/view/theme/frio/js/modal.js +++ b/view/theme/frio/js/modal.js @@ -188,14 +188,25 @@ function loadModalTitle() { } } -// This function loads html content from a friendica page -// into a modal. -function addToModal(url) { + +/** + * This function loads html content from a friendica page into a modal. + * + * @param {string} url The url with html content. + * @param {string} id The ID of a html element (can be undefined). + * @returns {void} + */ +function addToModal(url, id) { var char = qOrAmp(url); url = url + char + 'mode=none'; var modal = $('#modal').modal(); + // Only search for an element if we have an ID. + if (typeof id !== "undefined") { + url = url + " div#" + id; + } + modal .find('#modal-body') .load(url, function (responseText, textStatus) { @@ -215,7 +226,7 @@ function addToModal(url) { }); } -// Add a element (by it's id) to a bootstrap modal. +// Add an element (by its id) to a bootstrap modal. function addElmToModal(id) { var elm = $(id).html(); var modal = $('#modal').modal(); From 7c5e964581480902d7f0571ff92936beda36f4e2 Mon Sep 17 00:00:00 2001 From: rabuzarus Date: Wed, 5 Sep 2018 18:24:04 +0200 Subject: [PATCH 038/428] Frio - fix missing modal for editing albums --- view/theme/frio/js/mod_photos.js | 7 +++++++ view/theme/frio/templates/album_edit.tpl | 23 ++++++++++++----------- view/theme/frio/templates/photo_album.tpl | 4 ++-- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/view/theme/frio/js/mod_photos.js b/view/theme/frio/js/mod_photos.js index b8d03b5db9..77173385b1 100644 --- a/view/theme/frio/js/mod_photos.js +++ b/view/theme/frio/js/mod_photos.js @@ -15,7 +15,14 @@ $(document).ready(function() { }).trigger('change'); + // Click event listener for the album edit link/button. + $("body").on('click', '#album-edit-link', function() { + var modalUrl = $(this).attr("data-modal-url"); + if (typeof modalUrl !== "undefined") { + addToModal(modalUrl, 'photo-album-edit-wrapper'); + } + }); }); $(window).load(function() { diff --git a/view/theme/frio/templates/album_edit.tpl b/view/theme/frio/templates/album_edit.tpl index 583eb6d1b7..f4a60b7d03 100644 --- a/view/theme/frio/templates/album_edit.tpl +++ b/view/theme/frio/templates/album_edit.tpl @@ -1,14 +1,15 @@
-
- -
- -
- -
- - -
-
+
+ +
+ +
+ +
+ + +
+
+
diff --git a/view/theme/frio/templates/photo_album.tpl b/view/theme/frio/templates/photo_album.tpl index c991b03cfc..235b9c46db 100644 --- a/view/theme/frio/templates/photo_album.tpl +++ b/view/theme/frio/templates/photo_album.tpl @@ -12,9 +12,9 @@ {{if $edit}} - + {{/if}} {{if ! $noorder}} From f9fe162f2fa4a2142e8157ca2a7f20f7b0efeced Mon Sep 17 00:00:00 2001 From: rabuzarus Date: Wed, 5 Sep 2018 18:31:09 +0200 Subject: [PATCH 039/428] Frio - rise version --- view/theme/frio/theme.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/theme/frio/theme.php b/view/theme/frio/theme.php index 4e01289624..72e5ab0b61 100644 --- a/view/theme/frio/theme.php +++ b/view/theme/frio/theme.php @@ -2,7 +2,7 @@ /* * Name: frio * Description: Bootstrap V3 theme. The theme is currently under construction, so it is far from finished. For further information have a look at the ReadMe. - * Version: V.0.8 + * Version: V.0.8.5 * Author: Rabuzarus * */ From 1fe16282370ebec7218537e763e35f608bb68a17 Mon Sep 17 00:00:00 2001 From: rabuzarus Date: Wed, 5 Sep 2018 18:44:47 +0200 Subject: [PATCH 040/428] lockview - prevent notices --- mod/lockview.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mod/lockview.php b/mod/lockview.php index 0d87e15510..a2301b4ccb 100644 --- a/mod/lockview.php +++ b/mod/lockview.php @@ -47,7 +47,8 @@ function lockview_content(App $a) killme(); } - if ($item['private'] == 1 + if (isset($item['private']) + && $item['private'] == 1 && empty($item['allow_cid']) && empty($item['allow_gid']) && empty($item['deny_cid']) From f148dcabc45c2c793f28518aa2deec6d51826546 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 5 Sep 2018 22:16:23 +0200 Subject: [PATCH 041/428] CacheLockDriverTest Fixings - Changing test behaviour --- .../Core/Lock/ArrayCacheLockDriverTest.php | 14 +------ tests/src/Core/Lock/LockTest.php | 37 +++++++++++++------ .../Core/Lock/MemcacheCacheLockDriverTest.php | 15 +------- .../Lock/MemcachedCacheLockDriverTest.php | 15 +------- .../Core/Lock/RedisCacheLockDriverTest.php | 15 +------- .../src/Core/Lock/SemaphoreLockDriverTest.php | 15 +------- 6 files changed, 31 insertions(+), 80 deletions(-) diff --git a/tests/src/Core/Lock/ArrayCacheLockDriverTest.php b/tests/src/Core/Lock/ArrayCacheLockDriverTest.php index dc044f5c5c..671341718b 100644 --- a/tests/src/Core/Lock/ArrayCacheLockDriverTest.php +++ b/tests/src/Core/Lock/ArrayCacheLockDriverTest.php @@ -8,21 +8,9 @@ use Friendica\Core\Lock\CacheLockDriver; class ArrayCacheLockDriverTest extends LockTest { - /** - * @var \Friendica\Core\Cache\IMemoryCacheDriver - */ - private $cache; - protected function getInstance() { - $this->cache = new ArrayCache(); - return new CacheLockDriver($this->cache); - } - - public function tearDown() - { - $this->cache->clear(); - parent::tearDown(); + return new CacheLockDriver(new ArrayCache()); } public function testLockTTL() diff --git a/tests/src/Core/Lock/LockTest.php b/tests/src/Core/Lock/LockTest.php index 9698f0bdea..a7bbea265f 100644 --- a/tests/src/Core/Lock/LockTest.php +++ b/tests/src/Core/Lock/LockTest.php @@ -19,6 +19,7 @@ abstract class LockTest extends DatabaseTest { parent::setUp(); $this->instance = $this->getInstance(); + $this->instance->releaseAll(); // Reusable App object $this->app = BaseObject::getApp(); @@ -31,11 +32,18 @@ abstract class LockTest extends DatabaseTest Config::set('system', 'theme', 'system_theme'); } + protected function tearDown() + { + parent::tearDown(); + $this->instance->releaseAll(); + } + /** * @small */ public function testLock() { - $this->instance->acquireLock('foo', 1); + $this->assertFalse($this->instance->isLocked('foo')); + $this->assertTrue($this->instance->acquireLock('foo', 1)); $this->assertTrue($this->instance->isLocked('foo')); $this->assertFalse($this->instance->isLocked('bar')); } @@ -44,7 +52,8 @@ abstract class LockTest extends DatabaseTest * @small */ public function testDoubleLock() { - $this->instance->acquireLock('foo', 1); + $this->assertFalse($this->instance->isLocked('foo')); + $this->assertTrue($this->instance->acquireLock('foo', 1)); $this->assertTrue($this->instance->isLocked('foo')); // We already locked it $this->assertTrue($this->instance->acquireLock('foo', 1)); @@ -54,7 +63,8 @@ abstract class LockTest extends DatabaseTest * @small */ public function testReleaseLock() { - $this->instance->acquireLock('foo', 1); + $this->assertFalse($this->instance->isLocked('foo')); + $this->assertTrue($this->instance->acquireLock('foo', 1)); $this->assertTrue($this->instance->isLocked('foo')); $this->instance->releaseLock('foo'); $this->assertFalse($this->instance->isLocked('foo')); @@ -64,9 +74,9 @@ abstract class LockTest extends DatabaseTest * @small */ public function testReleaseAll() { - $this->instance->acquireLock('foo', 1); - $this->instance->acquireLock('bar', 1); - $this->instance->acquireLock('nice', 1); + $this->assertTrue($this->instance->acquireLock('foo', 1)); + $this->assertTrue($this->instance->acquireLock('bar', 1)); + $this->assertTrue($this->instance->acquireLock('nice', 1)); $this->assertTrue($this->instance->isLocked('foo')); $this->assertTrue($this->instance->isLocked('bar')); @@ -83,9 +93,12 @@ abstract class LockTest extends DatabaseTest * @small */ public function testReleaseAfterUnlock() { - $this->instance->acquireLock('foo', 1); - $this->instance->acquireLock('bar', 1); - $this->instance->acquireLock('nice', 1); + $this->assertFalse($this->instance->isLocked('foo')); + $this->assertFalse($this->instance->isLocked('bar')); + $this->assertFalse($this->instance->isLocked('nice')); + $this->assertTrue($this->instance->acquireLock('foo', 1)); + $this->assertTrue($this->instance->acquireLock('bar', 1)); + $this->assertTrue($this->instance->acquireLock('nice', 1)); $this->instance->releaseLock('foo'); @@ -103,10 +116,12 @@ abstract class LockTest extends DatabaseTest * @medium */ function testLockTTL() { + $this->assertFalse($this->instance->isLocked('foo')); + $this->assertFalse($this->instance->isLocked('bar')); // TODO [nupplaphil] - Because of the Datetime-Utils for the database, we have to wait a FULL second between the checks to invalidate the db-locks/cache - $this->instance->acquireLock('foo', 1, 1); - $this->instance->acquireLock('bar', 1, 3); + $this->assertTrue($this->instance->acquireLock('foo', 2, 1)); + $this->assertTrue($this->instance->acquireLock('bar', 2, 3)); $this->assertTrue($this->instance->isLocked('foo')); $this->assertTrue($this->instance->isLocked('bar')); diff --git a/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php b/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php index c54cf9c599..ca9b9b4639 100644 --- a/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php +++ b/tests/src/Core/Lock/MemcacheCacheLockDriverTest.php @@ -3,7 +3,6 @@ namespace Friendica\Test\src\Core\Lock; - use Friendica\Core\Cache\CacheDriverFactory; use Friendica\Core\Lock\CacheLockDriver; @@ -12,20 +11,8 @@ use Friendica\Core\Lock\CacheLockDriver; */ class MemcacheCacheLockDriverTest extends LockTest { - /** - * @var \Friendica\Core\Cache\IMemoryCacheDriver - */ - private $cache; - protected function getInstance() { - $this->cache = CacheDriverFactory::create('memcache'); - return new CacheLockDriver($this->cache); - } - - public function tearDown() - { - $this->cache->clear(); - parent::tearDown(); + return new CacheLockDriver(CacheDriverFactory::create('memcache')); } } diff --git a/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php b/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php index 27886261b2..71311d5baa 100644 --- a/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php +++ b/tests/src/Core/Lock/MemcachedCacheLockDriverTest.php @@ -3,7 +3,6 @@ namespace Friendica\Test\src\Core\Lock; - use Friendica\Core\Cache\CacheDriverFactory; use Friendica\Core\Lock\CacheLockDriver; @@ -12,20 +11,8 @@ use Friendica\Core\Lock\CacheLockDriver; */ class MemcachedCacheLockDriverTest extends LockTest { - /** - * @var \Friendica\Core\Cache\IMemoryCacheDriver - */ - private $cache; - protected function getInstance() { - $this->cache = CacheDriverFactory::create('memcached'); - return new CacheLockDriver($this->cache); - } - - public function tearDown() - { - $this->cache->clear(); - parent::tearDown(); + return new CacheLockDriver(CacheDriverFactory::create('memcached')); } } diff --git a/tests/src/Core/Lock/RedisCacheLockDriverTest.php b/tests/src/Core/Lock/RedisCacheLockDriverTest.php index eaafbf4e44..43cedb9cbc 100644 --- a/tests/src/Core/Lock/RedisCacheLockDriverTest.php +++ b/tests/src/Core/Lock/RedisCacheLockDriverTest.php @@ -3,7 +3,6 @@ namespace Friendica\Test\src\Core\Lock; - use Friendica\Core\Cache\CacheDriverFactory; use Friendica\Core\Lock\CacheLockDriver; @@ -12,21 +11,9 @@ use Friendica\Core\Lock\CacheLockDriver; */ class RedisCacheLockDriverTest extends LockTest { - /** - * @var \Friendica\Core\Cache\IMemoryCacheDriver - */ - private $cache; - protected function getInstance() { - $this->cache = CacheDriverFactory::create('redis'); - return new CacheLockDriver($this->cache); + return new CacheLockDriver(CacheDriverFactory::create('redis')); } - - public function tearDown() - { - $this->cache->clear(); - parent::tearDown(); - } } diff --git a/tests/src/Core/Lock/SemaphoreLockDriverTest.php b/tests/src/Core/Lock/SemaphoreLockDriverTest.php index cd4b915733..39f0763fb1 100644 --- a/tests/src/Core/Lock/SemaphoreLockDriverTest.php +++ b/tests/src/Core/Lock/SemaphoreLockDriverTest.php @@ -2,26 +2,13 @@ namespace Friendica\Test\src\Core\Lock; - use Friendica\Core\Lock\SemaphoreLockDriver; class SemaphoreLockDriverTest extends LockTest { - /** - * @var \Friendica\Core\Lock\SemaphoreLockDriver - */ - private $semaphoreLockDriver; - protected function getInstance() { - $this->semaphoreLockDriver = new SemaphoreLockDriver(); - return $this->semaphoreLockDriver; - } - - public function tearDown() - { - $this->semaphoreLockDriver->releaseAll(); - parent::tearDown(); + return new SemaphoreLockDriver(); } function testLockTTL() From 75a2576f7896d97d1e4127ee9563c0c8927bb5f8 Mon Sep 17 00:00:00 2001 From: rabuzarus Date: Thu, 6 Sep 2018 01:42:35 +0200 Subject: [PATCH 042/428] use magic links in single event view --- src/Model/Event.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Model/Event.php b/src/Model/Event.php index 992b77bada..016d1f8d9e 100644 --- a/src/Model/Event.php +++ b/src/Model/Event.php @@ -12,6 +12,7 @@ use Friendica\Core\L10n; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBA; +use Friendica\Model\Contact; use Friendica\Util\DateTimeFormat; use Friendica\Util\Map; @@ -589,6 +590,12 @@ class Event extends BaseObject $title = strip_tags(html_entity_decode($title, ENT_QUOTES, 'UTF-8')); } + $author_link = $event['author-link']; + $plink = $event['plink']; + + $event['author-link'] = Contact::magicLink($author_link); + $event['plink'] = Contact::magicLink($author_link, $plink); + $html = self::getHTML($event); $event['desc'] = BBCode::convert($event['desc']); $event['location'] = BBCode::convert($event['location']); From 04fb88585783f4883b40ec9d49a4a7fa644fb294 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 6 Sep 2018 04:24:34 +0000 Subject: [PATCH 043/428] Fix: Posts with pictures will now look good again on connector networks --- mod/photos.php | 2 +- src/Content/Text/BBCode.php | 5 ++++- src/Util/ParseUrl.php | 10 +++------- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/mod/photos.php b/mod/photos.php index 5fb6ba3683..16af455997 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -1633,7 +1633,7 @@ function photos_content(App $a) '$paginate' => $paginate, ]); - $a->page['htmlhead'] .= "\n" . '' . "\n"; + $a->page['htmlhead'] .= "\n" . '' . "\n"; $a->page['htmlhead'] .= '' . "\n"; $a->page['htmlhead'] .= '' . "\n"; $a->page['htmlhead'] .= '' . "\n"; diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 55fc24273d..3054170fc0 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -578,7 +578,10 @@ class BBCode extends BaseObject $return .= sprintf('
', $data["url"], self::proxyUrl($data["preview"], $simplehtml), $data["title"]); } - if (!empty($data['title']) && !empty($data['url'])) { + // Show a picture only when the BBCode is meant for posts to connector networks + if (($simplehtml != 0) && ($data["type"] == "photo") && !empty($data["url"]) && !empty($data["image"])) { + $return .= sprintf('', $data["url"], self::proxyUrl($data["image"], $simplehtml), $data["title"]); + } elseif (!empty($data['title']) && !empty($data['url'])) { $return .= sprintf('

%s

', $data['url'], $data['title']); } diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index 2c134542a0..520100b6d7 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -271,9 +271,9 @@ class ParseUrl $siteinfo['image'] = $meta_tag['content']; break; case 'twitter:card': - // Obsolete card type - if ($meta_tag['content'] == 'photo') { - $siteinfo['type'] = 'summary_large_image'; + // Convert Twitter types in our own + if ($meta_tag['content'] == 'summary_large_image') { + $siteinfo['type'] = 'photo'; } else { $siteinfo['type'] = $meta_tag['content']; } @@ -299,10 +299,6 @@ class ParseUrl } } - if ($siteinfo['type'] == 'summary' || $siteinfo['type'] == 'summary_large_image') { - $siteinfo['type'] = 'link'; - } - if (isset($keywords)) { $siteinfo['keywords'] = []; foreach ($keywords as $keyword) { From bd2b3b1ef5e066f927bf8ae95954dd4569319bca Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Thu, 6 Sep 2018 08:11:18 +0200 Subject: [PATCH 044/428] LockDriverFixings - release Locks in case of failures - adding some cache tests --- src/Core/Cache/ArrayCache.php | 5 +++++ src/Core/Worker.php | 2 ++ src/Model/Item.php | 1 + tests/src/Core/Cache/CacheTest.php | 24 +++++++++++++++++++----- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Core/Cache/ArrayCache.php b/src/Core/Cache/ArrayCache.php index b198287148..d1302c1d6e 100644 --- a/src/Core/Cache/ArrayCache.php +++ b/src/Core/Cache/ArrayCache.php @@ -53,6 +53,11 @@ class ArrayCache extends AbstractCacheDriver implements IMemoryCacheDriver */ public function clear($outdated = true) { + // Array doesn't support TTL so just don't delete something + if ($outdated) { + return true; + } + $this->cachedData = []; return true; } diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 9dd973728d..3400f00ae1 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -117,12 +117,14 @@ class Worker // Count active workers and compare them with a maximum value that depends on the load if (self::tooMuchWorkers()) { logger('Active worker limit reached, quitting.', LOGGER_DEBUG); + Lock::release('worker'); return; } // Check free memory if ($a->min_memory_reached()) { logger('Memory limit reached, quitting.', LOGGER_DEBUG); + Lock::release('worker'); return; } Lock::release('worker'); diff --git a/src/Model/Item.php b/src/Model/Item.php index d235f0a7f9..10c705a995 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1936,6 +1936,7 @@ class Item extends BaseObject } else { // This shouldn't happen. logger('Could not insert activity for URI ' . $item['uri'] . ' - should not happen'); + Lock::release('item_insert_activity'); return false; } if ($locked) { diff --git a/tests/src/Core/Cache/CacheTest.php b/tests/src/Core/Cache/CacheTest.php index 105142f0b7..5c56c2072f 100644 --- a/tests/src/Core/Cache/CacheTest.php +++ b/tests/src/Core/Cache/CacheTest.php @@ -81,19 +81,33 @@ abstract class CacheTest extends DatabaseTest '3_value1' => $this->instance->get('3_value1'), ]); - $this->assertTrue($this->instance->clear(false)); + $this->assertTrue($this->instance->clear()); $this->assertEquals([ - '1_value1' => null, - '1_value2' => null, - '2_value1' => null, - '3_value1' => null, + '1_value1' => 'ipsum lorum1', + '1_value2' => 'ipsum lorum2', + '2_value1' => 'ipsum lorum3', + '3_value1' => 'ipsum lorum4', ], [ '1_value1' => $this->instance->get('1_value1'), '1_value2' => $this->instance->get('1_value2'), '2_value1' => $this->instance->get('2_value1'), '3_value1' => $this->instance->get('3_value1'), ]); + + $this->assertTrue($this->instance->clear(false)); + + $this->assertEquals([ + '1_value1' => null, + '1_value2' => null, + '2_value3' => null, + '3_value4' => null, + ], [ + '1_value1' => $this->instance->get('1_value1'), + '1_value2' => $this->instance->get('1_value2'), + '2_value3' => $this->instance->get('2_value3'), + '3_value4' => $this->instance->get('3_value4'), + ]); } /** From f84b39be0b4e7d037c41157537f2864d3f6b7ef4 Mon Sep 17 00:00:00 2001 From: Aditoo17 <42938951+Aditoo17@users.noreply.github.com> Date: Thu, 6 Sep 2018 10:43:15 +0200 Subject: [PATCH 045/428] Fix iframe address --- doc/Quick-Start-groupsandpages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Quick-Start-groupsandpages.md b/doc/Quick-Start-groupsandpages.md index 652407d642..d4680f65f2 100644 --- a/doc/Quick-Start-groupsandpages.md +++ b/doc/Quick-Start-groupsandpages.md @@ -15,6 +15,6 @@ Remember the link at the top of this page will bring you back here. Once you've added some groups, move on to the next section. - + From 6113fdc940d77fba1871463ee0c5a27e1f22eda7 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 6 Sep 2018 09:20:45 +0000 Subject: [PATCH 046/428] Issue 5733: Changing relationship values does work now again with DFRN --- mod/dfrn_notify.php | 2 +- src/Protocol/Diaspora.php | 37 +++++++++++++++++++++++++++++-------- src/Protocol/OStatus.php | 14 ++++++++++++-- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index f653faca95..666c388a4a 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -182,7 +182,7 @@ function dfrn_notify_post(App $a) { function dfrn_dispatch_public($postdata) { - $msg = Diaspora::decodeRaw([], $postdata); + $msg = Diaspora::decodeRaw([], $postdata, true); if (!$msg) { // We have to fail silently to be able to hand it over to the salmon parser return false; diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index c25eb96898..7af8dbd424 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -365,15 +365,16 @@ class Diaspora /** * @brief: Decodes incoming Diaspora message in the new format * - * @param array $importer Array of the importer user - * @param string $raw raw post message + * @param array $importer Array of the importer user + * @param string $raw raw post message + * @param boolean $no_exit Don't do an http exit on error * * @return array * 'message' -> decoded Diaspora XML message * 'author' -> author diaspora handle * 'key' -> author public key (converted to pkcs#8) */ - public static function decodeRaw(array $importer, $raw) + public static function decodeRaw(array $importer, $raw, $no_exit = false) { $data = json_decode($raw); @@ -388,7 +389,11 @@ class Diaspora if (!is_object($j_outer_key_bundle)) { logger('Outer Salmon did not verify. Discarding.'); - System::httpExit(400); + if ($no_exit) { + return false; + } else { + System::httpExit(400); + } } $outer_iv = base64_decode($j_outer_key_bundle->iv); @@ -403,7 +408,11 @@ class Diaspora if (!is_object($basedom)) { logger('Received data does not seem to be an XML. Discarding. '.$xml); - System::httpExit(400); + if ($no_exit) { + return false; + } else { + System::httpExit(400); + } } $base = $basedom->children(NAMESPACE_SALMON_ME); @@ -425,19 +434,31 @@ class Diaspora $author_addr = base64_decode($key_id); if ($author_addr == '') { logger('No author could be decoded. Discarding. Message: ' . $xml); - System::httpExit(400); + if ($no_exit) { + return false; + } else { + System::httpExit(400); + } } $key = self::key($author_addr); if ($key == '') { logger("Couldn't get a key for handle " . $author_addr . ". Discarding."); - System::httpExit(400); + if ($no_exit) { + return false; + } else { + System::httpExit(400); + } } $verify = Crypto::rsaVerify($signed_data, $signature, $key); if (!$verify) { logger('Message did not verify. Discarding.'); - System::httpExit(400); + if ($no_exit) { + return false; + } else { + System::httpExit(400); + } } return ['message' => (string)base64url_decode($base->data), diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index 551b4ad887..ece265c99b 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -74,6 +74,16 @@ class OStatus $author["contact-id"] = $contact["id"]; $contact = null; + +/* + This here would be better, but we would get problems with contacts from the statusnet addon + This is kept here as a reminder for the future + + $cid = Contact::getIdForURL($author["author-link"], $importer["uid"]); + if ($cid) { + $contact = DBA::selectFirst('contact', [], ['id' => $cid]); + } +*/ if ($aliaslink != '') { $condition = ["`uid` = ? AND `alias` = ? AND `network` != ? AND `rel` IN (?, ?)", $importer["uid"], $aliaslink, Protocol::STATUSNET, @@ -219,7 +229,7 @@ class OStatus $gcid = GContact::update($contact); GContact::link($gcid, $contact["uid"], $contact["id"]); - } else { + } elseif ($contact["network"] != Protocol::DFRN) { $contact = null; } @@ -312,7 +322,7 @@ class OStatus self::$conv_list = []; } - logger("Import OStatus message", LOGGER_DEBUG); + logger('Import OStatus message for user ' . $importer['uid'], LOGGER_DEBUG); if ($xml == "") { return false; From 26607d4a275c6f2973287836439f5e9b805511d1 Mon Sep 17 00:00:00 2001 From: rabuzarus Date: Thu, 6 Sep 2018 14:40:34 +0200 Subject: [PATCH 047/428] Frio - bugfix - don't show new event button if the button isn't available --- view/theme/frio/templates/events_js.tpl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/view/theme/frio/templates/events_js.tpl b/view/theme/frio/templates/events_js.tpl index 31debbe310..a4ca9004cd 100644 --- a/view/theme/frio/templates/events_js.tpl +++ b/view/theme/frio/templates/events_js.tpl @@ -3,11 +3,13 @@ {{include file="section_title.tpl" title=$title pullright=1}} {{* The link to create a new event *}} + {{if $new_event.0}} + {{/if}} {{* We create our own fullcallendar header (with title & calendar view *}}
From e9a73e4480154fd69195401c970e444159f87964 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 6 Sep 2018 13:27:03 +0000 Subject: [PATCH 048/428] Fix fatal error due to missing "use" --- src/Module/Proxy.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Module/Proxy.php b/src/Module/Proxy.php index 7983e01f7a..0de45b3325 100644 --- a/src/Module/Proxy.php +++ b/src/Module/Proxy.php @@ -8,6 +8,7 @@ namespace Friendica\Module; use Friendica\App; use Friendica\BaseModule; use Friendica\Core\Config; +use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model\Photo; From 1d4a5402ff1a63ea3f2bd17d834ebce74f44379f Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 6 Sep 2018 20:30:16 +0000 Subject: [PATCH 049/428] Picture posts do work again - everything else should work as well --- src/Content/Text/BBCode.php | 22 +++++++++++----------- src/Util/ParseUrl.php | 9 ++++++--- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 3054170fc0..2dc13ae5e0 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -572,17 +572,17 @@ class BBCode extends BaseObject $return = sprintf('
', $data["type"]); } - if (!empty($data["image"])) { - $return .= sprintf('
', $data["url"], self::proxyUrl($data["image"], $simplehtml), $data["title"]); - } elseif (!empty($data["preview"])) { - $return .= sprintf('
', $data["url"], self::proxyUrl($data["preview"], $simplehtml), $data["title"]); - } - - // Show a picture only when the BBCode is meant for posts to connector networks - if (($simplehtml != 0) && ($data["type"] == "photo") && !empty($data["url"]) && !empty($data["image"])) { - $return .= sprintf('', $data["url"], self::proxyUrl($data["image"], $simplehtml), $data["title"]); - } elseif (!empty($data['title']) && !empty($data['url'])) { - $return .= sprintf('

%s

', $data['url'], $data['title']); + if (!empty($data['title']) && !empty($data['url'])) { + if (!empty($data["image"]) && empty($data["text"]) && ($data["type"] == "photo")) { + $return .= sprintf('', $data["url"], self::proxyUrl($data["image"], $simplehtml), $data["title"]); + } else { + if (!empty($data["image"])) { + $return .= sprintf('
', $data["url"], self::proxyUrl($data["image"], $simplehtml), $data["title"]); + } elseif (!empty($data["preview"])) { + $return .= sprintf('
', $data["url"], self::proxyUrl($data["preview"], $simplehtml), $data["title"]); + } + $return .= sprintf('

%s

', $data['url'], $data['title']); + } } if (!empty($data["description"]) && $data["description"] != $data["title"]) { diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index 520100b6d7..4443da7564 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -271,11 +271,9 @@ class ParseUrl $siteinfo['image'] = $meta_tag['content']; break; case 'twitter:card': - // Convert Twitter types in our own + // Detect photo pages if ($meta_tag['content'] == 'summary_large_image') { $siteinfo['type'] = 'photo'; - } else { - $siteinfo['type'] = $meta_tag['content']; } break; case 'twitter:description': @@ -334,6 +332,11 @@ class ParseUrl } } + // Prevent to have a photo type without an image + if (empty($siteinfo['image']) && (siteinfo['type'] == 'photo')) { + $siteinfo['type'] = 'link'; + } + if ((@$siteinfo['image'] == '') && !$no_guessing) { $list = $xpath->query('//img[@src]'); foreach ($list as $node) { From 2592c3891ce3134d591c890c7bd7f789f554f208 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 6 Sep 2018 21:10:48 +0000 Subject: [PATCH 050/428] forgotten $ --- src/Util/ParseUrl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index 4443da7564..dd39a052a0 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -333,7 +333,7 @@ class ParseUrl } // Prevent to have a photo type without an image - if (empty($siteinfo['image']) && (siteinfo['type'] == 'photo')) { + if (empty($siteinfo['image']) && ($siteinfo['type'] == 'photo')) { $siteinfo['type'] = 'link'; } From 2f7ba1370226bbcb97fd6b9f9b737b8462ce97ac Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 6 Sep 2018 18:42:57 -0400 Subject: [PATCH 051/428] Restore display when there aren't unread notifications --- mod/notifications.php | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/mod/notifications.php b/mod/notifications.php index 091323d998..5feb3be19a 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -308,18 +308,15 @@ function notifications_content(App $a) '$item_seen' => $it['seen'], ]); } - - $notif_show_lnk = [ - 'href' => ($show ? 'notifications/'.$notifs['ident'] : 'notifications/'.$notifs['ident'].'?show=all' ), - 'text' => ($show ? L10n::t('Show unread') : L10n::t('Show all')), - ]; - - // Output if there aren't any notifications available - if (count($notifs['notifications']) == 0) { - $notif_nocontent = L10n::t('No more %s notifications.', $notifs['ident']); - } + } else { + $notif_nocontent = L10n::t('No more %s notifications.', $notifs['ident']); } + $notif_show_lnk = [ + 'href' => ($show ? 'notifications/'.$notifs['ident'] : 'notifications/'.$notifs['ident'].'?show=all' ), + 'text' => ($show ? L10n::t('Show unread') : L10n::t('Show all')), + ]; + $o .= replace_macros($notif_tpl, [ '$notif_header' => $notif_header, '$tabs' => $tabs, From f85af78097d2ab73a9ee4b020a6a366f3a147de3 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 6 Sep 2018 18:55:06 -0400 Subject: [PATCH 052/428] Source format mod/notifications - Add array alignment - Convert remaining double quotes to quotes - Replace x() with defaults() - Add missing spaces --- mod/notifications.php | 221 +++++++++++++++++++----------------------- 1 file changed, 101 insertions(+), 120 deletions(-) diff --git a/mod/notifications.php b/mod/notifications.php index 5feb3be19a..212736305f 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -21,7 +21,7 @@ function notifications_post(App $a) $request_id = (($a->argc > 1) ? $a->argv[1] : 0); - if ($request_id === "all") { + if ($request_id === 'all') { return; } @@ -68,8 +68,8 @@ function notifications_content(App $a) return; } - $page = (x($_REQUEST,'page') ? $_REQUEST['page'] : 1); - $show = (x($_REQUEST,'show') ? $_REQUEST['show'] : 0); + $page = defaults($_REQUEST, 'page', 1); + $show = defaults($_REQUEST, 'show', 0); Nav::setSelected('notifications'); @@ -118,7 +118,6 @@ function notifications_content(App $a) $notifs = $nm->homeNotifs($show, $startrec, $perpage); } - // Set the pager $a->set_pager_itemspage($perpage); @@ -136,7 +135,7 @@ function notifications_content(App $a) // Process the data for template creation if (defaults($notifs, 'ident', '') === 'introductions') { $sugg = get_markup_template('suggestions.tpl'); - $tpl = get_markup_template("intros.tpl"); + $tpl = get_markup_template('intros.tpl'); // The link to switch between ignored and normal connection requests $notif_show_lnk = [ @@ -146,127 +145,121 @@ function notifications_content(App $a) // Loop through all introduction notifications.This creates an array with the output html for each // introduction - foreach ($notifs['notifications'] as $it) { + foreach ($notifs['notifications'] as $notif) { // There are two kind of introduction. Contacts suggested by other contacts and normal connection requests. // We have to distinguish between these two because they use different data. - switch ($it['label']) { + switch ($notif['label']) { case 'friend_suggestion': $notif_content[] = replace_macros($sugg, [ - '$type' => $it['label'], + '$type' => $notif['label'], '$str_notifytype' => L10n::t('Notification type:'), - '$notify_type' => $it['notify_type'], - '$intro_id' => $it['intro_id'], + '$notify_type'=> $notif['notify_type'], + '$intro_id' => $notif['intro_id'], '$lbl_madeby' => L10n::t('Suggested by:'), - '$madeby' => $it['madeby'], - '$madeby_url' => $it['madeby_url'], - '$madeby_zrl' => $it['madeby_zrl'], - '$madeby_addr' => $it['madeby_addr'], - '$contact_id' => $it['contact_id'], - '$photo' => $it['photo'], - '$fullname' => $it['name'], - '$url' => $it['url'], - '$zrl' => $it['zrl'], - '$lbl_url' => L10n::t('Profile URL'), - '$addr' => $it['addr'], - '$hidden' => ['hidden', L10n::t('Hide this contact from others'), ($it['hidden'] == 1), ''], - - '$knowyou' => $it['knowyou'], - '$approve' => L10n::t('Approve'), - '$note' => $it['note'], - '$request' => $it['request'], - '$ignore' => L10n::t('Ignore'), - '$discard' => L10n::t('Discard'), + '$madeby' => $notif['madeby'], + '$madeby_url' => $notif['madeby_url'], + '$madeby_zrl' => $notif['madeby_zrl'], + '$madeby_addr'=> $notif['madeby_addr'], + '$contact_id' => $notif['contact_id'], + '$photo' => $notif['photo'], + '$fullname' => $notif['name'], + '$url' => $notif['url'], + '$zrl' => $notif['zrl'], + '$lbl_url' => L10n::t('Profile URL'), + '$addr' => $notif['addr'], + '$hidden' => ['hidden', L10n::t('Hide this contact from others'), ($notif['hidden'] == 1), ''], + '$knowyou' => $notif['knowyou'], + '$approve' => L10n::t('Approve'), + '$note' => $notif['note'], + '$request' => $notif['request'], + '$ignore' => L10n::t('Ignore'), + '$discard' => L10n::t('Discard'), ]); break; // Normal connection requests default: - $friend_selected = (($it['network'] !== Protocol::OSTATUS) ? ' checked="checked" ' : ' disabled '); - $fan_selected = (($it['network'] === Protocol::OSTATUS) ? ' checked="checked" disabled ' : ''); - $dfrn_tpl = get_markup_template('netfriend.tpl'); + $friend_selected = (($notif['network'] !== Protocol::OSTATUS) ? ' checked="checked" ' : ' disabled '); + $fan_selected = (($notif['network'] === Protocol::OSTATUS) ? ' checked="checked" disabled ' : ''); - $knowyou = ''; $lbl_knowyou = ''; - $dfrn_text = ''; - $helptext = ''; - $helptext2 = ''; - $helptext3 = ''; + $knowyou = ''; + $helptext = ''; + $helptext2 = ''; + $helptext3 = ''; - if ($it['network'] === Protocol::DFRN || $it['network'] === Protocol::DIASPORA) { - if ($it['network'] === Protocol::DFRN) { - $lbl_knowyou = L10n::t('Claims to be known to you: '); - $knowyou = (($it['knowyou']) ? L10n::t('yes') : L10n::t('no')); - $helptext = L10n::t('Shall your connection be bidirectional or not?'); - $helptext2 = L10n::t('Accepting %s as a friend allows %s to subscribe to your posts, and you will also receive updates from them in your news feed.', $it['name'], $it['name']); - $helptext3 = L10n::t('Accepting %s as a subscriber allows them to subscribe to your posts, but you will not receive updates from them in your news feed.', $it['name']); - } else { - $knowyou = ''; - $helptext = L10n::t('Shall your connection be bidirectional or not?'); - $helptext2 = L10n::t('Accepting %s as a friend allows %s to subscribe to your posts, and you will also receive updates from them in your news feed.', $it['name'], $it['name']); - $helptext3 = L10n::t('Accepting %s as a sharer allows them to subscribe to your posts, but you will not receive updates from them in your news feed.', $it['name']); - } + if ($notif['network'] === Protocol::DFRN) { + $lbl_knowyou = L10n::t('Claims to be known to you: '); + $knowyou = (($notif['knowyou']) ? L10n::t('yes') : L10n::t('no')); + $helptext = L10n::t('Shall your connection be bidirectional or not?'); + $helptext2 = L10n::t('Accepting %s as a friend allows %s to subscribe to your posts, and you will also receive updates from them in your news feed.', $notif['name'], $notif['name']); + $helptext3 = L10n::t('Accepting %s as a subscriber allows them to subscribe to your posts, but you will not receive updates from them in your news feed.', $notif['name']); + } elseif ($notif['network'] === Protocol::DIASPORA) { + $helptext = L10n::t('Shall your connection be bidirectional or not?'); + $helptext2 = L10n::t('Accepting %s as a friend allows %s to subscribe to your posts, and you will also receive updates from them in your news feed.', $notif['name'], $notif['name']); + $helptext3 = L10n::t('Accepting %s as a sharer allows them to subscribe to your posts, but you will not receive updates from them in your news feed.', $notif['name']); } - $dfrn_text = replace_macros($dfrn_tpl,[ - '$intro_id' => $it['intro_id'], + $dfrn_tpl = get_markup_template('netfriend.tpl'); + $dfrn_text = replace_macros($dfrn_tpl, [ + '$intro_id' => $notif['intro_id'], '$friend_selected' => $friend_selected, - '$fan_selected' => $fan_selected, + '$fan_selected'=> $fan_selected, '$approve_as1' => $helptext, '$approve_as2' => $helptext2, '$approve_as3' => $helptext3, - '$as_friend' => L10n::t('Friend'), - '$as_fan' => (($it['network'] == Protocol::DIASPORA) ? L10n::t('Sharer') : L10n::t('Subscriber')) + '$as_friend' => L10n::t('Friend'), + '$as_fan' => (($notif['network'] == Protocol::DIASPORA) ? L10n::t('Sharer') : L10n::t('Subscriber')) ]); - $header = $it["name"]; + $header = $notif['name']; - if ($it["addr"] != "") { - $header .= " <".$it["addr"].">"; + if ($notif['addr'] != '') { + $header .= ' <' . $notif['addr'] . '>'; } - $header .= " (".ContactSelector::networkToName($it['network'], $it['url']).")"; + $header .= ' (' . ContactSelector::networkToName($notif['network'], $notif['url']) . ')'; - if ($it['network'] != Protocol::DIASPORA) { + if ($notif['network'] != Protocol::DIASPORA) { $discard = L10n::t('Discard'); } else { $discard = ''; } $notif_content[] = replace_macros($tpl, [ - '$type' => $it['label'], - '$header' => htmlentities($header), + '$type' => $notif['label'], + '$header' => htmlentities($header), '$str_notifytype' => L10n::t('Notification type:'), - '$notify_type' => $it['notify_type'], - '$dfrn_text' => $dfrn_text, - '$dfrn_id' => $it['dfrn_id'], - '$uid' => $it['uid'], - '$intro_id' => $it['intro_id'], - '$contact_id' => $it['contact_id'], - '$photo' => $it['photo'], - '$fullname' => $it['name'], - '$location' => $it['location'], - '$lbl_location' => L10n::t('Location:'), - '$about' => $it['about'], - '$lbl_about' => L10n::t('About:'), - '$keywords' => $it['keywords'], - '$lbl_keywords' => L10n::t('Tags:'), - '$gender' => $it['gender'], - '$lbl_gender' => L10n::t('Gender:'), - '$hidden' => ['hidden', L10n::t('Hide this contact from others'), ($it['hidden'] == 1), ''], - '$url' => $it['url'], - '$zrl' => $it['zrl'], - '$lbl_url' => L10n::t('Profile URL'), - '$addr' => $it['addr'], + '$notify_type' => $notif['notify_type'], + '$dfrn_text' => $dfrn_text, + '$dfrn_id' => $notif['dfrn_id'], + '$uid' => $notif['uid'], + '$intro_id' => $notif['intro_id'], + '$contact_id' => $notif['contact_id'], + '$photo' => $notif['photo'], + '$fullname' => $notif['name'], + '$location' => $notif['location'], + '$lbl_location'=> L10n::t('Location:'), + '$about' => $notif['about'], + '$lbl_about' => L10n::t('About:'), + '$keywords' => $notif['keywords'], + '$lbl_keywords'=> L10n::t('Tags:'), + '$gender' => $notif['gender'], + '$lbl_gender' => L10n::t('Gender:'), + '$hidden' => ['hidden', L10n::t('Hide this contact from others'), ($notif['hidden'] == 1), ''], + '$url' => $notif['url'], + '$zrl' => $notif['zrl'], + '$lbl_url' => L10n::t('Profile URL'), + '$addr' => $notif['addr'], '$lbl_knowyou' => $lbl_knowyou, '$lbl_network' => L10n::t('Network:'), - '$network' => ContactSelector::networkToName($it['network'], $it['url']), - '$knowyou' => $knowyou, - '$approve' => L10n::t('Approve'), - '$note' => $it['note'], - '$ignore' => L10n::t('Ignore'), - '$discard' => $discard, - + '$network' => ContactSelector::networkToName($notif['network'], $notif['url']), + '$knowyou' => $knowyou, + '$approve' => L10n::t('Approve'), + '$note' => $notif['note'], + '$ignore' => L10n::t('Ignore'), + '$discard' => $discard, ]); break; } @@ -276,36 +269,24 @@ function notifications_content(App $a) info(L10n::t('No introductions.') . EOL); } - // Normal notifications (no introductions) + // Normal notifications (no introductions) } elseif (!empty($notifs['notifications'])) { - // The template files we need in different cases for formatting the content - $tpl_item_like = 'notifications_likes_item.tpl'; - $tpl_item_dislike = 'notifications_dislikes_item.tpl'; - $tpl_item_attend = 'notifications_attend_item.tpl'; - $tpl_item_attendno = 'notifications_attend_item.tpl'; - $tpl_item_attendmaybe = 'notifications_attend_item.tpl'; - $tpl_item_friend = 'notifications_friends_item.tpl'; - $tpl_item_comment = 'notifications_comments_item.tpl'; - $tpl_item_post = 'notifications_posts_item.tpl'; - $tpl_item_notify = 'notify.tpl'; - // Loop trough ever notification This creates an array with the output html for each // notification and apply the correct template according to the notificationtype (label). - foreach ($notifs['notifications'] as $it) { - + foreach ($notifs['notifications'] as $notif) { // We use the notification label to get the correct template file - $tpl_var_name = 'tpl_item_'.$it['label']; + $tpl_var_name = 'tpl_item_' . $notif['label']; $tpl_notif = get_markup_template($$tpl_var_name); - $notif_content[] = replace_macros($tpl_notif,[ - '$item_label' => $it['label'], - '$item_link' => $it['link'], - '$item_image' => $it['image'], - '$item_url' => $it['url'], - '$item_text' => $it['text'], - '$item_when' => $it['when'], - '$item_ago' => $it['ago'], - '$item_seen' => $it['seen'], + $notif_content[] = replace_macros($tpl_notif, [ + '$item_label' => $notif['label'], + '$item_link' => $notif['link'], + '$item_image' => $notif['image'], + '$item_url' => $notif['url'], + '$item_text' => $notif['text'], + '$item_when' => $notif['when'], + '$item_ago' => $notif['ago'], + '$item_seen' => $notif['seen'], ]); } } else { @@ -313,17 +294,17 @@ function notifications_content(App $a) } $notif_show_lnk = [ - 'href' => ($show ? 'notifications/'.$notifs['ident'] : 'notifications/'.$notifs['ident'].'?show=all' ), + 'href' => ($show ? 'notifications/' . $notifs['ident'] : 'notifications/' . $notifs['ident'] . '?show=all' ), 'text' => ($show ? L10n::t('Show unread') : L10n::t('Show all')), ]; $o .= replace_macros($notif_tpl, [ - '$notif_header' => $notif_header, - '$tabs' => $tabs, - '$notif_content' => $notif_content, + '$notif_header' => $notif_header, + '$tabs' => $tabs, + '$notif_content' => $notif_content, '$notif_nocontent' => $notif_nocontent, - '$notif_show_lnk' => $notif_show_lnk, - '$notif_paginate' => alt_pager($a, count($notif_content)) + '$notif_show_lnk' => $notif_show_lnk, + '$notif_paginate' => alt_pager($a, count($notif_content)) ]); return $o; From 99244d33f504349e4e11e5d3a6d0a3c505f12fee Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 7 Sep 2018 06:10:33 +0000 Subject: [PATCH 053/428] Fix for #5732 - too much links had been detected as photos --- src/Util/ParseUrl.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index dd39a052a0..40cb0b8fc0 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -333,7 +333,7 @@ class ParseUrl } // Prevent to have a photo type without an image - if (empty($siteinfo['image']) && ($siteinfo['type'] == 'photo')) { + if ((empty($siteinfo['image']) || !empty($siteinfo['text'])) && ($siteinfo['type'] == 'photo')) { $siteinfo['type'] = 'link'; } From 71215115ebb1e06b461dc5b0fa7ee4c27d8c665c Mon Sep 17 00:00:00 2001 From: Benjamin Lorteau Date: Fri, 7 Sep 2018 11:15:23 -0400 Subject: [PATCH 054/428] Restore template choice by notification label --- mod/notifications.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/mod/notifications.php b/mod/notifications.php index 212736305f..acd49de063 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -274,9 +274,19 @@ function notifications_content(App $a) // Loop trough ever notification This creates an array with the output html for each // notification and apply the correct template according to the notificationtype (label). foreach ($notifs['notifications'] as $notif) { - // We use the notification label to get the correct template file - $tpl_var_name = 'tpl_item_' . $notif['label']; - $tpl_notif = get_markup_template($$tpl_var_name); + $notification_templates = [ + 'like' => 'notifications_likes_item.tpl', + 'dislike' => 'notifications_dislikes_item.tpl', + 'attend' => 'notifications_attend_item.tpl', + 'attendno' => 'notifications_attend_item.tpl', + 'attendmaybe' => 'notifications_attend_item.tpl', + 'friend' => 'notifications_friends_item.tpl', + 'comment' => 'notifications_comments_item.tpl', + 'post' => 'notifications_posts_item.tpl', + 'notify' => 'notify.tpl', + ]; + + $tpl_notif = get_markup_template($notification_templates[$notif['label']]); $notif_content[] = replace_macros($tpl_notif, [ '$item_label' => $notif['label'], From 791a77f44133eb3c7f92575668996bcea1bff5e1 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sat, 8 Sep 2018 02:37:53 -0400 Subject: [PATCH 055/428] Add overwrite parameter to App->loadConfigFile --- src/App.php | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/App.php b/src/App.php index 488c2301b6..0dc4b86b95 100644 --- a/src/App.php +++ b/src/App.php @@ -372,13 +372,13 @@ 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'); + $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php', true); } } /** * Tries to load the specified configuration file into the App->config array. - * Overwrites previously set values. + * Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config. * * The config format is INI and the template for configuration files is the following: * @@ -391,9 +391,10 @@ class App * // Keep this line * * @param type $filepath + * @param bool $overwrite Force value overwrite if the config key already exists * @throws Exception */ - public function loadConfigFile($filepath) + public function loadConfigFile($filepath, $overwrite = false) { if (!file_exists($filepath)) { throw new Exception('Error parsing non-existent config file ' . $filepath); @@ -409,7 +410,11 @@ class App foreach ($config as $category => $values) { foreach ($values as $key => $value) { - $this->setConfigValue($category, $key, $value); + if ($overwrite) { + $this->setConfigValue($category, $key, $value); + } else { + $this->setDefaultConfigValue($category, $key, $value); + } } } } @@ -427,7 +432,7 @@ class App // 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'); + $this->loadConfigFile($this->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'addon.ini.php', true); } } @@ -1244,6 +1249,20 @@ class App return $return; } + /** + * Sets a default value in the config cache. Ignores already existing keys. + * + * @param string $cat Config category + * @param string $k Config key + * @param mixed $v Default value to set + */ + private function setDefaultConfigValue($cat, $k, $v) + { + if (!isset($this->config[$cat][$k])) { + $this->setConfigValue($cat, $k, $v); + } + } + /** * Sets a value in the config cache. Accepts raw output from the config table * From d581318c7cfd78a94abe1aa5b2578be297601df0 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 9 Sep 2018 06:32:01 +0000 Subject: [PATCH 056/428] Notices come, notices go ... --- mod/message.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/message.php b/mod/message.php index 8c9aa657df..223976ddbe 100644 --- a/mod/message.php +++ b/mod/message.php @@ -488,7 +488,7 @@ function render_messages(array $msg, $t) '$id' => $rr['id'], '$from_name' => $participants, '$from_url' => Contact::magicLink($rr['url']), - '$from_addr' => $contact['addr'], + '$from_addr' => defaults($contact, 'addr', ''), '$sparkle' => ' sparkle', '$from_photo' => ProxyUtils::proxifyUrl($from_photo, false, ProxyUtils::SIZE_THUMB), '$subject' => $subject_e, From 071aff223a672ccf3925bf91c5020bd080e7196f Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 9 Sep 2018 09:51:59 -0400 Subject: [PATCH 057/428] Format source of mod/events --- mod/events.php | 118 +++++++++++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 47 deletions(-) diff --git a/mod/events.php b/mod/events.php index c4d40252d3..38b632cf49 100644 --- a/mod/events.php +++ b/mod/events.php @@ -20,7 +20,8 @@ use Friendica\Util\Temporal; require_once 'include/items.php'; -function events_init(App $a) { +function events_init(App $a) +{ if (!local_user()) { return; } @@ -42,7 +43,8 @@ function events_init(App $a) { return; } -function events_post(App $a) { +function events_post(App $a) +{ logger('post: ' . print_r($_REQUEST, true), LOGGER_DATA); @@ -50,8 +52,8 @@ function events_post(App $a) { return; } - $event_id = (x($_POST, 'event_id') ? intval($_POST['event_id']) : 0); - $cid = (x($_POST, 'cid') ? intval($_POST['cid']) : 0); + $event_id = !empty($_POST['event_id']) ? intval($_POST['event_id']) : 0; + $cid = !empty($_POST['cid']) ? intval($_POST['cid']) : 0; $uid = local_user(); $start_text = escape_tags(defaults($_REQUEST, 'start_text', '')); @@ -137,7 +139,7 @@ function events_post(App $a) { $str_contact_deny = !empty($_POST['contact_deny']) ? perms2str($_POST['contact_deny']) : ''; // Undo the pseudo-contact of self, since there are real contacts now - if (strpos($str_contact_allow, '<' . $self . '>') !== false ) { + if (strpos($str_contact_allow, '<' . $self . '>') !== false) { $str_contact_allow = str_replace('<' . $self . '>', '', $str_contact_allow); } // Make sure to set the `private` field as true. This is necessary to @@ -187,8 +189,8 @@ function events_post(App $a) { goaway($_SESSION['return_url']); } -function events_content(App $a) { - +function events_content(App $a) +{ if (!local_user()) { notice(L10n::t('Permission denied.') . EOL); return; @@ -244,7 +246,7 @@ function events_content(App $a) { $mode = 'view'; $y = 0; $m = 0; - $ignored = (x($_REQUEST, 'ignored') ? intval($_REQUEST['ignored']) : 0); + $ignored = !empty($_REQUEST['ignored']) ? intval($_REQUEST['ignored']) : 0; if ($a->argc > 1) { if ($a->argc > 2 && $a->argv[1] == 'event') { @@ -272,7 +274,6 @@ function events_content(App $a) { // The view mode part is similiar to /mod/cal.php if ($mode == 'view') { - $thisyear = DateTimeFormat::localNow('Y'); $thismonth = DateTimeFormat::localNow('m'); if (!$y) { @@ -312,10 +313,10 @@ function events_content(App $a) { $finish = sprintf('%d-%d-%d %d:%d:%d', $y, $m, $dim, 23, 59, 59); if ($a->argc > 1 && $a->argv[1] === 'json') { - if (x($_GET, 'start')) { - $start = $_GET['start']; + if (!empty($_GET['start'])) { + $start = $_GET['start']; } - if (x($_GET, 'end')) { + if (!empty($_GET['end'])) { $finish = $_GET['end']; } } @@ -349,7 +350,7 @@ function events_content(App $a) { $r = Event::sortByDate($r); foreach ($r as $rr) { $j = $rr['adjust'] ? DateTimeFormat::local($rr['start'], 'j') : DateTimeFormat::utc($rr['start'], 'j'); - if (!x($links,$j)) { + if (empty($links[$j])) { $links[$j] = System::baseUrl() . '/' . $a->cmd . '#link-' . $j; } } @@ -363,12 +364,12 @@ function events_content(App $a) { $events = Event::prepareListForTemplate($r); } - if ($a->argc > 1 && $a->argv[1] === 'json'){ + if ($a->argc > 1 && $a->argv[1] === 'json') { echo json_encode($events); killme(); } - if (x($_GET, 'id')) { + if (!empty($_GET['id'])) { $tpl = get_markup_template("event.tpl"); } else { $tpl = get_markup_template("events_js.tpl"); @@ -378,7 +379,7 @@ function events_content(App $a) { foreach ($events as $key => $event) { $event_item = []; foreach ($event['item'] as $k => $v) { - $k = str_replace('-' ,'_', $k); + $k = str_replace('-', '_', $k); $event_item[$k] = $v; } $events[$key]['item'] = $event_item; @@ -403,7 +404,7 @@ function events_content(App $a) { '$list' => L10n::t('list'), ]); - if (x($_GET, 'id')) { + if (!empty($_GET['id'])) { echo $o; killme(); } @@ -428,41 +429,45 @@ function events_content(App $a) { } // In case of an error the browser is redirected back here, with these parameters filled in with the previous values - if (x($_REQUEST, 'nofinish')) {$orig_event['nofinish'] = $_REQUEST['nofinish'];} - if (x($_REQUEST, 'adjust')) {$orig_event['adjust'] = $_REQUEST['adjust'];} - if (x($_REQUEST, 'summary')) {$orig_event['summary'] = $_REQUEST['summary'];} - if (x($_REQUEST, 'description')) {$orig_event['description'] = $_REQUEST['description'];} - if (x($_REQUEST, 'location')) {$orig_event['location'] = $_REQUEST['location'];} - if (x($_REQUEST, 'start')) {$orig_event['start'] = $_REQUEST['start'];} - if (x($_REQUEST, 'finish')) {$orig_event['finish'] = $_REQUEST['finish'];} - if (x($_REQUEST,'finish')) $orig_event['finish'] = $_REQUEST['finish']; + if (!empty($_REQUEST['nofinish'])) {$orig_event['nofinish'] = $_REQUEST['nofinish'];} + if (!empty($_REQUEST['adjust'])) {$orig_event['adjust'] = $_REQUEST['adjust'];} + if (!empty($_REQUEST['summary'])) {$orig_event['summary'] = $_REQUEST['summary'];} + if (!empty($_REQUEST['description'])) {$orig_event['description'] = $_REQUEST['description'];} + if (!empty($_REQUEST['location'])) {$orig_event['location'] = $_REQUEST['location'];} + if (!empty($_REQUEST['start'])) {$orig_event['start'] = $_REQUEST['start'];} + if (!empty($_REQUEST['finish'])) {$orig_event['finish'] = $_REQUEST['finish'];} - $n_checked = ((x($orig_event) && $orig_event['nofinish']) ? ' checked="checked" ' : ''); - $a_checked = ((x($orig_event) && $orig_event['adjust']) ? ' checked="checked" ' : ''); + $n_checked = (!empty($orig_event['nofinish']) ? ' checked="checked" ' : ''); + $a_checked = (!empty($orig_event['adjust']) ? ' checked="checked" ' : ''); - $t_orig = (x($orig_event) ? $orig_event['summary'] : ''); - $d_orig = (x($orig_event) ? $orig_event['desc'] : ''); - $l_orig = (x($orig_event) ? $orig_event['location'] : ''); - $eid = (x($orig_event) ? $orig_event['id'] : 0); - $cid = (x($orig_event) ? $orig_event['cid'] : 0); - $uri = (x($orig_event) ? $orig_event['uri'] : ''); + $t_orig = !empty($orig_event) ? $orig_event['summary'] : ''; + $d_orig = !empty($orig_event) ? $orig_event['desc'] : ''; + $l_orig = !empty($orig_event) ? $orig_event['location'] : ''; + $eid = !empty($orig_event) ? $orig_event['id'] : 0; + $cid = !empty($orig_event) ? $orig_event['cid'] : 0; + $uri = !empty($orig_event) ? $orig_event['uri'] : ''; $sh_disabled = ''; - $sh_checked = ''; + $sh_checked = ''; - if (x($orig_event)) { - $sh_checked = (($orig_event['allow_cid'] === '<' . local_user() . '>' && !$orig_event['allow_gid'] && !$orig_event['deny_cid'] && !$orig_event['deny_gid']) ? '' : ' checked="checked" '); + if (!empty($orig_event) + && ($orig_event['allow_cid'] !== '<' . local_user() . '>' + || $orig_event['allow_gid'] + || $orig_event['deny_cid'] + || $orig_event['deny_gid'])) + { + $sh_checked = ' checked="checked" '; } if ($cid || $mode === 'edit') { $sh_disabled = 'disabled="disabled"'; } - $sdt = (x($orig_event) ? $orig_event['start'] : 'now'); - $fdt = (x($orig_event) ? $orig_event['finish'] : 'now'); + $sdt = !empty($orig_event) ? $orig_event['start'] : 'now'; + $fdt = !empty($orig_event) ? $orig_event['finish'] : 'now'; $tz = date_default_timezone_get(); - if (x($orig_event)) { + if (!empty($orig_event)) { $tz = ($orig_event['adjust'] ? date_default_timezone_get() : 'UTC'); } @@ -470,15 +475,15 @@ function events_content(App $a) { $smonth = DateTimeFormat::convert($sdt, $tz, 'UTC', 'm'); $sday = DateTimeFormat::convert($sdt, $tz, 'UTC', 'd'); - $shour = (x($orig_event) ? DateTimeFormat::convert($sdt, $tz, 'UTC', 'H') : '00'); - $sminute = (x($orig_event) ? DateTimeFormat::convert($sdt, $tz, 'UTC', 'i') : '00'); + $shour = !empty($orig_event) ? DateTimeFormat::convert($sdt, $tz, 'UTC', 'H') : '00'; + $sminute = !empty($orig_event) ? DateTimeFormat::convert($sdt, $tz, 'UTC', 'i') : '00'; $fyear = DateTimeFormat::convert($fdt, $tz, 'UTC', 'Y'); $fmonth = DateTimeFormat::convert($fdt, $tz, 'UTC', 'm'); $fday = DateTimeFormat::convert($fdt, $tz, 'UTC', 'd'); - $fhour = (x($orig_event) ? DateTimeFormat::convert($fdt, $tz, 'UTC', 'H') : '00'); - $fminute = (x($orig_event) ? DateTimeFormat::convert($fdt, $tz, 'UTC', 'i') : '00'); + $fhour = !empty($orig_event) ? DateTimeFormat::convert($fdt, $tz, 'UTC', 'H') : '00'; + $fminute = !empty($orig_event) ? DateTimeFormat::convert($fdt, $tz, 'UTC', 'i') : '00'; $perms = ACL::getDefaultUserPermissions($orig_event); @@ -497,7 +502,7 @@ function events_content(App $a) { $tpl = get_markup_template('event_form.tpl'); - $o .= replace_macros($tpl,[ + $o .= replace_macros($tpl, [ '$post' => System::baseUrl() . '/events', '$eid' => $eid, '$cid' => $cid, @@ -511,11 +516,31 @@ function events_content(App $a) { '$title' => L10n::t('Event details'), '$desc' => L10n::t('Starting date and Title are required.'), '$s_text' => L10n::t('Event Starts:') . ' *', - '$s_dsel' => Temporal::getDateTimeField(new DateTime(), DateTime::createFromFormat('Y', $syear+5), DateTime::createFromFormat('Y-m-d H:i', "$syear-$smonth-$sday $shour:$sminute"), L10n::t('Event Starts:'), 'start_text', true, true, '', '', true), + '$s_dsel' => Temporal::getDateTimeField( + new DateTime(), + DateTime::createFromFormat('Y', $syear+5), + DateTime::createFromFormat('Y-m-d H:i', "$syear-$smonth-$sday $shour:$sminute"), + L10n::t('Event Starts:'), + 'start_text', + true, + true, + '', + '', + true + ), '$n_text' => L10n::t('Finish date/time is not known or not relevant'), '$n_checked' => $n_checked, '$f_text' => L10n::t('Event Finishes:'), - '$f_dsel' => Temporal::getDateTimeField(new DateTime(), DateTime::createFromFormat('Y', $fyear+5), DateTime::createFromFormat('Y-m-d H:i', "$fyear-$fmonth-$fday $fhour:$fminute"), L10n::t('Event Finishes:'), 'finish_text', true, true, 'start_text'), + '$f_dsel' => Temporal::getDateTimeField( + new DateTime(), + DateTime::createFromFormat('Y', $fyear+5), + DateTime::createFromFormat('Y-m-d H:i', "$fyear-$fmonth-$fday $fhour:$fminute"), + L10n::t('Event Finishes:'), + 'finish_text', + true, + true, + 'start_text' + ), '$a_text' => L10n::t('Adjust for viewer timezone'), '$a_checked' => $a_checked, '$d_text' => L10n::t('Description:'), @@ -536,7 +561,6 @@ function events_content(App $a) { '$basic' => L10n::t('Basic'), '$advanced' => L10n::t('Advanced'), '$permissions' => L10n::t('Permissions'), - ]); return $o; From 4edbea3ed01f0891b22b44f74efb6990f9deac6c Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 9 Sep 2018 09:54:54 -0400 Subject: [PATCH 058/428] Fix JS error when no acl is defined --- view/js/main.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/view/js/main.js b/view/js/main.js index 4788d90a83..4ccbc8044e 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -305,7 +305,9 @@ $(function() { // Asynchronous calls are deferred until the very end of the page load to ease on slower connections window.addEventListener("load", function(){ NavUpdate(); - acl.get(0, 100); + if (typeof acl !== 'undefined') { + acl.get(0, 100); + } }); // Allow folks to stop the ajax page updates with the pause/break key From 11a3b45957c880108aeaeddf4f8bbd3ae64c5a0f Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 9 Sep 2018 10:10:17 -0400 Subject: [PATCH 059/428] [frio] Fix ACL selection in new event modal - Fix this.allow_cid.push isn't a function error --- view/theme/frio/js/event_edit.js | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/view/theme/frio/js/event_edit.js b/view/theme/frio/js/event_edit.js index da0837223a..628835a5f0 100644 --- a/view/theme/frio/js/event_edit.js +++ b/view/theme/frio/js/event_edit.js @@ -1,7 +1,7 @@ $(document).ready(function() { // Go to the permissions tab if the checkbox is checked. $('body').on("click", "#id_share", function() { - if ($('#id_share').is(':checked') && !( $('#id_share').attr("disabled"))) { + if ($('#id_share').is(':checked') && !( $('#id_share').attr("disabled"))) { $('#acl-wrapper').show(); $("a#event-perms-lnk").parent("li").show(); toggleEventNav("a#event-perms-lnk"); @@ -54,20 +54,19 @@ $(document).ready(function() { // without page reloading (e.g. closing an old modal and open a new modal). // Otherwise we wouldn't get the ACL data. /// @todo: Try to implement some kind of ACL reloading in acl.js. - if (typeof acl !== "undefined") { - var eventPerms = document.getElementById('event-edit-form'); - acl = new ACL( - baseurl + "/acl", - [ - eventPerms.dataset.allow_cid, - eventPerms.dataset.allow_gid, - eventPerms.dataset.deny_cid, - eventPerms.dataset.deny_gid - ] - ); - } + var eventPerms = document.getElementById('event-edit-form'); + acl = new ACL( + baseurl + "/acl", + [ + JSON.parse(eventPerms.dataset.allow_cid), + JSON.parse(eventPerms.dataset.allow_gid), + JSON.parse(eventPerms.dataset.deny_cid), + JSON.parse(eventPerms.dataset.deny_gid) + ] + ); + acl.get(0, 100); }); // Load the html of the actual event and incect the output to the @@ -81,7 +80,7 @@ function doEventPreview() { } -// The following functions show/hide the specific event-edit content +// The following functions show/hide the specific event-edit content // in dependence of the selected nav. function eventAclActive() { $("#event-edit-wrapper, #event-preview, #event-desc-wrapper").hide(); From e461474290f87a1e783100435183cf67217dce1b Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 9 Sep 2018 18:33:14 -0400 Subject: [PATCH 060/428] Fix count being called on the wrong variable in mod/notes --- mod/notes.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mod/notes.php b/mod/notes.php index 68a870e9d6..01f283870e 100644 --- a/mod/notes.php +++ b/mod/notes.php @@ -70,8 +70,11 @@ function notes_content(App $a, $update = false) $count = 0; if (DBA::isResult($r)) { - $count = count($r); - $o .= conversation($a, DBA::toArray($r), 'notes', $update); + $notes = DBA::toArray($r); + + $count = count($notes); + + $o .= conversation($a, $notes, 'notes', $update); } $o .= alt_pager($a, $count); From 0a5476591d99af6155dff047795a06da6eb9fc62 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 10 Sep 2018 21:07:25 +0000 Subject: [PATCH 061/428] Activitity pub - first commit with much test code --- src/Module/Inbox.php | 47 +++ src/Protocol/ActivityPub.php | 772 +++++++++++++++++++++++++++++++++++ 2 files changed, 819 insertions(+) create mode 100644 src/Module/Inbox.php create mode 100644 src/Protocol/ActivityPub.php diff --git a/src/Module/Inbox.php b/src/Module/Inbox.php new file mode 100644 index 0000000000..86fdae7c90 --- /dev/null +++ b/src/Module/Inbox.php @@ -0,0 +1,47 @@ + $_SERVER, 'body' => $obj])); + + logger('Blubb: init ' . $tempfile); + exit(); +// goaway($dest); + } + + public static function post() + { + $a = self::getApp(); + + logger('Blubb: post'); + exit(); +// goaway($dest); + } +} diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php new file mode 100644 index 0000000000..f1d885b6c6 --- /dev/null +++ b/src/Protocol/ActivityPub.php @@ -0,0 +1,772 @@ +get_curl_code(); +echo $return_code."\n"; + print_r(BaseObject::getApp()->get_curl_headers()); + print_r($headers); + } + + /** + * Return the ActivityPub profile of the given user + * + * @param integer $uid User ID + * @return array + */ + public static function profile($uid) + { + $accounttype = ['Person', 'Organization', 'Service', 'Group', 'Application']; + + $condition = ['uid' => $uid, 'blocked' => false, 'account_expired' => false, + 'account_removed' => false, 'verified' => true]; + $fields = ['guid', 'nickname', 'pubkey', 'account-type']; + $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']; + $contact = DBA::selectFirst('contact', $fields, ['uid' => $uid, 'self' => true]); + if (!DBA::isResult($contact)) { + return []; + } + + $data = ['@context' => ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1', + ['uuid' => 'http://schema.org/identifier', 'sensitive' => 'as:sensitive', + 'vcard' => 'http://www.w3.org/2006/vcard/ns#']]]; + + $data['id'] = $contact['url']; + $data['uuid'] = $user['guid']; + $data['type'] = $accounttype[$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' => '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'] = false; + $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; + } + + public static function createActivityFromItem($item_id) + { + $item = Item::selectFirst([], ['id' => $item_id]); + + $data = ['@context' => ['https://www.w3.org/ns/activitystreams', 'https://w3id.org/security/v1', + ['Emoji' => 'toot:Emoji', 'Hashtag' => 'as:Hashtag', 'atomUri' => 'ostatus:atomUri', + 'conversation' => 'ostatus:conversation', 'inReplyToAtomUri' => 'ostatus:inReplyToAtomUri', + 'ostatus' => 'http://ostatus.org#', 'sensitive' => 'as:sensitive', + 'toot' => 'http://joinmastodon.org/ns#']]]; + + $data['type'] = 'Create'; + $data['id'] = $item['plink']; + $data['actor'] = $item['author-link']; + $data['to'] = 'https://www.w3.org/ns/activitystreams#Public'; + $data['object'] = self::createNote($item); +// print_r($data); +// print_r($item); + return $data; + } + + public static function createNote($item) + { + $data = []; + $data['type'] = 'Note'; + $data['id'] = $item['plink']; + //$data['context'] = $data['conversation'] = $item['parent-uri']; + $data['actor'] = $item['author-link']; +// if (!$item['private']) { +// $data['to'] = []; +// $data['to'][] = '"https://pleroma.soykaf.com/users/heluecht"'; + $data['to'] = 'https://www.w3.org/ns/activitystreams#Public'; +// $data['cc'] = 'https://pleroma.soykaf.com/users/heluecht'; +// } + $data['published'] = DateTimeFormat::utc($item["created"]."+00:00", DateTimeFormat::ATOM); + $data['updated'] = DateTimeFormat::utc($item["edited"]."+00:00", DateTimeFormat::ATOM); + $data['attributedTo'] = $item['author-link']; + $data['title'] = BBCode::convert($item['title'], false, 7); + $data['content'] = BBCode::convert($item['body'], false, 7); + //$data['summary'] = ''; + //$data['sensitive'] = false; + //$data['emoji'] = []; + //$data['tag'] = []; + //$data['attachment'] = []; + return $data; + } + + /** + * Fetches ActivityPub content from the given url + * + * @param string $url content url + * @return array + */ + public static function fetchContent($url) + { + $ret = Network::curl($url, false, $redirects, ['accept_content' => 'application/activity+json']); + + if (!$ret['success'] || empty($ret['body'])) { + return; + } + + return json_decode($ret['body'], true); + } + + /** + * 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); + + $ret = Network::curl($webfinger, false, $redirects, ['accept_content' => 'application/jrd+json,application/json']); + if (!$ret['success'] || empty($ret['body'])) { + return false; + } + + $data = json_decode($ret['body'], 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 the given url + * + * @param string $url profile url + * @return array + */ + public static function fetchProfile($url) + { + if (empty(parse_url($url, PHP_URL_SCHEME))) { + $url = self::addrToUrl($url); + if (empty($url)) { + return false; + } + } + + $data = self::fetchContent($url); + + if (empty($data) || empty($data['id']) || empty($data['inbox'])) { + return false; + } + + $profile = ['network' => Protocol::ACTIVITYPUB]; + $profile['nick'] = $data['preferredUsername']; + $profile['name'] = defaults($data, 'name', $profile['nick']); + $profile['guid'] = defaults($data, 'uuid', null); + $profile['url'] = $data['id']; + $profile['alias'] = self::processElement($data, 'url', 'href'); + + $parts = parse_url($profile['url']); + unset($parts['scheme']); + unset($parts['path']); + $profile['addr'] = $profile['nick'] . '@' . str_replace('//', '', Network::unparseURL($parts)); + + $profile['photo'] = self::processElement($data, 'icon', 'url'); + $profile['about'] = defaults($data, 'summary', ''); + $profile['batch'] = self::processElement($data, 'endpoints', 'sharedInbox'); + $profile['pubkey'] = self::processElement($data, 'publicKey', 'publicKeyPem'); + $profile['notify'] = $data['inbox']; + $profile['poll'] = $data['outbox']; + + // Check if the address is resolvable + if (self::addrToUrl($profile['addr']) == $profile['url']) { + $parts = parse_url($profile['url']); + unset($parts['path']); + $profile['baseurl'] = Network::unparseURL($parts); + } else { + unset($profile['addr']); + } + + if ($profile['url'] == $profile['alias']) { + unset($profile['alias']); + } + + // Remove all "null" fields + foreach ($profile as $field => $content) { + if (is_null($content)) { + unset($profile[$field]); + } + } + + // Handled + unset($data['id']); + unset($data['inbox']); + unset($data['outbox']); + unset($data['preferredUsername']); + unset($data['name']); + unset($data['summary']); + unset($data['url']); + unset($data['publicKey']); + unset($data['endpoints']); + unset($data['icon']); + unset($data['uuid']); + + // To-Do + unset($data['type']); + unset($data['manuallyApprovesFollowers']); + + // Unhandled + unset($data['@context']); + unset($data['tag']); + unset($data['attachment']); + unset($data['image']); + unset($data['nomadicLocations']); + unset($data['signature']); + unset($data['following']); + unset($data['followers']); + unset($data['featured']); + unset($data['movedTo']); + unset($data['liked']); + unset($data['sharedInbox']); // Misskey + unset($data['isCat']); // Misskey + unset($data['kroeg:blocks']); // Kroeg + unset($data['updated']); // Kroeg + +/* if (!empty($data)) { + print_r($data); + die(); + } +*/ + return $profile; + } + + public static function fetchOutbox($url) + { + $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']); + return; + } else { + $items = []; + } + + foreach ($items as $activity) { + self::processActivity($activity, $url); + } + } + + function processActivity($activity, $url) + { + if (empty($activity['type'])) { + return; + } + + if (empty($activity['object'])) { + return; + } + + if (empty($activity['actor'])) { + return; + } + + $actor = self::processElement($activity, 'actor', 'id'); + if (empty($actor)) { + return; + } + + if (is_string($activity['object'])) { + $object_url = $activity['object']; + } elseif (!empty($activity['object']['id'])) { + $object_url = $activity['object']['id']; + } else { + return; + } + + $receivers = self::getReceivers($activity); + if (empty($receivers)) { + return; + } + + // ---------------------------------- + // unhandled + unset($activity['@context']); + unset($activity['id']); + + // Non standard + unset($activity['title']); + unset($activity['atomUri']); + unset($activity['context_id']); + unset($activity['statusnetConversationId']); + + $structure = $activity; + + // To-Do? + unset($activity['context']); + unset($activity['location']); + + // handled + unset($activity['to']); + unset($activity['cc']); + unset($activity['bto']); + unset($activity['bcc']); + unset($activity['type']); + unset($activity['actor']); + unset($activity['object']); + unset($activity['published']); + unset($activity['updated']); + unset($activity['instrument']); + unset($activity['inReplyTo']); + + if (!empty($activity)) { + echo "Activity\n"; + print_r($activity); + die($url."\n"); + } + + $activity = $structure; + // ---------------------------------- + + $item = self::fetchObject($object_url, $url); + if (empty($item)) { + return; + } + + $item = self::addActivityFields($item, $activity); + + $item['owner'] = $actor; + + $item['receiver'] = array_merge($item['receiver'], $receivers); + + switch ($activity['type']) { + case 'Create': + case 'Update': + self::createItem($item); + break; + + case 'Announce': + self::announceItem($item); + break; + + case 'Like': + case 'Dislike': + self::activityItem($item); + break; + + case 'Follow': + break; + + default: + echo "Unknown activity: ".$activity['type']."\n"; + print_r($item); + die(); + break; + } + } + + private static function getReceivers($activity) + { + $receivers = []; + + $elements = ['to', 'cc', 'bto', 'bcc']; + foreach ($elements as $element) { + if (empty($activity[$element])) { + continue; + } + + // The receiver can be an arror or a string + if (is_string($activity[$element])) { + $activity[$element] = [$activity[$element]]; + } + + foreach ($activity[$element] as $receiver) { + if ($receiver == self::PUBLIC) { + $receivers[$receiver] = 0; + } + + $condition = ['self' => true, 'nurl' => normalise_link($receiver)]; + $contact = DBA::selectFirst('contact', ['id'], $condition); + if (!DBA::isResult($contact)) { + continue; + } + $receivers[$receiver] = $contact['id']; + } + } + return $receivers; + } + + private static function addActivityFields($item, $activity) + { + if (!empty($activity['published']) && empty($item['published'])) { + $item['published'] = $activity['published']; + } + + if (!empty($activity['updated']) && empty($item['updated'])) { + $item['updated'] = $activity['updated']; + } + + if (!empty($activity['inReplyTo']) && empty($item['parent-uri'])) { + $item['parent-uri'] = self::processElement($activity, 'inReplyTo', 'id'); + } + + if (!empty($activity['instrument'])) { + $item['service'] = self::processElement($activity, 'instrument', 'name', 'Service'); + } + + // Remove all "null" fields + foreach ($item as $field => $content) { + if (is_null($content)) { + unset($item[$field]); + } + } + + return $item; + } + + private static function fetchObject($object_url, $url) + { + $data = self::fetchContent($object_url); + if (empty($data)) { + return false; + } + + if (empty($data['type'])) { + return false; + } else { + $type = $data['type']; + } + + if (in_array($type, ['Note', 'Article', 'Video'])) { + $common = self::processCommonData($data, $url); + } + + switch ($type) { + case 'Note': + return array_merge($common, self::processNote($data, $url)); + case 'Article': + return array_merge($common, self::processArticle($data, $url)); + case 'Video': + return array_merge($common, self::processVideo($data, $url)); + + case 'Announce': + if (empty($data['object'])) { + return false; + } + return self::fetchObject($data['object'], $url); + + case 'Person': + case 'Tombstone': + break; + + default: + echo "Unknown object type: ".$data['type']."\n"; + print_r($data); + die($url."\n"); + break; + } + } + + private static function processCommonData(&$object, $url) + { + if (empty($object['id']) || empty($object['attributedTo'])) { + return false; + } + + $item = []; + $item['uri'] = $object['id']; + + if (!empty($object['inReplyTo'])) { + $item['reply-to-uri'] = self::processElement($object, 'inReplyTo', 'id'); + } else { + $item['reply-to-uri'] = $item['uri']; + } + + $item['published'] = defaults($object, 'published', null); + $item['updated'] = defaults($object, 'updated', $item['published']); + + if (empty($item['published']) && !empty($item['updated'])) { + $item['published'] = $item['updated']; + } + + $item['uuid'] = defaults($object, 'uuid', null); + $item['owner'] = $item['author'] = self::processElement($object, 'attributedTo', 'id'); + $item['context'] = defaults($object, 'context', null); + $item['conversation'] = defaults($object, 'conversation', null); + $item['sensitive'] = defaults($object, 'sensitive', null); + $item['name'] = defaults($object, 'name', null); + $item['title'] = defaults($object, 'title', null); + $item['content'] = defaults($object, 'content', null); + $item['summary'] = defaults($object, 'summary', null); + $item['location'] = self::processElement($object, 'location', 'name', 'Place'); + $item['attachments'] = defaults($object, 'attachment', null); + $item['tags'] = defaults($object, 'tag', null); + $item['service'] = self::processElement($object, 'instrument', 'name', 'Service'); + $item['alternate-url'] = self::processElement($object, 'url', 'href'); + $item['receiver'] = self::getReceivers($object); + + // handled + unset($object['id']); + unset($object['inReplyTo']); + unset($object['published']); + unset($object['updated']); + unset($object['uuid']); + unset($object['attributedTo']); + unset($object['context']); + unset($object['conversation']); + unset($object['sensitive']); + unset($object['name']); + unset($object['title']); + unset($object['content']); + unset($object['summary']); + unset($object['location']); + unset($object['attachment']); + unset($object['tag']); + unset($object['instrument']); + unset($object['url']); + unset($object['to']); + unset($object['cc']); + unset($object['bto']); + unset($object['bcc']); + + // To-Do + unset($object['source']); + + // Unhandled + unset($object['@context']); + unset($object['type']); + unset($object['actor']); + unset($object['signature']); + unset($object['mediaType']); + unset($object['duration']); + unset($object['replies']); + unset($object['icon']); + + /* + audience, preview, endTime, startTime, generator, image + */ + + return $item; + } + + private static function processNote($object, $url) + { + $item = []; + + // To-Do? + unset($object['emoji']); + unset($object['atomUri']); + unset($object['inReplyToAtomUri']); + + // Unhandled + unset($object['contentMap']); + unset($object['announcement_count']); + unset($object['announcements']); + unset($object['context_id']); + unset($object['likes']); + unset($object['like_count']); + unset($object['inReplyToStatusId']); + unset($object['shares']); + unset($object['quoteUrl']); + unset($object['statusnetConversationId']); + + if (empty($object)) + return $item; + + echo "Unknown Note\n"; + print_r($object); + print_r($item); + die($url."\n"); + + return []; + } + + private static function processArticle($object, $url) + { + $item = []; + + if (empty($object)) + return $item; + + echo "Unknown Article\n"; + print_r($object); + print_r($item); + die($url."\n"); + + return []; + } + + private static function processVideo($object, $url) + { + $item = []; + + // To-Do? + unset($object['category']); + unset($object['licence']); + unset($object['language']); + unset($object['commentsEnabled']); + + // Unhandled + unset($object['views']); + unset($object['waitTranscoding']); + unset($object['state']); + unset($object['support']); + unset($object['subtitleLanguage']); + unset($object['likes']); + unset($object['dislikes']); + unset($object['shares']); + unset($object['comments']); + + if (empty($object)) + return $item; + + echo "Unknown Video\n"; + print_r($object); + print_r($item); + die($url."\n"); + + return []; + } + + private static function processElement($array, $element, $key, $type = null) + { + if (empty($array)) { + return false; + } + + if (empty($array[$element])) { + return false; + } + + if (is_string($array[$element])) { + return $array[$element]; + } + + if (is_null($type)) { + if (!empty($array[$element][$key])) { + return $array[$element][$key]; + } + + if (!empty($array[$element][0][$key])) { + return $array[$element][0][$key]; + } + + return false; + } + + if (!empty($array[$element][$key]) && !empty($array[$element]['type']) && ($array[$element]['type'] == $type)) { + return $array[$element][$key]; + } + + /// @todo Add array search + + return false; + } + + private static function createItem($item) + { +// print_r($item); + } + + private static function announceItem($item) + { +// print_r($item); + } + + private static function activityItem($item) + { + // print_r($item); + } + +} From 8b96a53fba794bfd11738772b51015a0390c056b Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 11 Sep 2018 04:10:11 +0000 Subject: [PATCH 062/428] Burn notices, burn --- mod/bookmarklet.php | 4 ++++ mod/photos.php | 6 ++++-- mod/salmon.php | 8 ++++---- mod/webfinger.php | 2 +- src/Model/Profile.php | 2 +- src/Network/Probe.php | 44 +++++++++++++++++++++---------------------- 6 files changed, 36 insertions(+), 30 deletions(-) diff --git a/mod/bookmarklet.php b/mod/bookmarklet.php index 21b2039c58..e1ae9aa64c 100644 --- a/mod/bookmarklet.php +++ b/mod/bookmarklet.php @@ -30,6 +30,10 @@ function bookmarklet_content(App $a) $page = normalise_link(System::baseUrl() . "/bookmarklet"); if (!strstr($referer, $page)) { + if (empty($_REQUEST["url"])) { + System::httpExit(400, ["title" => L10n::t('Bad Request')]); + } + $content = add_page_info($_REQUEST["url"]); $x = [ diff --git a/mod/photos.php b/mod/photos.php index 16af455997..e205d72c6d 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -212,7 +212,7 @@ function photos_post(App $a) } // Check if the user has responded to a delete confirmation query - if ($_REQUEST['canceled']) { + if (!empty($_REQUEST['canceled'])) { goaway($_SESSION['photo_return']); } @@ -762,12 +762,14 @@ function photos_post(App $a) $filesize = $ret['filesize']; $type = $ret['type']; $error = UPLOAD_ERR_OK; - } else { + } elseif (!empty($_FILES['userfile'])) { $src = $_FILES['userfile']['tmp_name']; $filename = basename($_FILES['userfile']['name']); $filesize = intval($_FILES['userfile']['size']); $type = $_FILES['userfile']['type']; $error = $_FILES['userfile']['error']; + } else { + $error = UPLOAD_ERR_NO_FILE; } if ($error !== UPLOAD_ERR_OK) { diff --git a/mod/salmon.php b/mod/salmon.php index d07b06004d..bd4b3773cb 100644 --- a/mod/salmon.php +++ b/mod/salmon.php @@ -41,14 +41,14 @@ function salmon_post(App $a, $xml = '') { $base = null; // figure out where in the DOM tree our data is hiding - if($dom->provenance->data) + if (!empty($dom->provenance->data)) $base = $dom->provenance; - elseif($dom->env->data) + elseif (!empty($dom->env->data)) $base = $dom->env; - elseif($dom->data) + elseif (!empty($dom->data)) $base = $dom; - if(! $base) { + if (empty($base)) { logger('unable to locate salmon data in xml '); System::httpExit(400); } diff --git a/mod/webfinger.php b/mod/webfinger.php index 6f49a8f28c..4f23db6d8f 100644 --- a/mod/webfinger.php +++ b/mod/webfinger.php @@ -23,7 +23,7 @@ function webfinger_content(App $a) $o = '

Webfinger Diagnostic

'; $o .= '
'; - $o .= 'Lookup address: '; + $o .= 'Lookup address: '; $o .= '
'; $o .= '

'; diff --git a/src/Model/Profile.php b/src/Model/Profile.php index 29bc7e680d..3a014517da 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -361,7 +361,7 @@ class Profile if ($r) { $remote_url = $r[0]['url']; $message_path = preg_replace('=(.*)/profile/(.*)=ism', '$1/message/new/', $remote_url); - $wallmessage_link = $message_path . base64_encode($profile['addr']); + $wallmessage_link = $message_path . base64_encode(defaults($profile, 'addr', '')); } else if (!empty($profile['nickname'])) { $wallmessage_link = 'wallmessage/' . $profile['nickname']; } diff --git a/src/Network/Probe.php b/src/Network/Probe.php index af2d1c9a16..75231f44ff 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -967,23 +967,23 @@ class Probe $hcard_url = ""; $data = []; foreach ($webfinger["links"] as $link) { - if (($link["rel"] == NAMESPACE_DFRN) && ($link["href"] != "")) { + if (($link["rel"] == NAMESPACE_DFRN) && !empty($link["href"])) { $data["network"] = Protocol::DFRN; - } elseif (($link["rel"] == NAMESPACE_FEED) && ($link["href"] != "")) { + } elseif (($link["rel"] == NAMESPACE_FEED) && !empty($link["href"])) { $data["poll"] = $link["href"]; - } elseif (($link["rel"] == "http://webfinger.net/rel/profile-page") && ($link["type"] == "text/html") && ($link["href"] != "")) { + } elseif (($link["rel"] == "http://webfinger.net/rel/profile-page") && (defaults($link, "type", "") == "text/html") && !empty($link["href"])) { $data["url"] = $link["href"]; - } elseif (($link["rel"] == "http://microformats.org/profile/hcard") && ($link["href"] != "")) { + } elseif (($link["rel"] == "http://microformats.org/profile/hcard") && !empty($link["href"])) { $hcard_url = $link["href"]; - } elseif (($link["rel"] == NAMESPACE_POCO) && ($link["href"] != "")) { + } elseif (($link["rel"] == NAMESPACE_POCO) && !empty($link["href"])) { $data["poco"] = $link["href"]; - } elseif (($link["rel"] == "http://webfinger.net/rel/avatar") && ($link["href"] != "")) { + } elseif (($link["rel"] == "http://webfinger.net/rel/avatar") && !empty($link["href"])) { $data["photo"] = $link["href"]; - } elseif (($link["rel"] == "http://joindiaspora.com/seed_location") && ($link["href"] != "")) { + } elseif (($link["rel"] == "http://joindiaspora.com/seed_location") && !empty($link["href"])) { $data["baseurl"] = trim($link["href"], '/'); - } elseif (($link["rel"] == "http://joindiaspora.com/guid") && ($link["href"] != "")) { + } elseif (($link["rel"] == "http://joindiaspora.com/guid") && !empty($link["href"])) { $data["guid"] = $link["href"]; - } elseif (($link["rel"] == "diaspora-public-key") && ($link["href"] != "")) { + } elseif (($link["rel"] == "diaspora-public-key") && !empty($link["href"])) { $data["pubkey"] = base64_decode($link["href"]); //if (strstr($data["pubkey"], 'RSA ') || ($link["type"] == "RSA")) @@ -1170,21 +1170,21 @@ class Probe $hcard_url = ""; $data = []; foreach ($webfinger["links"] as $link) { - if (($link["rel"] == "http://microformats.org/profile/hcard") && ($link["href"] != "")) { + if (($link["rel"] == "http://microformats.org/profile/hcard") && !empty($link["href"])) { $hcard_url = $link["href"]; - } elseif (($link["rel"] == "http://joindiaspora.com/seed_location") && ($link["href"] != "")) { + } elseif (($link["rel"] == "http://joindiaspora.com/seed_location") && !empty($link["href"])) { $data["baseurl"] = trim($link["href"], '/'); - } elseif (($link["rel"] == "http://joindiaspora.com/guid") && ($link["href"] != "")) { + } elseif (($link["rel"] == "http://joindiaspora.com/guid") && !empty($link["href"])) { $data["guid"] = $link["href"]; - } elseif (($link["rel"] == "http://webfinger.net/rel/profile-page") && ($link["type"] == "text/html") && ($link["href"] != "")) { + } elseif (($link["rel"] == "http://webfinger.net/rel/profile-page") && (defaults($link, "type", "") == "text/html") && !empty($link["href"])) { $data["url"] = $link["href"]; - } elseif (($link["rel"] == NAMESPACE_FEED) && ($link["href"] != "")) { + } elseif (($link["rel"] == NAMESPACE_FEED) && !empty($link["href"])) { $data["poll"] = $link["href"]; - } elseif (($link["rel"] == NAMESPACE_POCO) && ($link["href"] != "")) { + } elseif (($link["rel"] == NAMESPACE_POCO) && !empty($link["href"])) { $data["poco"] = $link["href"]; - } elseif (($link["rel"] == "salmon") && ($link["href"] != "")) { + } elseif (($link["rel"] == "salmon") && !empty($link["href"])) { $data["notify"] = $link["href"]; - } elseif (($link["rel"] == "diaspora-public-key") && ($link["href"] != "")) { + } elseif (($link["rel"] == "diaspora-public-key") && !empty($link["href"])) { $data["pubkey"] = base64_decode($link["href"]); //if (strstr($data["pubkey"], 'RSA ') || ($link["type"] == "RSA")) @@ -1272,15 +1272,15 @@ class Probe if (is_array($webfinger["links"])) { foreach ($webfinger["links"] as $link) { if (($link["rel"] == "http://webfinger.net/rel/profile-page") - && ($link["type"] == "text/html") + && (defaults($link, "type", "") == "text/html") && ($link["href"] != "") ) { $data["url"] = $link["href"]; - } elseif (($link["rel"] == "salmon") && ($link["href"] != "")) { + } elseif (($link["rel"] == "salmon") && !empty($link["href"])) { $data["notify"] = $link["href"]; - } elseif (($link["rel"] == NAMESPACE_FEED) && ($link["href"] != "")) { + } elseif (($link["rel"] == NAMESPACE_FEED) && !empty($link["href"])) { $data["poll"] = $link["href"]; - } elseif (($link["rel"] == "magic-public-key") && ($link["href"] != "")) { + } elseif (($link["rel"] == "magic-public-key") && !empty($link["href"])) { $pubkey = $link["href"]; if (substr($pubkey, 0, 5) === 'data:') { @@ -1436,7 +1436,7 @@ class Probe $data = []; foreach ($webfinger["links"] as $link) { if (($link["rel"] == "http://webfinger.net/rel/profile-page") - && ($link["type"] == "text/html") + && (defaults($link, "type", "") == "text/html") && ($link["href"] != "") ) { $data["url"] = $link["href"]; From 1afa6523bc6988843c576a5664b393d0d1e80e88 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 11 Sep 2018 07:07:56 +0000 Subject: [PATCH 063/428] Adding (temporary) calls to AP in existing stuff --- mod/display.php | 11 ++++++++++- mod/profile.php | 10 ++++++++++ mod/xrd.php | 4 ++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/mod/display.php b/mod/display.php index 907bf8ebba..21e28d5617 100644 --- a/mod/display.php +++ b/mod/display.php @@ -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,14 @@ function display_init(App $a) displayShowFeed($item["id"], false); } + if (stristr(defaults($_SERVER, 'HTTP_ACCEPT', ''), 'application/activity+json')) { + $wall_item = Item::selectFirst(['id', 'uid'], ['guid' => $item['guid'], 'wall' => true]); + if ($wall_item['uid'] == 180) { + $data = ActivityPub::createActivityFromItem($wall_item['id']); + echo json_encode($data); + exit(); + } + } if ($item["id"] != $item["parent"]) { $item = Item::selectFirstForUser(local_user(), $fields, ['id' => $item["parent"]]); } diff --git a/mod/profile.php b/mod/profile.php index 2e3ccd28c5..fd23964e41 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -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,15 @@ function profile_init(App $a) DFRN::autoRedir($a, $which); } + if (stristr(defaults($_SERVER, 'HTTP_ACCEPT', ''), 'application/activity+json')) { + $user = DBA::selectFirst('user', ['uid'], ['nickname' => $which]); + if ($user['uid'] == 180) { + $data = ActivityPub::profile($user['uid']); + echo json_encode($data); + exit(); + } + } + Profile::load($a, $which, $profile); $blocked = !local_user() && !remote_user() && Config::get('system', 'block_public'); diff --git a/mod/xrd.php b/mod/xrd.php index 61505f2996..87766ca26e 100644 --- a/mod/xrd.php +++ b/mod/xrd.php @@ -92,6 +92,10 @@ function xrd_json($a, $uri, $alias, $profile_url, $r) ['rel' => 'http://purl.org/openwebauth/v1', 'type' => 'application/x-dfrn+json', 'href' => System::baseUrl().'/owa'] ] ]; + if ($r['uid'] == 180) { + $json['links'][] = ['rel' => 'self', 'type' => 'application/activity+json', 'href' => $profile_url]; + } + echo json_encode($json); killme(); } From f566db52d3b915871fb7c639130daca1746d3eaa Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 11 Sep 2018 08:04:14 +0000 Subject: [PATCH 064/428] And more notices ... --- src/Protocol/PortableContact.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Protocol/PortableContact.php b/src/Protocol/PortableContact.php index 20ee77a07c..2939f69e55 100644 --- a/src/Protocol/PortableContact.php +++ b/src/Protocol/PortableContact.php @@ -1157,9 +1157,9 @@ class PortableContact if (isset($data['version'])) { $platform = "Mastodon"; - $version = $data['version']; - $site_name = $data['title']; - $info = $data['description']; + $version = defaults($data, 'version', ''); + $site_name = defaults($data, 'title', ''); + $info = defaults($data, 'description', ''); $network = Protocol::OSTATUS; } From 7529fc61dd9169368224a092bcdf7d3cfeee1982 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 11 Sep 2018 19:54:45 -0400 Subject: [PATCH 065/428] Fix introductions notifications links --- mod/notifications.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mod/notifications.php b/mod/notifications.php index acd49de063..3934a32357 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -132,6 +132,11 @@ function notifications_content(App $a) $notif_tpl = get_markup_template('notifications.tpl'); + $notif_show_lnk = [ + 'href' => ($show ? 'notifications/' . $notifs['ident'] : 'notifications/' . $notifs['ident'] . '?show=all' ), + 'text' => ($show ? L10n::t('Show unread') : L10n::t('Show all')), + ]; + // Process the data for template creation if (defaults($notifs, 'ident', '') === 'introductions') { $sugg = get_markup_template('suggestions.tpl'); @@ -303,11 +308,6 @@ function notifications_content(App $a) $notif_nocontent = L10n::t('No more %s notifications.', $notifs['ident']); } - $notif_show_lnk = [ - 'href' => ($show ? 'notifications/' . $notifs['ident'] : 'notifications/' . $notifs['ident'] . '?show=all' ), - 'text' => ($show ? L10n::t('Show unread') : L10n::t('Show all')), - ]; - $o .= replace_macros($notif_tpl, [ '$notif_header' => $notif_header, '$tabs' => $tabs, From 8c07baf54b0d426d3e38d3d01aaeffd9ceb1d8f1 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 12 Sep 2018 06:01:28 +0000 Subject: [PATCH 066/428] Better http answers --- src/Module/Inbox.php | 23 +++++------------------ src/Protocol/ActivityPub.php | 3 +++ 2 files changed, 8 insertions(+), 18 deletions(-) diff --git a/src/Module/Inbox.php b/src/Module/Inbox.php index 86fdae7c90..0bc78b030c 100644 --- a/src/Module/Inbox.php +++ b/src/Module/Inbox.php @@ -9,6 +9,7 @@ use Friendica\Database\DBA; use Friendica\Model\Contact; use Friendica\Util\HTTPSignature; use Friendica\Util\Network; +use Friendica\Core\System; /** * ActivityPub Inbox @@ -18,30 +19,16 @@ class Inbox extends BaseModule public static function init() { $a = self::getApp(); - logger('Blubb: init 1'); $postdata = file_get_contents('php://input'); - $obj = json_decode($postdata); - - if (empty($obj)) { - exit(); + if (empty($postdata)) { + System::httpExit(400); } $tempfile = tempnam(get_temppath(), 'activitypub'); - file_put_contents($tempfile, json_encode(['header' => $_SERVER, 'body' => $obj])); + file_put_contents($tempfile, json_encode(['header' => $_SERVER, 'body' => $postdata])); - logger('Blubb: init ' . $tempfile); - exit(); -// goaway($dest); - } - - public static function post() - { - $a = self::getApp(); - - logger('Blubb: post'); - exit(); -// goaway($dest); + System::httpExit(200); } } diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index f1d885b6c6..8992c525b0 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -25,6 +25,9 @@ use Friendica\Content\Text\BBCode; * * 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 */ class ActivityPub { From 96d10c25e359b74d4b0bcab08c234625c0ecf031 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 12 Sep 2018 06:05:14 +0000 Subject: [PATCH 067/428] Issue 5733: Removing contacts does work now on the same machine as well --- mod/contacts.php | 7 +++++++ mod/dfrn_notify.php | 14 +++++++------- src/Protocol/DFRN.php | 5 +---- src/Worker/RemoveContact.php | 4 ++-- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/mod/contacts.php b/mod/contacts.php index 68f68fec3b..69bf2b47f9 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -47,6 +47,11 @@ function contacts_init(App $a) if (!DBA::isResult($contact)) { $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => 0]); } + + // Don't display contacts that are about to be deleted + if (($contact['network'] == Protocol::PHANTOM)) { + $contact = false; + } } if (DBA::isResult($contact)) { @@ -719,6 +724,8 @@ function contacts_content(App $a, $update = 0) $sql_extra = " AND `blocked` = 0 "; } + $sql_extra .= sprintf(" AND `network` != '%s' ", Protocol::PHANTOM); + $search = x($_GET, 'search') ? notags(trim($_GET['search'])) : ''; $nets = x($_GET, 'nets' ) ? notags(trim($_GET['nets'])) : ''; diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index 666c388a4a..2f76b59b97 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -79,13 +79,13 @@ function dfrn_notify_post(App $a) { $condition = []; switch ($direction) { case (-1): - $condition = ["`issued-id` = ? OR `dfrn-id` = ?", $dfrn_id, $dfrn_id]; + $condition = ["(`issued-id` = ? OR `dfrn-id` = ?) AND `uid` = ?", $dfrn_id, $dfrn_id, $user['uid']]; break; case 0: - $condition = ['issued-id' => $dfrn_id, 'duplex' => true]; + $condition = ['issued-id' => $dfrn_id, 'duplex' => true, 'uid' => $user['uid']]; break; case 1: - $condition = ['dfrn-id' => $dfrn_id, 'duplex' => true]; + $condition = ['dfrn-id' => $dfrn_id, 'duplex' => true, 'uid' => $user['uid']]; break; default: System::xmlExit(3, 'Invalid direction'); @@ -287,15 +287,15 @@ function dfrn_notify_content(App $a) { $condition = []; switch ($direction) { case (-1): - $condition = ["`issued-id` = ? OR `dfrn-id` = ?", $dfrn_id, $dfrn_id]; + $condition = ["(`issued-id` = ? OR `dfrn-id` = ?) AND `uid` = ?", $dfrn_id, $dfrn_id, $user['uid']]; $my_id = $dfrn_id; break; case 0: - $condition = ['issued-id' => $dfrn_id, 'duplex' => true]; + $condition = ['issued-id' => $dfrn_id, 'duplex' => true, 'uid' => $user['uid']]; $my_id = '1:' . $dfrn_id; break; case 1: - $condition = ['dfrn-id' => $dfrn_id, 'duplex' => true]; + $condition = ['dfrn-id' => $dfrn_id, 'duplex' => true, 'uid' => $user['uid']]; $my_id = '0:' . $dfrn_id; break; default: @@ -326,7 +326,7 @@ function dfrn_notify_content(App $a) { $pub_key = trim($importer['cpubkey']); $dplx = intval($importer['duplex']); - if (($dplx && strlen($prv_key)) || (strlen($prv_key) && !strlen($pub_key))) { + if (!empty($prv_key) && empty($pub_key)) { openssl_private_encrypt($hash, $challenge, $prv_key); openssl_private_encrypt($id_str, $encrypted_id, $prv_key); } elseif (strlen($pub_key)) { diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index b207c3ca87..3832e38e16 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -1280,10 +1280,7 @@ class DFRN } } - if (($contact['duplex'] && strlen($contact['pubkey'])) - || ($owner['page-flags'] == Contact::PAGE_COMMUNITY && strlen($contact['pubkey'])) - || ($contact['rel'] == Contact::SHARING && strlen($contact['pubkey'])) - ) { + if (empty($contact['prvkey']) && !empty($contact['pubkey'])) { openssl_public_decrypt($sent_dfrn_id, $final_dfrn_id, $contact['pubkey']); openssl_public_decrypt($challenge, $postvars['challenge'], $contact['pubkey']); } else { diff --git a/src/Worker/RemoveContact.php b/src/Worker/RemoveContact.php index b07661b7a9..8f986eab11 100644 --- a/src/Worker/RemoveContact.php +++ b/src/Worker/RemoveContact.php @@ -13,8 +13,8 @@ require_once 'include/dba.php'; class RemoveContact { public static function execute($id) { - // Only delete if the contact is archived - $condition = ['archive' => true, 'network' => Protocol::PHANTOM, 'id' => $id]; + // Only delete if the contact is to be deleted + $condition = ['network' => Protocol::PHANTOM, 'id' => $id]; $r = DBA::exists('contact', $condition); if (!DBA::isResult($r)) { return; From 7daa46503d3f0cd970fce3769ad1e79c9cecc0ef Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 12 Sep 2018 06:13:04 +0000 Subject: [PATCH 068/428] Don't risk incompatibilities --- mod/dfrn_notify.php | 2 +- src/Protocol/DFRN.php | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index 2f76b59b97..8a53ac09b6 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -326,7 +326,7 @@ function dfrn_notify_content(App $a) { $pub_key = trim($importer['cpubkey']); $dplx = intval($importer['duplex']); - if (!empty($prv_key) && empty($pub_key)) { + if (($dplx && strlen($prv_key)) || (strlen($prv_key) && !strlen($pub_key))) { openssl_private_encrypt($hash, $challenge, $prv_key); openssl_private_encrypt($id_str, $encrypted_id, $prv_key); } elseif (strlen($pub_key)) { diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 3832e38e16..b207c3ca87 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -1280,7 +1280,10 @@ class DFRN } } - if (empty($contact['prvkey']) && !empty($contact['pubkey'])) { + if (($contact['duplex'] && strlen($contact['pubkey'])) + || ($owner['page-flags'] == Contact::PAGE_COMMUNITY && strlen($contact['pubkey'])) + || ($contact['rel'] == Contact::SHARING && strlen($contact['pubkey'])) + ) { openssl_public_decrypt($sent_dfrn_id, $final_dfrn_id, $contact['pubkey']); openssl_public_decrypt($challenge, $postvars['challenge'], $contact['pubkey']); } else { From 969311cb44a2748ebc93c485e1cd57ad86e0f139 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 12 Sep 2018 18:48:18 +0000 Subject: [PATCH 069/428] Replacing the non standard "title" with "name" --- src/Protocol/ActivityPub.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index 8992c525b0..07989621f1 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -160,7 +160,7 @@ echo $return_code."\n"; $data['published'] = DateTimeFormat::utc($item["created"]."+00:00", DateTimeFormat::ATOM); $data['updated'] = DateTimeFormat::utc($item["edited"]."+00:00", DateTimeFormat::ATOM); $data['attributedTo'] = $item['author-link']; - $data['title'] = BBCode::convert($item['title'], false, 7); + $data['name'] = BBCode::convert($item['title'], false, 7); $data['content'] = BBCode::convert($item['body'], false, 7); //$data['summary'] = ''; //$data['sensitive'] = false; @@ -588,10 +588,10 @@ echo $return_code."\n"; $item['context'] = defaults($object, 'context', null); $item['conversation'] = defaults($object, 'conversation', null); $item['sensitive'] = defaults($object, 'sensitive', null); - $item['name'] = defaults($object, 'name', null); - $item['title'] = defaults($object, 'title', null); - $item['content'] = defaults($object, 'content', null); + $item['name'] = defaults($object, 'title', null); + $item['name'] = defaults($object, 'name', $item['name']); $item['summary'] = defaults($object, 'summary', null); + $item['content'] = defaults($object, 'content', null); $item['location'] = self::processElement($object, 'location', 'name', 'Place'); $item['attachments'] = defaults($object, 'attachment', null); $item['tags'] = defaults($object, 'tag', null); From c4825a8b5305df009fb548321da423feb112cf20 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 12 Sep 2018 18:49:36 +0000 Subject: [PATCH 070/428] Fixing parentheses --- mod/contacts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/contacts.php b/mod/contacts.php index 69bf2b47f9..1604f0b660 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -49,7 +49,7 @@ function contacts_init(App $a) } // Don't display contacts that are about to be deleted - if (($contact['network'] == Protocol::PHANTOM)) { + if ($contact['network'] == Protocol::PHANTOM) { $contact = false; } } From 67fa0ed433fa2519108e5f9b4715b3fdea1cb9fd Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 12 Sep 2018 21:30:10 +0000 Subject: [PATCH 071/428] Signature check added --- src/Module/Inbox.php | 13 +-- src/Protocol/ActivityPub.php | 157 +++++++++++++++++++++++++++++++++-- 2 files changed, 158 insertions(+), 12 deletions(-) diff --git a/src/Module/Inbox.php b/src/Module/Inbox.php index 0bc78b030c..63de5de12d 100644 --- a/src/Module/Inbox.php +++ b/src/Module/Inbox.php @@ -5,10 +5,7 @@ namespace Friendica\Module; use Friendica\BaseModule; -use Friendica\Database\DBA; -use Friendica\Model\Contact; -use Friendica\Util\HTTPSignature; -use Friendica\Util\Network; +use Friendica\Protocol\ActivityPub; use Friendica\Core\System; /** @@ -26,7 +23,13 @@ class Inbox extends BaseModule System::httpExit(400); } - $tempfile = tempnam(get_temppath(), 'activitypub'); + if (ActivityPub::verifySignature($postdata, $_SERVER)) { + $filename = 'signed-activitypub'; + } else { + $filename = 'failed-activitypub'; + } + + $tempfile = tempnam(get_temppath(), filename); file_put_contents($tempfile, json_encode(['header' => $_SERVER, 'body' => $postdata])); System::httpExit(200); diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index 07989621f1..83aae72aa5 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -53,16 +53,11 @@ class ActivityPub $headers[] = 'Signature: keyId="' . $owner['url'] . '#main-key' . '",headers="(request-target) host date",signature="' . $signature . '"'; $headers[] = 'Content-Type: application/activity+json'; -//print_r($headers); -//die($signed_data); -//$headers = []; -// $headers = HTTPSignature::createSig('', $headers, $owner['uprvkey'], $owner['url'] . '#main-key', false, false, 'sha256'); Network::post($target, $content, $headers); $return_code = BaseObject::getApp()->get_curl_code(); -echo $return_code."\n"; - print_r(BaseObject::getApp()->get_curl_headers()); - print_r($headers); + + echo $return_code."\n"; } /** @@ -226,6 +221,154 @@ echo $return_code."\n"; return false; } + public static function verifySignature($content, $http_headers) + { + $object = json_decode($content, true); + + if (empty($object)) { + return false; + } + + $actor = self::processElement($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 = ActivityPub::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, $algorithm)) { + return false; + } + + // Check the digest if it was 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 addd all hashes from the rfc + + if (!empty($hashalg) && base64_encode(hash($hashalg, $content, true)) != $digest[1]) { + return false; + } + } + + // Check the content-length if it was part of the signed data + if (in_array('content-length', $sig_block['headers'])) { + if (strlen($content) != $headers['content-length']) { + return false; + } + } + + return true; + + } + + private static function fetchKey($id, $actor) + { + $url = (strpos($id, '#') ? substr($id, 0, strpos($id, '#')) : $id); + + $profile = self::fetchProfile($url); + if (!empty($profile)) { + return $profile['pubkey']; + } elseif ($url != $actor) { + $profile = self::fetchProfile($actor); + if (!empty($profile)) { + return $profile['pubkey']; + } + } + + return false; + } + + /** + * @brief + * + * @param string $header + * @return array associate array with + * - \e string \b keyID + * - \e string \b algorithm + * - \e array \b headers + * - \e string \b signature + */ + private static function parseSigHeader($header) + { + $ret = []; + $matches = []; + + if (preg_match('/keyId="(.*?)"/ism',$header,$matches)) { + $ret['keyId'] = $matches[1]; + } + + if (preg_match('/algorithm="(.*?)"/ism',$header,$matches)) { + $ret['algorithm'] = $matches[1]; + } + + if (preg_match('/headers="(.*?)"/ism',$header,$matches)) { + $ret['headers'] = explode(' ', $matches[1]); + } + + if (preg_match('/signature="(.*?)"/ism',$header,$matches)) { + $ret['signature'] = base64_decode(preg_replace('/\s+/','',$matches[1])); + } + + return $ret; + } + /** * Fetches a profile from the given url * From f7b03bc5f39e0efd8c1b278d665f7babaad58985 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 12 Sep 2018 21:33:44 +0000 Subject: [PATCH 072/428] Missing $ --- src/Module/Inbox.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Module/Inbox.php b/src/Module/Inbox.php index 63de5de12d..bb0d9ef040 100644 --- a/src/Module/Inbox.php +++ b/src/Module/Inbox.php @@ -29,7 +29,7 @@ class Inbox extends BaseModule $filename = 'failed-activitypub'; } - $tempfile = tempnam(get_temppath(), filename); + $tempfile = tempnam(get_temppath(), $filename); file_put_contents($tempfile, json_encode(['header' => $_SERVER, 'body' => $postdata])); System::httpExit(200); From 63b5cb4fc688f9da2984c4c10439dba3a432633a Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 13 Sep 2018 15:46:37 +0000 Subject: [PATCH 073/428] Issue 5721: Temporarily deactivate the picture upload from private mails --- view/js/main.js | 5 +++++ view/theme/frio/templates/prv_message.tpl | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/view/js/main.js b/view/js/main.js index 4ccbc8044e..83086c82b0 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -81,6 +81,11 @@ $(function() { Dialog.doImageBrowser("comment", id); return; } + + if (bbcode == "imgprv") { + bbcode = "img"; + } + insertFormatting(bbcode, id); }); diff --git a/view/theme/frio/templates/prv_message.tpl b/view/theme/frio/templates/prv_message.tpl index 4c90dcae6d..9077c4d4c1 100644 --- a/view/theme/frio/templates/prv_message.tpl +++ b/view/theme/frio/templates/prv_message.tpl @@ -33,7 +33,7 @@
- + + From 4c56724715d1e87517cb8ae2fd79accc18f19394 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Thu, 20 Sep 2018 16:50:58 +0200 Subject: [PATCH 132/428] make share button visible in preview --- view/theme/frio/templates/jot.tpl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/view/theme/frio/templates/jot.tpl b/view/theme/frio/templates/jot.tpl index c4ccdfd864..7a4854ce44 100644 --- a/view/theme/frio/templates/jot.tpl +++ b/view/theme/frio/templates/jot.tpl @@ -117,6 +117,9 @@ {{$acl}}
+ + + + + {{* PHP Values. *}} +
+
+
{{$php.0}}
+
+ + + + {{foreach $php.1 as $k => $p}} + + {{/foreach}} + +
ConfigurationValue
{{$k}}{{$p}}
+
+
+
From 16d37acca178f8e6e49484194516a5762e3f77b0 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Thu, 27 Sep 2018 19:00:24 +0200 Subject: [PATCH 209/428] fix indent --- view/theme/frio/templates/admin/summary.tpl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/view/theme/frio/templates/admin/summary.tpl b/view/theme/frio/templates/admin/summary.tpl index 6cdcb65929..ff70a0c7cb 100644 --- a/view/theme/frio/templates/admin/summary.tpl +++ b/view/theme/frio/templates/admin/summary.tpl @@ -64,13 +64,13 @@
{{$php.0}}
- - - {{foreach $php.1 as $k => $p}} - - {{/foreach}} - -
ConfigurationValue
{{$k}}{{$p}}
+ ConfigurationValue + + {{foreach $php.1 as $k => $p}} + {{$k}}{{$p}} + {{/foreach}} + +
From 1803862fc54e2968af275841c1e48a66dd0d4aa9 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Thu, 27 Sep 2018 19:46:28 +0200 Subject: [PATCH 210/428] associative array + adding mysql value + removing table header --- mod/admin.php | 12 ++++++++++-- view/theme/frio/templates/admin/summary.tpl | 12 ++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index 0cb30924a8..562845ecc8 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -908,7 +908,15 @@ function admin_page_summary(App $a) $queues = ['label' => L10n::t('Message queues'), 'queue' => $queue, 'workerq' => $workerqueue]; - $php_settings = [L10n::t('PHP Values'), ['upload_max_filesize' => ini_get('upload_max_filesize'), 'post_max_size' => ini_get('post_max_size'), 'memory_limit' => ini_get('memory_limit')]]; + + $r = q("SHOW variables LIKE 'max_allowed_packet'"); + $max_allowed_packet = (($r) ? $r[0]['Value'] : 0); + + $server_settings = ['label' => L10n::t('Server Settings'), + 'php' => ['upload_max_filesize' => ini_get('upload_max_filesize'), + 'post_max_size' => ini_get('post_max_size'), + 'memory_limit' => ini_get('memory_limit')], + 'mysql' => ['max_allowed_packet' => $max_allowed_packet]]; $t = get_markup_template('admin/summary.tpl'); return replace_macros($t, [ @@ -924,7 +932,7 @@ function admin_page_summary(App $a) '$codename' => FRIENDICA_CODENAME, '$build' => Config::get('system', 'build'), '$addons' => [L10n::t('Active addons'), $a->addons], - '$php' => $php_settings, + '$serversettings' => $server_settings, '$showwarning' => $showwarning, '$warningtext' => $warningtext ]); diff --git a/view/theme/frio/templates/admin/summary.tpl b/view/theme/frio/templates/admin/summary.tpl index ff70a0c7cb..3c33f92fdb 100644 --- a/view/theme/frio/templates/admin/summary.tpl +++ b/view/theme/frio/templates/admin/summary.tpl @@ -58,15 +58,19 @@
{{$platform}} '{{$codename}}' {{$version.1}} - {{$build}}
- {{* PHP Values. *}} + {{* Server Settings. *}}

-
{{$php.0}}
+
{{$serversettings.label}}
- - {{foreach $php.1 as $k => $p}} + + {{foreach $serversettings.php as $k => $p}} + + {{/foreach}} + + {{foreach $serversettings.mysql as $k => $p}} {{/foreach}} From 1add30cc5b4cd83c08e46fe127daa6c8195e204a Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Thu, 27 Sep 2018 20:04:33 +0200 Subject: [PATCH 211/428] Adding serversettings table in template for non frio themes --- view/templates/admin/summary.tpl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/view/templates/admin/summary.tpl b/view/templates/admin/summary.tpl index 8929cfbecd..202fd43b3e 100644 --- a/view/templates/admin/summary.tpl +++ b/view/templates/admin/summary.tpl @@ -44,5 +44,22 @@
{{$platform}} '{{$codename}}' {{$version.1}} - {{$build}} +
+
{{$serversettings.label}}
+
+
ConfigurationValue
PHP
{{$k}}{{$p}}
MySQL / MariaDB
{{$k}}{{$p}}
+ + + {{foreach $serversettings.php as $k => $p}} + + {{/foreach}} + + {{foreach $serversettings.mysql as $k => $p}} + + {{/foreach}} + +
PHP
{{$k}}{{$p}}
MySQL / MariaDB
{{$k}}{{$p}}
+ +
From a36d010f8635e74293bb1264f9defb6d8f24b45b Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 27 Sep 2018 21:03:29 +0000 Subject: [PATCH 212/428] Composer-foo --- composer.lock | 586 ++++++++++++++++++++++++++++---------------------- 1 file changed, 325 insertions(+), 261 deletions(-) diff --git a/composer.lock b/composer.lock index 27e0f329e0..1c5c25c0f4 100644 --- a/composer.lock +++ b/composer.lock @@ -41,16 +41,16 @@ }, { "name": "bower-asset/Chart-js", - "version": "v2.7.2", + "version": "v2.7.1", "source": { "type": "git", "url": "https://github.com/chartjs/Chart.js.git", - "reference": "98f104cdd03617f1300b417b3d60c23d4e3e3403" + "reference": "0fead21939b92c15093c1b7d5ee2627fb5900fff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/chartjs/Chart.js/zipball/98f104cdd03617f1300b417b3d60c23d4e3e3403", - "reference": "98f104cdd03617f1300b417b3d60c23d4e3e3403", + "url": "https://api.github.com/repos/chartjs/Chart.js/zipball/0fead21939b92c15093c1b7d5ee2627fb5900fff", + "reference": "0fead21939b92c15093c1b7d5ee2627fb5900fff", "shasum": "" }, "type": "bower-asset-library", @@ -69,7 +69,7 @@ "MIT" ], "description": "Simple HTML5 charts using the canvas element.", - "time": "2018-03-01T21:45:21+00:00" + "time": "2017-10-28T15:01:52+00:00" }, { "name": "bower-asset/base64", @@ -135,16 +135,16 @@ }, { "name": "bower-asset/vue", - "version": "v2.5.17", + "version": "v2.5.16", "source": { "type": "git", "url": "https://github.com/vuejs/vue.git", - "reference": "636c9b4ef17f2062720b677cbbe613f146f4d4db" + "reference": "25342194016dc3bcc81cb3e8e229b0fb7ba1d1d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vuejs/vue/zipball/636c9b4ef17f2062720b677cbbe613f146f4d4db", - "reference": "636c9b4ef17f2062720b677cbbe613f146f4d4db", + "url": "https://api.github.com/repos/vuejs/vue/zipball/25342194016dc3bcc81cb3e8e229b0fb7ba1d1d6", + "reference": "25342194016dc3bcc81cb3e8e229b0fb7ba1d1d6", "shasum": "" }, "type": "bower-asset-library" @@ -195,119 +195,30 @@ ], "time": "2016-04-25T04:17:52+00:00" }, - { - "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.3", + "version": "v2.5.1", "source": { "type": "git", "url": "https://github.com/DivineOmega/password_exposed.git", - "reference": "1f1b49e3ec55b0f07115d342b145091368b081c4" + "reference": "c928bf722eb02398df11076add60df070cb55581" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/DivineOmega/password_exposed/zipball/1f1b49e3ec55b0f07115d342b145091368b081c4", - "reference": "1f1b49e3ec55b0f07115d342b145091368b081c4", + "url": "https://api.github.com/repos/DivineOmega/password_exposed/zipball/c928bf722eb02398df11076add60df070cb55581", + "reference": "c928bf722eb02398df11076add60df070cb55581", "shasum": "" }, "require": { - "divineomega/do-file-cache-psr-6": "^2.0", "guzzlehttp/guzzle": "^6.3", "paragonie/certainty": "^1", - "php": ">=5.6" + "php": ">=5.6", + "rapidwebltd/rw-file-cache-psr-6": "^1.0" }, "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", @@ -330,7 +241,7 @@ } ], "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-07-12T22:09:43+00:00" + "time": "2018-04-02T18:16:36+00:00" }, { "name": "ezyang/htmlpurifier", @@ -378,16 +289,16 @@ }, { "name": "fxp/composer-asset-plugin", - "version": "v1.4.4", + "version": "v1.4.2", "source": { "type": "git", "url": "https://github.com/fxpio/composer-asset-plugin.git", - "reference": "0d07328eef6e6f3753aa835fd2faef7fed1717bf" + "reference": "61352d99940d2b2392a5d2db83b8c0ef5faf222a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fxpio/composer-asset-plugin/zipball/0d07328eef6e6f3753aa835fd2faef7fed1717bf", - "reference": "0d07328eef6e6f3753aa835fd2faef7fed1717bf", + "url": "https://api.github.com/repos/fxpio/composer-asset-plugin/zipball/61352d99940d2b2392a5d2db83b8c0ef5faf222a", + "reference": "61352d99940d2b2392a5d2db83b8c0ef5faf222a", "shasum": "" }, "require": { @@ -395,7 +306,7 @@ "php": ">=5.3.3" }, "require-dev": { - "composer/composer": "^1.6.0" + "composer/composer": "^1.4.0" }, "type": "composer-plugin", "extra": { @@ -433,20 +344,20 @@ "npm", "package" ], - "time": "2018-07-02T11:37:17+00:00" + "time": "2017-10-20T06:53:56+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "6.3.3", + "version": "6.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" + "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", - "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", "shasum": "" }, "require": { @@ -456,7 +367,7 @@ }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "phpunit/phpunit": "^4.0 || ^5.0", "psr/log": "^1.0" }, "suggest": { @@ -465,7 +376,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.3-dev" + "dev-master": "6.2-dev" } }, "autoload": { @@ -498,7 +409,7 @@ "rest", "web service" ], - "time": "2018-04-22T15:46:56+00:00" + "time": "2017-06-22T18:50:49+00:00" }, { "name": "guzzlehttp/promises", @@ -761,16 +672,16 @@ }, { "name": "mobiledetect/mobiledetectlib", - "version": "2.8.33", + "version": "2.8.30", "source": { "type": "git", "url": "https://github.com/serbanghita/Mobile-Detect.git", - "reference": "cd385290f9a0d609d2eddd165a1e44ec1bf12102" + "reference": "5500bbbf312fe77ef0c7223858dad84fe49ee0c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/cd385290f9a0d609d2eddd165a1e44ec1bf12102", - "reference": "cd385290f9a0d609d2eddd165a1e44ec1bf12102", + "url": "https://api.github.com/repos/serbanghita/Mobile-Detect/zipball/5500bbbf312fe77ef0c7223858dad84fe49ee0c3", + "reference": "5500bbbf312fe77ef0c7223858dad84fe49ee0c3", "shasum": "" }, "require": { @@ -809,7 +720,7 @@ "mobile detector", "php mobile detect" ], - "time": "2018-09-01T15:05:15+00:00" + "time": "2017-12-18T10:38:51+00:00" }, { "name": "npm-asset/cropperjs", @@ -950,16 +861,67 @@ }, { "name": "npm-asset/fullcalendar", - "version": "3.9.0", + "version": "3.8.2", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-3.9.0.tgz", + "url": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-3.8.2.tgz", "reference": null, - "shasum": "b608a9989f3416f0b1d526c6bdfeeaf2ac79eda5" + "shasum": "ef7dc77b89134bbe6163e51136f7a1f8bfc1d807" }, "require": { "npm-asset/jquery": ">=2,<4.0", - "npm-asset/moment": ">=2.20.1,<3.0.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" }, "type": "npm-asset-library", "extra": { @@ -1007,7 +969,7 @@ "full-sized", "jquery-plugin" ], - "time": "2018-03-05T03:30:23+00:00" + "time": "2018-01-30T23:49:01+00:00" }, { "name": "npm-asset/imagesloaded", @@ -1234,12 +1196,12 @@ }, { "name": "npm-asset/jquery-datetimepicker", - "version": "2.5.20", + "version": "2.5.17", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/jquery-datetimepicker/-/jquery-datetimepicker-2.5.20.tgz", + "url": "https://registry.npmjs.org/jquery-datetimepicker/-/jquery-datetimepicker-2.5.17.tgz", "reference": null, - "shasum": "687d6204b90b03dc93f725f8df036e1d061f37ac" + "shasum": "8857a631f248081d4072563bde40fa8c17e407b1" }, "require": { "npm-asset/jquery": ">=1.7.2", @@ -1247,14 +1209,8 @@ "npm-asset/php-date-formatter": ">=1.3.4,<2.0.0" }, "require-dev": { - "npm-asset/chai": ">=4.1.2,<5.0.0", "npm-asset/concat": "dev-github:azer/concat", "npm-asset/concat-cli": ">=4.0.0,<5.0.0", - "npm-asset/karma": ">=2.0.0,<3.0.0", - "npm-asset/karma-chai": ">=0.1.0,<0.2.0", - "npm-asset/karma-firefox-launcher": ">=1.1.0,<2.0.0", - "npm-asset/karma-mocha": ">=1.3.0,<2.0.0", - "npm-asset/mocha": ">=5.0.4,<6.0.0", "npm-asset/uglifycss": ">=0.0.27,<0.0.28", "npm-asset/uglifyjs": ">=2.4.10,<3.0.0" }, @@ -1270,13 +1226,13 @@ "url": "git+https://github.com/xdan/datetimepicker.git" }, "npm-asset-scripts": { - "test": "karma start --browsers Firefox karma.conf.js --single-run", + "test": "echo \"Error: no test specified\" && exit 1", "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 run test && npm version patch --no-git-tag-version && npm run build && npm run github" + "public": "npm version patch --no-git-tag-version && npm run build && npm run github" } }, "license": [ @@ -1286,7 +1242,7 @@ { "name": "Chupurnov", "email": "chupurnov@gmail.com", - "url": "https://xdsoft.net/" + "url": "http://xdsoft.net/" } ], "description": "jQuery Plugin DateTimePicker it is DatePicker and TimePicker in one", @@ -1300,7 +1256,7 @@ "time", "timepicker" ], - "time": "2018-03-21T16:26:39+00:00" + "time": "2018-01-23T05:56:50+00:00" }, { "name": "npm-asset/jquery-mousewheel", @@ -1359,12 +1315,45 @@ }, { "name": "npm-asset/moment", - "version": "2.22.2", + "version": "2.20.1", "dist": { "type": "tar", - "url": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", + "url": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", "reference": null, - "shasum": "3c257f9839fc0e93ff53149632239eb90783ff66" + "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|*" }, "type": "npm-asset-library", "extra": { @@ -1434,21 +1423,16 @@ "time", "validate" ], - "time": "2018-06-01T06:58:41+00:00" + "time": "2017-12-19T04:44:18+00:00" }, { "name": "npm-asset/php-date-formatter", - "version": "v1.3.5", - "source": { - "type": "git", - "url": "https://github.com/kartik-v/php-date-formatter.git", - "reference": "d842e1c4e6a8d6108017b726321c305bb5ae4fb5" - }, + "version": "1.3.4", "dist": { - "type": "zip", - "url": "https://api.github.com/repos/kartik-v/php-date-formatter/zipball/d842e1c4e6a8d6108017b726321c305bb5ae4fb5", - "reference": "d842e1c4e6a8d6108017b726321c305bb5ae4fb5", - "shasum": "" + "type": "tar", + "url": "https://registry.npmjs.org/php-date-formatter/-/php-date-formatter-1.3.4.tgz", + "reference": null, + "shasum": "09a15ae0766ba0beb1900c27c1ec319ef2e4563e" }, "type": "npm-asset-library", "extra": { @@ -1461,31 +1445,35 @@ }, "npm-asset-repository": { "type": "git", - "url": "https://github.com/kartik-v/php-date-formatter.git" - } + "url": "git+https://github.com/kartik-v/php-date-formatter.git" + }, + "npm-asset-scripts": [] }, "license": [ "BSD-3-Clause" ], "authors": [ - "Kartik Visweswaran " + { + "name": "Kartik Visweswaran", + "email": "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": "2018-07-13T06:56:46+00:00" + "time": "2016-02-18T15:15:55+00:00" }, { "name": "paragonie/certainty", - "version": "v1.0.4", + "version": "v1.0.2", "source": { "type": "git", "url": "https://github.com/paragonie/certainty.git", - "reference": "d0f22c0fe579cf0e4f8ee301de5bc97ab124faac" + "reference": "a2d14f5b0b85c58329dee248d77d34e7e1202a32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/certainty/zipball/d0f22c0fe579cf0e4f8ee301de5bc97ab124faac", - "reference": "d0f22c0fe579cf0e4f8ee301de5bc97ab124faac", + "url": "https://api.github.com/repos/paragonie/certainty/zipball/a2d14f5b0b85c58329dee248d77d34e7e1202a32", + "reference": "a2d14f5b0b85c58329dee248d77d34e7e1202a32", "shasum": "" }, "require": { @@ -1532,27 +1520,28 @@ "ssl", "tls" ], - "time": "2018-04-09T07:21:55+00:00" + "time": "2018-03-12T18:34:23+00:00" }, { "name": "paragonie/constant_time_encoding", - "version": "v2.2.2", + "version": "v1.0.2", "source": { "type": "git", "url": "https://github.com/paragonie/constant_time_encoding.git", - "reference": "eccf915f45f911bfb189d1d1638d940ec6ee6e33" + "reference": "6111a38faf6fdebc14e36652d22036f379ba58d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/eccf915f45f911bfb189d1d1638d940ec6ee6e33", - "reference": "eccf915f45f911bfb189d1d1638d940ec6ee6e33", + "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/6111a38faf6fdebc14e36652d22036f379ba58d3", + "reference": "6111a38faf6fdebc14e36652d22036f379ba58d3", "shasum": "" }, "require": { - "php": "^7" + "php": "^5.3|^7" }, "require-dev": { - "phpunit/phpunit": "^6|^7", + "paragonie/random_compat": "^1|^2", + "phpunit/phpunit": "4.*|5.*", "vimeo/psalm": "^1" }, "type": "library", @@ -1594,20 +1583,20 @@ "hex2bin", "rfc4648" ], - "time": "2018-03-10T19:47:49+00:00" + "time": "2018-03-10T19:46:06+00:00" }, { "name": "paragonie/random_compat", - "version": "v2.0.17", + "version": "v2.0.11", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d" + "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d", - "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/5da4d3c796c275c55f057af5a643ae297d96b4d8", + "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8", "shasum": "" }, "require": { @@ -1639,28 +1628,27 @@ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", "keywords": [ "csprng", - "polyfill", "pseudorandom", "random" ], - "time": "2018-07-04T16:31:37+00:00" + "time": "2017-09-27T21:40:39+00:00" }, { "name": "paragonie/sodium_compat", - "version": "v1.7.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/paragonie/sodium_compat.git", - "reference": "7b73005be3c224f12c47bd75a23ce24b762e47e8" + "reference": "1f6e5682eff4a5a6a394b14331a1904f1740e432" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/7b73005be3c224f12c47bd75a23ce24b762e47e8", - "reference": "7b73005be3c224f12c47bd75a23ce24b762e47e8", + "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/1f6e5682eff4a5a6a394b14331a1904f1740e432", + "reference": "1f6e5682eff4a5a6a394b14331a1904f1740e432", "shasum": "" }, "require": { - "paragonie/random_compat": ">=1", + "paragonie/random_compat": "^1|^2", "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7" }, "require-dev": { @@ -1725,7 +1713,7 @@ "secret-key cryptography", "side-channel resistant" ], - "time": "2018-09-22T03:59:58+00:00" + "time": "2018-02-15T05:50:20+00:00" }, { "name": "pear/text_languagedetect", @@ -1867,6 +1855,94 @@ ], "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", @@ -1917,16 +1993,16 @@ }, { "name": "smarty/smarty", - "version": "v3.1.33", + "version": "v3.1.31", "source": { "type": "git", "url": "https://github.com/smarty-php/smarty.git", - "reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f" + "reference": "c7d42e4a327c402897dd587871434888fde1e7a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/smarty-php/smarty/zipball/dd55b23121e55a3b4f1af90a707a6c4e5969530f", - "reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f", + "url": "https://api.github.com/repos/smarty-php/smarty/zipball/c7d42e4a327c402897dd587871434888fde1e7a9", + "reference": "c7d42e4a327c402897dd587871434888fde1e7a9", "shasum": "" }, "require": { @@ -1966,7 +2042,7 @@ "keywords": [ "templating" ], - "time": "2018-09-12T20:54:16+00:00" + "time": "2016-12-14T21:57:25+00:00" } ], "packages-dev": [ @@ -2115,6 +2191,53 @@ ], "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", @@ -2263,16 +2386,16 @@ }, { "name": "phpspec/prophecy", - "version": "1.8.0", + "version": "1.7.6", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/33a7e3c4fda54e912ff6338c48823bd5c0f0b712", + "reference": "33a7e3c4fda54e912ff6338c48823bd5c0f0b712", "shasum": "" }, "require": { @@ -2284,12 +2407,12 @@ }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8.x-dev" + "dev-master": "1.7.x-dev" } }, "autoload": { @@ -2322,7 +2445,7 @@ "spy", "stub" ], - "time": "2018-08-05T17:53:17+00:00" + "time": "2018-04-18T13:57:24+00:00" }, { "name": "phpunit/dbunit", @@ -3282,81 +3405,22 @@ "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.15", + "version": "v3.4.8", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "c2f4812ead9f847cb69e90917ca7502e6892d6b8" + "reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/c2f4812ead9f847cb69e90917ca7502e6892d6b8", - "reference": "c2f4812ead9f847cb69e90917ca7502e6892d6b8", + "url": "https://api.github.com/repos/symfony/yaml/zipball/a42f9da85c7c38d59f5e53f076fe81a091f894d0", + "reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-ctype": "~1.8" + "php": "^5.5.9|>=7.0.8" }, "conflict": { "symfony/console": "<3.4" @@ -3397,7 +3461,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-08-10T07:34:36+00:00" + "time": "2018-04-03T05:14:20+00:00" }, { "name": "webmozart/assert", From 162233e503c34a942f5093cdaa409644c4445016 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 27 Sep 2018 21:04:56 +0000 Subject: [PATCH 213/428] moved line --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index b1fde04eb9..ebf8217e5e 100644 --- a/composer.json +++ b/composer.json @@ -16,6 +16,7 @@ "php": ">=5.6.1", "ext-xml": "*", "asika/simple-console": "^1.0", + "digitalbazaar/json-ld": "^0.4.7", "divineomega/password_exposed": "^2.4", "ezyang/htmlpurifier": "~4.7.0", "league/html-to-markdown": "~4.8.0", @@ -37,8 +38,7 @@ "npm-asset/jgrowl": "^1.4", "npm-asset/fullcalendar": "^3.0.1", "npm-asset/cropperjs": "1.2.2", - "npm-asset/imagesloaded": "4.1.4", - "digitalbazaar/json-ld": "^0.4.7" + "npm-asset/imagesloaded": "4.1.4" }, "repositories": [ { From 30f67d6e140394eecd23d558b41aff3cd82c08d0 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 27 Sep 2018 21:14:01 +0000 Subject: [PATCH 214/428] removed unneded line --- src/Util/JsonLD.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Util/JsonLD.php b/src/Util/JsonLD.php index 4100b258bb..2b6fac4ad4 100644 --- a/src/Util/JsonLD.php +++ b/src/Util/JsonLD.php @@ -5,7 +5,6 @@ namespace Friendica\Util; use Friendica\Core\Cache; -use digitalbazaar\jsonld as DBJsonLD; use Exception; /** From a5ddcb367bb697516f1fe4c5bebee5cb25a760cc Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 27 Sep 2018 21:19:14 +0000 Subject: [PATCH 215/428] Newly generated messages --- util/messages.po | 1427 +++++++++++++++++++++++----------------------- 1 file changed, 728 insertions(+), 699 deletions(-) diff --git a/util/messages.po b/util/messages.po index 0495cbb86c..c27fb25627 100644 --- a/util/messages.po +++ b/util/messages.po @@ -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 \n" "Language-Team: LANGUAGE \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 "

What next

" 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 registration page " @@ -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." +#: mod/unfollow.php:38 mod/unfollow.php:88 +msgid "You aren't following this contact." 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" -msgstr "" - -#: mod/unfollow.php:76 -msgid "You aren't a friend of this contact." -msgstr "" - -#: mod/unfollow.php:82 +#: mod/unfollow.php:44 mod/unfollow.php:94 msgid "Unfollowing is currently not supported by your network." msgstr "" -#: mod/unfollow.php:103 mod/contacts.php:601 +#: mod/unfollow.php:65 +msgid "Contact unfollowed" +msgstr "" + +#: 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 "" -"%s is not reachable on your system. This is a servere " -"configuration issue that prevents the communication.. See the " -"installation page for help." +"%s is not reachable on your system. This is a severe " +"configuration issue that prevents server to server communication. See the installation page 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 may 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 " 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 "" "%s wrote the following post" msgstr "" -#: local/testshare.php:158 src/Content/Text/BBCode.php:991 +#: local/testshare.php:158 src/Content/Text/BBCode.php:992 #, php-format msgid "%2$s %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 'Setup the worker'" 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 "" From da79566125b28885d82de30d409f445f6843d4c3 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 28 Sep 2018 03:56:41 +0000 Subject: [PATCH 216/428] Relocated function --- src/Model/User.php | 17 +++++++++++++++++ src/Protocol/ActivityPub.php | 23 +++-------------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Model/User.php b/src/Model/User.php index 095bf56e72..7432b75774 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -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 * diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index 663b03e939..ce960e10d3 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -1665,23 +1665,6 @@ class ActivityPub logger('Activity ' . $url . ' had been fetched and processed.'); } - /** - * @brief Returns the user id of a given profile url - * - * @param string $profile - * - * @return integer user id - */ - private static function getUserOfProfile($profile) - { - $self = DBA::selectFirst('contact', ['uid'], ['nurl' => normalise_link($profile), 'self' => true]); - if (!DBA::isResult($self)) { - return false; - } else { - return $self['uid']; - } - } - /** * @brief perform a "follow" request * @@ -1690,7 +1673,7 @@ class ActivityPub private static function followUser($activity) { $actor = JsonLD::fetchElement($activity, 'object', 'id'); - $uid = self::getUserOfProfile($actor); + $uid = User::getIdForURL($actor); if (empty($uid)) { return; } @@ -1745,7 +1728,7 @@ class ActivityPub private static function acceptFollowUser($activity) { $actor = JsonLD::fetchElement($activity, 'object', 'actor'); - $uid = self::getUserOfProfile($actor); + $uid = User::getIdForURL($actor); if (empty($uid)) { return; } @@ -1803,7 +1786,7 @@ class ActivityPub private static function undoFollowUser($activity) { $object = JsonLD::fetchElement($activity, 'object', 'object'); - $uid = self::getUserOfProfile($object); + $uid = User::getIdForURL($object); if (empty($uid)) { return; } From 357352efcc96be6dde8196e76b372774b04cee61 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 28 Sep 2018 15:04:51 +0000 Subject: [PATCH 217/428] Changed json-ld library --- composer.json | 6 +-- composer.lock | 138 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 94 insertions(+), 50 deletions(-) diff --git a/composer.json b/composer.json index ebf8217e5e..68e5cae99b 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,6 @@ "php": ">=5.6.1", "ext-xml": "*", "asika/simple-console": "^1.0", - "digitalbazaar/json-ld": "^0.4.7", "divineomega/password_exposed": "^2.4", "ezyang/htmlpurifier": "~4.7.0", "league/html-to-markdown": "~4.8.0", @@ -38,12 +37,13 @@ "npm-asset/jgrowl": "^1.4", "npm-asset/fullcalendar": "^3.0.1", "npm-asset/cropperjs": "1.2.2", - "npm-asset/imagesloaded": "4.1.4" + "npm-asset/imagesloaded": "4.1.4", + "friendica/json-ld": "^1.0" }, "repositories": [ { "type": "vcs", - "url": "https://github.com/pear/Text_Highlighter" + "url": "https://git.friendi.ca/friendica/php-json-ld" } ], "autoload": { diff --git a/composer.lock b/composer.lock index 1c5c25c0f4..f163101481 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "36f76191086a7f81370b51d0ff8cea1d", + "content-hash": "ece71ff50417ed5fcc1a439ea554925c", "packages": [ { "name": "asika/simple-console", @@ -149,52 +149,6 @@ }, "type": "bower-asset-library" }, - { - "name": "digitalbazaar/json-ld", - "version": "0.4.7", - "source": { - "type": "git", - "url": "https://github.com/digitalbazaar/php-json-ld.git", - "reference": "dc1bd23f0ee2efd27ccf636d32d2738dabcee182" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/digitalbazaar/php-json-ld/zipball/dc1bd23f0ee2efd27ccf636d32d2738dabcee182", - "reference": "dc1bd23f0ee2efd27ccf636d32d2738dabcee182", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": ">=5.3.0" - }, - "type": "library", - "autoload": { - "files": [ - "jsonld.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Digital Bazaar, Inc.", - "email": "support@digitalbazaar.com" - } - ], - "description": "A JSON-LD Processor and API implementation in PHP.", - "homepage": "https://github.com/digitalbazaar/php-json-ld", - "keywords": [ - "JSON-LD", - "Linked Data", - "RDF", - "Semantic Web", - "json", - "jsonld" - ], - "time": "2016-04-25T04:17:52+00:00" - }, { "name": "divineomega/password_exposed", "version": "v2.5.1", @@ -287,6 +241,50 @@ ], "time": "2015-08-05T01:03:42+00:00" }, + { + "name": "friendica/json-ld", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://git.friendi.ca/friendica/php-json-ld", + "reference": "a9ac64daf01cfd97e80c36a5104247d37c0ae5ef" + }, + "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", + "url": "http://digitalbazaar.com/" + }, + { + "name": "Friendica Team", + "url": "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-09-28T00:01:12+00:00" + }, { "name": "fxp/composer-asset-plugin", "version": "v1.4.2", @@ -2046,6 +2044,52 @@ } ], "packages-dev": [ + { + "name": "digitalbazaar/json-ld", + "version": "0.4.7", + "source": { + "type": "git", + "url": "https://github.com/digitalbazaar/php-json-ld.git", + "reference": "dc1bd23f0ee2efd27ccf636d32d2738dabcee182" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/digitalbazaar/php-json-ld/zipball/dc1bd23f0ee2efd27ccf636d32d2738dabcee182", + "reference": "dc1bd23f0ee2efd27ccf636d32d2738dabcee182", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=5.3.0" + }, + "type": "library", + "autoload": { + "files": [ + "jsonld.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Digital Bazaar, Inc.", + "email": "support@digitalbazaar.com" + } + ], + "description": "A JSON-LD Processor and API implementation in PHP.", + "homepage": "https://github.com/digitalbazaar/php-json-ld", + "keywords": [ + "JSON-LD", + "Linked Data", + "RDF", + "Semantic Web", + "json", + "jsonld" + ], + "time": "2016-04-25T04:17:52+00:00" + }, { "name": "doctrine/instantiator", "version": "1.0.5", From b043c7e0f2658e32d19ccd61120df6994d8e555a Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 28 Sep 2018 15:25:20 +0000 Subject: [PATCH 218/428] Changed constant name to keep compatible with PHP 5 --- src/Protocol/ActivityPub.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index ce960e10d3..a02031f003 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -75,7 +75,7 @@ use Friendica\Core\Config; */ class ActivityPub { - const PUBLIC = 'https://www.w3.org/ns/activitystreams#Public'; + 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/', @@ -364,7 +364,7 @@ class ActivityPub $contacts[$item['author-link']] = $item['author-link']; if (!$item['private']) { - $data['to'][] = self::PUBLIC; + $data['to'][] = self::PUBLIC_COLLECTION; if (!empty($actor_profile['followers'])) { $data['cc'][] = $actor_profile['followers']; } @@ -1172,11 +1172,11 @@ class ActivityPub } foreach ($activity[$element] as $receiver) { - if ($receiver == self::PUBLIC) { + if ($receiver == self::PUBLIC_COLLECTION) { $receivers['uid:0'] = 0; } - if (($receiver == self::PUBLIC) && !empty($actor)) { + 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]; @@ -1189,7 +1189,7 @@ class ActivityPub DBA::close($contacts); } - if (in_array($receiver, [$followers, self::PUBLIC]) && !empty($actor)) { + 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); From 82987d018ae680cd937c5bdf4ffe71143644988d Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Sep 2018 07:21:57 +0000 Subject: [PATCH 219/428] Some changes for better code quality --- src/Model/Item.php | 5 ++--- src/Model/Profile.php | 2 +- src/Model/Term.php | 4 ++-- src/Module/Outbox.php | 4 ++-- src/Module/Owa.php | 2 +- src/Network/Probe.php | 4 +--- src/Protocol/ActivityPub.php | 19 ++++++++----------- 7 files changed, 17 insertions(+), 23 deletions(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index 619f5dc349..2c9be633a9 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -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]); } diff --git a/src/Model/Profile.php b/src/Model/Profile.php index d25bdd4fad..cb2754cc80 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -35,7 +35,7 @@ class Profile * * @return array Profile data */ - public static function getProfileForUser($uid) + public static function getByUID($uid) { $profile = DBA::selectFirst('profile', [], ['uid' => $uid, 'is-default' => true]); return $profile; diff --git a/src/Model/Term.php b/src/Model/Term.php index 2623125329..fb7670a306 100644 --- a/src/Model/Term.php +++ b/src/Model/Term.php @@ -33,9 +33,9 @@ class Term return $tag_text; } - public static function tagArrayFromItemId($itemid) + public static function tagArrayFromItemId($itemid, $type = [TERM_HASHTAG, TERM_MENTION]) { - $condition = ['otype' => TERM_OBJ_POST, 'oid' => $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 []; diff --git a/src/Module/Outbox.php b/src/Module/Outbox.php index 722315145f..8ddc861836 100644 --- a/src/Module/Outbox.php +++ b/src/Module/Outbox.php @@ -29,10 +29,10 @@ class Outbox extends BaseModule $page = defaults($_REQUEST, 'page', null); - $Outbox = ActivityPub::getOutbox($owner, $page); + $outbox = ActivityPub::getOutbox($owner, $page); header('Content-Type: application/activity+json'); - echo json_encode($Outbox); + echo json_encode($outbox); exit(); } } diff --git a/src/Module/Owa.php b/src/Module/Owa.php index 68f31c59de..7a5fe128c8 100644 --- a/src/Module/Owa.php +++ b/src/Module/Owa.php @@ -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:verifyMagic($contact['pubkey']); + $verified = HTTPSignature::verifyMagic($contact['pubkey']); if ($verified && $verified['header_signed'] && $verified['header_valid']) { logger('OWA header: ' . print_r($verified, true), LOGGER_DATA); diff --git a/src/Network/Probe.php b/src/Network/Probe.php index b19f34b762..2c84ddb85a 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -338,9 +338,7 @@ class Probe $ap_profile = ActivityPub::probeProfile($uri); if (!empty($ap_profile) && (defaults($data, 'network', '') != Protocol::DFRN)) { - if (!empty($ap_profile) && ($ap_profile['network'] == Protocol::ACTIVITYPUB)) { - $data = $ap_profile; - } + $data = $ap_profile; } if (!isset($data["url"])) { diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index a02031f003..58bd9dcfe1 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -113,7 +113,7 @@ class ActivityPub $data['totalItems'] = $count; // When we hide our friends we will only show the pure number but don't allow more. - $profile = Profile::getProfileForUser($owner['uid']); + $profile = Profile::getByUID($owner['uid']); if (!empty($profile['hide-friends'])) { return $data; } @@ -160,7 +160,7 @@ class ActivityPub $data['totalItems'] = $count; // When we hide our friends we will only show the pure number but don't allow more. - $profile = Profile::getProfileForUser($owner['uid']); + $profile = Profile::getByUID($owner['uid']); if (!empty($profile['hide-friends'])) { return $data; } @@ -323,8 +323,7 @@ class ActivityPub $permissions['to'][] = $actor; - $elements = ['to', 'cc', 'bto', 'bcc']; - foreach ($elements as $element) { + foreach (['to', 'cc', 'bto', 'bcc'] as $element) { if (empty($activity[$element])) { continue; } @@ -359,7 +358,7 @@ class ActivityPub $actor_profile = APContact::getProfileByURL($item['author-link']); - $terms = Term::tagArrayFromItemId($item['id']); + $terms = Term::tagArrayFromItemId($item['id'], TERM_MENTION); $contacts[$item['author-link']] = $item['author-link']; @@ -461,8 +460,7 @@ class ActivityPub $item_profile = APContact::getProfileByURL($item['owner-link']); } - $elements = ['to', 'cc', 'bto', 'bcc']; - foreach ($elements as $element) { + foreach (['to', 'cc', 'bto', 'bcc'] as $element) { if (empty($permissions[$element])) { continue; } @@ -624,7 +622,7 @@ class ActivityPub { $tags = []; - $terms = Term::tagArrayFromItemId($item['id']); + $terms = Term::tagArrayFromItemId($item['id'], TERM_MENTION); foreach ($terms as $term) { if ($term['type'] == TERM_MENTION) { $contact = Contact::getDetailsByURL($term['url']); @@ -1160,13 +1158,12 @@ class ActivityPub $followers = ''; } - $elements = ['to', 'cc', 'bto', 'bcc']; - foreach ($elements as $element) { + foreach (['to', 'cc', 'bto', 'bcc'] as $element) { if (empty($activity[$element])) { continue; } - // The receiver can be an arror or a string + // The receiver can be an array or a string if (is_string($activity[$element])) { $activity[$element] = [$activity[$element]]; } From 2fc79e3886af68463a7851e5cad2c0a968d15e73 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Sep 2018 07:48:13 +0000 Subject: [PATCH 220/428] Superfluous, since we only fetch this data --- src/Protocol/ActivityPub.php | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index 58bd9dcfe1..c04347f4e9 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -369,9 +369,6 @@ class ActivityPub } foreach ($terms as $term) { - if ($term['type'] != TERM_MENTION) { - continue; - } $profile = APContact::getProfileByURL($term['url'], false); if (!empty($profile) && empty($contacts[$profile['url']])) { $data['cc'][] = $profile['url']; @@ -384,9 +381,6 @@ class ActivityPub $mentioned = []; foreach ($terms as $term) { - if ($term['type'] != TERM_MENTION) { - continue; - } $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]); @@ -624,16 +618,14 @@ class ActivityPub $terms = Term::tagArrayFromItemId($item['id'], TERM_MENTION); foreach ($terms as $term) { - if ($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]; + $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; } From e71f4972952e61ae06d0e4970c47cee93e8cb8a1 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Sep 2018 08:14:05 +0000 Subject: [PATCH 221/428] Renamed --- src/Model/APContact.php | 2 +- src/Protocol/ActivityPub.php | 32 ++++++++++++++++---------------- src/Util/HTTPSignature.php | 4 ++-- src/Util/LDSignature.php | 2 +- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/Model/APContact.php b/src/Model/APContact.php index c8f8998ae6..efd6ed0e9d 100644 --- a/src/Model/APContact.php +++ b/src/Model/APContact.php @@ -63,7 +63,7 @@ class APContact extends BaseObject * @param boolean $update true = always update, false = never update, null = update when not found * @return array profile array */ - public static function getProfileByURL($url, $update = null) + public static function getByURL($url, $update = null) { if (empty($url)) { return false; diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index c04347f4e9..ab5da4666c 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -312,9 +312,9 @@ class ActivityPub $activity = json_decode($conversation['source'], true); $actor = JsonLD::fetchElement($activity, 'actor', 'id'); - $profile = APContact::getProfileByURL($actor); + $profile = APContact::getByURL($actor); - $item_profile = APContact::getProfileByURL($item['author-link']); + $item_profile = APContact::getByURL($item['author-link']); $exclude[] = $item['author-link']; if ($item['gravity'] == GRAVITY_PARENT) { @@ -356,7 +356,7 @@ class ActivityPub $data = array_merge($data, self::fetchPermissionBlockFromConversation($item)); - $actor_profile = APContact::getProfileByURL($item['author-link']); + $actor_profile = APContact::getByURL($item['author-link']); $terms = Term::tagArrayFromItemId($item['id'], TERM_MENTION); @@ -369,7 +369,7 @@ class ActivityPub } foreach ($terms as $term) { - $profile = APContact::getProfileByURL($term['url'], false); + $profile = APContact::getByURL($term['url'], false); if (!empty($profile) && empty($contacts[$profile['url']])) { $data['cc'][] = $profile['url']; $contacts[$profile['url']] = $profile['url']; @@ -405,7 +405,7 @@ class ActivityPub continue; } - $profile = APContact::getProfileByURL($parent['author-link'], false); + $profile = APContact::getByURL($parent['author-link'], false); if (!empty($profile) && empty($contacts[$profile['url']])) { $data['cc'][] = $profile['url']; $contacts[$profile['url']] = $profile['url']; @@ -415,7 +415,7 @@ class ActivityPub continue; } - $profile = APContact::getProfileByURL($parent['owner-link'], false); + $profile = APContact::getByURL($parent['owner-link'], false); if (!empty($profile) && empty($contacts[$profile['url']])) { $data['cc'][] = $profile['url']; $contacts[$profile['url']] = $profile['url']; @@ -449,9 +449,9 @@ class ActivityPub $inboxes = []; if ($item['gravity'] == GRAVITY_ACTIVITY) { - $item_profile = APContact::getProfileByURL($item['author-link']); + $item_profile = APContact::getByURL($item['author-link']); } else { - $item_profile = APContact::getProfileByURL($item['owner-link']); + $item_profile = APContact::getByURL($item['owner-link']); } foreach (['to', 'cc', 'bto', 'bcc'] as $element) { @@ -470,7 +470,7 @@ class ActivityPub } DBA::close($contacts); } else { - $profile = APContact::getProfileByURL($receiver); + $profile = APContact::getByURL($receiver); if (!empty($profile)) { $target = defaults($profile, 'sharedinbox', $profile['inbox']); $inboxes[$target] = $target; @@ -725,7 +725,7 @@ class ActivityPub */ public static function transmitActivity($activity, $target, $uid) { - $profile = APContact::getProfileByURL($target); + $profile = APContact::getByURL($target); $owner = User::getOwnerDataById($uid); @@ -751,7 +751,7 @@ class ActivityPub */ public static function transmitContactAccept($target, $id, $uid) { - $profile = APContact::getProfileByURL($target); + $profile = APContact::getByURL($target); $owner = User::getOwnerDataById($uid); $data = ['@context' => 'https://www.w3.org/ns/activitystreams', @@ -778,7 +778,7 @@ class ActivityPub */ public static function transmitContactReject($target, $id, $uid) { - $profile = APContact::getProfileByURL($target); + $profile = APContact::getByURL($target); $owner = User::getOwnerDataById($uid); $data = ['@context' => 'https://www.w3.org/ns/activitystreams', @@ -804,7 +804,7 @@ class ActivityPub */ public static function transmitContactUndo($target, $uid) { - $profile = APContact::getProfileByURL($target); + $profile = APContact::getByURL($target); $id = System::baseUrl() . '/activity/' . System::createGUID(); @@ -847,7 +847,7 @@ class ActivityPub */ public static function probeProfile($url) { - $apcontact = APContact::getProfileByURL($url, true); + $apcontact = APContact::getByURL($url, true); if (empty($apcontact)) { return false; } @@ -1141,7 +1141,7 @@ class ActivityPub } if (!empty($actor)) { - $profile = APContact::getProfileByURL($actor); + $profile = APContact::getByURL($actor); $followers = defaults($profile, 'followers', ''); logger('Actor: ' . $actor . ' - Followers: ' . $followers, LOGGER_DEBUG); @@ -1706,7 +1706,7 @@ class ActivityPub } logger('Updating profile for ' . $activity['object']['id'], LOGGER_DEBUG); - APContact::getProfileByURL($activity['object']['id'], true); + APContact::getByURL($activity['object']['id'], true); } /** diff --git a/src/Util/HTTPSignature.php b/src/Util/HTTPSignature.php index c02124874f..234d896078 100644 --- a/src/Util/HTTPSignature.php +++ b/src/Util/HTTPSignature.php @@ -424,12 +424,12 @@ class HTTPSignature { $url = (strpos($id, '#') ? substr($id, 0, strpos($id, '#')) : $id); - $profile = APContact::getProfileByURL($url); + $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::getProfileByURL($actor); + $profile = APContact::getByURL($actor); if (!empty($profile)) { logger('Taking key from actor ' . $actor, LOGGER_DEBUG); return ['url' => $actor, 'pubkey' => $profile['pubkey']]; diff --git a/src/Util/LDSignature.php b/src/Util/LDSignature.php index ebbffeb1e8..7776ec96c2 100644 --- a/src/Util/LDSignature.php +++ b/src/Util/LDSignature.php @@ -30,7 +30,7 @@ class LDSignature return false; } - $profile = APContact::getProfileByURL($actor); + $profile = APContact::getByURL($actor); if (empty($profile['pubkey'])) { return false; } From cb44aa83c7983996a586994d8b582a4777f4a989 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Sep 2018 12:21:57 +0000 Subject: [PATCH 222/428] Object instead of Display --- index.php | 4 ---- mod/display.php | 8 ++------ src/Module/Object.php | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 src/Module/Object.php diff --git a/index.php b/index.php index a62b7a2ea1..8b0bd47251 100644 --- a/index.php +++ b/index.php @@ -215,10 +215,6 @@ if (strlen($a->module)) { * First see if we have an addon which is masquerading as a module. */ - if ($a->module == 'object') { - $a->module = 'display'; - } - // Compatibility with the Android Diaspora client if ($a->module == 'stream') { goaway('network?f=&order=post'); diff --git a/mod/display.php b/mod/display.php index ff98e689d3..25bda99d01 100644 --- a/mod/display.php +++ b/mod/display.php @@ -78,13 +78,9 @@ function display_init(App $a) } if (ActivityPub::isRequest()) { - $wall_item = Item::selectFirst(['id', 'uid'], ['guid' => $item['guid'], 'wall' => true]); - if (DBA::isResult($wall_item)) { - $data = ActivityPub::createObjectFromItemID($wall_item['id']); - echo json_encode($data); - exit(); - } + goaway(str_replace('display/', 'object/', $a->query_string)); } + if ($item["id"] != $item["parent"]) { $item = Item::selectFirstForUser(local_user(), $fields, ['id' => $item["parent"]]); } diff --git a/src/Module/Object.php b/src/Module/Object.php new file mode 100644 index 0000000000..557b906d2b --- /dev/null +++ b/src/Module/Object.php @@ -0,0 +1,41 @@ +argv[1])) { + System::httpExit(404); + } + + if (!ActivityPub::isRequest()) { + goaway(str_replace('object/', '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::createObjectFromItemID($item['id']); + + header('Content-Type: application/activity+json'); + echo json_encode($data); + exit(); + } +} From a8b776c189e92034ecd252e71b0fc9e5fa364a13 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Sep 2018 13:15:10 +0000 Subject: [PATCH 223/428] There is now "rawContent" for technical endpoints --- index.php | 10 ++++++++-- src/Module/Followers.php | 2 +- src/Module/Following.php | 2 +- src/Module/Inbox.php | 2 +- src/Module/Object.php | 2 +- src/Module/Outbox.php | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/index.php b/index.php index 8b0bd47251..46b95c75e4 100644 --- a/index.php +++ b/index.php @@ -342,15 +342,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); diff --git a/src/Module/Followers.php b/src/Module/Followers.php index 80ad68def4..98e9f1e0ee 100644 --- a/src/Module/Followers.php +++ b/src/Module/Followers.php @@ -14,7 +14,7 @@ use Friendica\Model\User; */ class Followers extends BaseModule { - public static function init() + public static function rawContent() { $a = self::getApp(); diff --git a/src/Module/Following.php b/src/Module/Following.php index 091a505cc9..6023db4cbe 100644 --- a/src/Module/Following.php +++ b/src/Module/Following.php @@ -14,7 +14,7 @@ use Friendica\Model\User; */ class Following extends BaseModule { - public static function init() + public static function rawContent() { $a = self::getApp(); diff --git a/src/Module/Inbox.php b/src/Module/Inbox.php index 4fc450d85a..c97c3b7afb 100644 --- a/src/Module/Inbox.php +++ b/src/Module/Inbox.php @@ -15,7 +15,7 @@ use Friendica\Util\HTTPSignature; */ class Inbox extends BaseModule { - public static function init() + public static function rawContent() { $a = self::getApp(); diff --git a/src/Module/Object.php b/src/Module/Object.php index 557b906d2b..05aae84f86 100644 --- a/src/Module/Object.php +++ b/src/Module/Object.php @@ -15,7 +15,7 @@ use Friendica\Database\DBA; */ class Object extends BaseModule { - public static function init() + public static function rawContent() { $a = self::getApp(); diff --git a/src/Module/Outbox.php b/src/Module/Outbox.php index 8ddc861836..f6bad56dd6 100644 --- a/src/Module/Outbox.php +++ b/src/Module/Outbox.php @@ -14,7 +14,7 @@ use Friendica\Model\User; */ class Outbox extends BaseModule { - public static function init() + public static function rawContent() { $a = self::getApp(); From 761bdafa34bfdf1b2b43a3f06ae092e0925898ac Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Sep 2018 14:13:07 +0000 Subject: [PATCH 224/428] Correct content type --- mod/profile.php | 1 + src/Protocol/ActivityPub.php | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mod/profile.php b/mod/profile.php index 8df63705e4..e20836a059 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -55,6 +55,7 @@ function profile_init(App $a) if (DBA::isResult($user)) { $data = ActivityPub::profile($user['uid']); echo json_encode($data); + header('Content-Type: application/activity+json'); exit(); } } diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index ab5da4666c..cf9ca3dd43 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -834,8 +834,9 @@ class ActivityPub { $ret = Network::curl($url, false, $redirects, ['accept_content' => 'application/activity+json, application/ld+json']); if (!$ret['success'] || empty($ret['body'])) { - return; + return false; } + return json_decode($ret['body'], true); } From 0a699be3c0d505762f24843c3939fe97ad300563 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Sun, 30 Sep 2018 19:03:05 +0200 Subject: [PATCH 225/428] replace session return url by static pages --- mod/follow.php | 10 ++++++---- mod/unfollow.php | 12 +++++++----- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/mod/follow.php b/mod/follow.php index 627ab52033..f70a8610e4 100644 --- a/mod/follow.php +++ b/mod/follow.php @@ -25,7 +25,7 @@ function follow_post(App $a) $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 } diff --git a/mod/unfollow.php b/mod/unfollow.php index b80263a3ec..61f99ee489 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -14,7 +14,7 @@ use Friendica\Model\User; function unfollow_post() { - $return_url = $_SESSION['return_url']; + $return_url = 'contacts'; if (!local_user()) { notice(L10n::t('Permission denied.')); @@ -42,7 +42,7 @@ function unfollow_post() 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($return_url); // 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 } From 57fe36e9a3e414b21544335dad4484193edc36ae Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Sun, 30 Sep 2018 19:26:29 +0200 Subject: [PATCH 226/428] replace session return url by static pages --- mod/contacts.php | 19 ++++--------------- mod/follow.php | 2 +- mod/message.php | 8 +++----- 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/mod/contacts.php b/mod/contacts.php index 1604f0b660..fb57ce6aee 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -168,11 +168,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) @@ -476,20 +472,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') { diff --git a/mod/follow.php b/mod/follow.php index f70a8610e4..04c279c5b6 100644 --- a/mod/follow.php +++ b/mod/follow.php @@ -20,7 +20,7 @@ function follow_post(App $a) } if (isset($_REQUEST['cancel'])) { - goaway($_SESSION['return_url']); + goaway('contacts'); } $uid = local_user(); diff --git a/mod/message.php b/mod/message.php index d0a583967b..e2380fdb5c 100644 --- a/mod/message.php +++ b/mod/message.php @@ -160,7 +160,7 @@ 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]; @@ -169,8 +169,7 @@ function message_content(App $a) info(L10n::t('Message deleted.') . EOL); } - //goaway(System::baseUrl(true) . '/message' ); - goaway($_SESSION['return_url']); + goaway('/message' ); } else { $r = q("SELECT `parent-uri`,`convid` FROM `mail` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($a->argv[2]), @@ -184,8 +183,7 @@ function message_content(App $a) info(L10n::t('Conversation removed.') . EOL); } } - //goaway(System::baseUrl(true) . '/message' ); - goaway($_SESSION['return_url']); + goaway('/message' ); } } From 5456ef01855f7f6bda4f137980df5a1793712bb1 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Sep 2018 20:26:30 +0000 Subject: [PATCH 227/428] Profile update and some more is now added --- src/Protocol/ActivityPub.php | 209 +++++++++++++++++++++++++++-------- src/Worker/ProfileUpdate.php | 4 +- 2 files changed, 167 insertions(+), 46 deletions(-) diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index cf9ca3dd43..6fdd0795a5 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -44,27 +44,25 @@ use Friendica\Core\Config; * To-do: * * Receiver: - * - Update Note - * - Delete Note - * - Delete Person + * - Update (Image, Video, Article, Note) + + - Event * - Undo Announce - * - Reject Follow - * - Undo Accept - * - Undo Follow + * + * Check what this is meant to do: * - Add - * - Create Image - * - Create Video - * - Event - * - Remove * - Block * - Flag + * - Remove + * - Undo Block + * - Undo Accept (Problem: This could invert a contact accept or an event accept) * * Transmitter: + * - Delete (Application, Group, Organization, Person, Service) + * - Event + * + * Complicated: * - Announce * - Undo Announce - * - Update Person - * - Reject Follow - * - Event * * General: * - Attachments @@ -81,7 +79,9 @@ class ActivityPub 'diaspora' => 'https://diasporafoundation.org/ns/', 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', 'sensitive' => 'as:sensitive', 'Hashtag' => 'as:Hashtag']]; - + const ACCOUNT_TYPES = ['Person', 'Organization', 'Service', 'Group', 'Application']; + const CONTENT_TYPES = ['Note', 'Article', 'Video', 'Image']; + const ACTIVITY_TYPES = ['Like', 'Dislike', 'Accept', 'Reject', 'TentativeAccept']; /** * @brief Checks if the web request is done for the AP protocol * @@ -243,7 +243,6 @@ class ActivityPub */ public static function profile($uid) { - $accounttype = ['Person', 'Organization', 'Service', 'Group', 'Application']; $condition = ['uid' => $uid, 'blocked' => false, 'account_expired' => false, 'account_removed' => false, 'verified' => true]; $fields = ['guid', 'nickname', 'pubkey', 'account-type', 'page-flags']; @@ -267,7 +266,7 @@ class ActivityPub $data = ['@context' => self::CONTEXT]; $data['id'] = $contact['url']; $data['diaspora:guid'] = $user['guid']; - $data['type'] = $accounttype[$user['account-type']]; + $data['type'] = self::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']; @@ -431,6 +430,29 @@ class ActivityPub return $data; } + /** + * @brief Fetches a list of inboxes of followers of a given user + * + * @param integer $uid User ID + * + * @return array of follower inboxes + */ + private static function fetchTargetInboxesforUser($uid) + { + $inboxes = []; + + $contacts = DBA::select('contact', ['notify', 'batch'], ['uid' => $uid, + 'rel' => [Contact::FOLLOWER, Contact::FRIEND], 'network' => Protocol::ACTIVITYPUB, + 'archive' => false, 'pending' => false]); + while ($contact = DBA::fetch($contacts)) { + $contact = defaults($contact, 'batch', $contact['notify']); + $inboxes[$contact] = $contact; + } + DBA::close($contacts); + + return $inboxes; + } + /** * @brief Fetches an array of inboxes for the given item and user * @@ -461,14 +483,7 @@ class ActivityPub foreach ($permissions[$element] as $receiver) { if ($receiver == $item_profile['followers']) { - $contacts = DBA::select('contact', ['notify', 'batch'], ['uid' => $uid, - 'rel' => [Contact::FOLLOWER, Contact::FRIEND], 'network' => Protocol::ACTIVITYPUB, - 'archive' => false, 'pending' => false]); - while ($contact = DBA::fetch($contacts)) { - $contact = defaults($contact, 'batch', $contact['notify']); - $inboxes[$contact] = $contact; - } - DBA::close($contacts); + $inboxes = self::fetchTargetInboxesforUser($uid); } else { $profile = APContact::getByURL($receiver); if (!empty($profile)) { @@ -716,6 +731,36 @@ class ActivityPub return $data; } + /** + * @brief Transmits a profile change to the followers + * + * @param integer $uid User ID + */ + public static function transmitProfileUpdate($uid) + { + $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::profile($uid), + 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), + 'to' => [$profile['followers']], + 'cc' => []]; + + logger('Sending profile update to followers for user ' . $uid, LOGGER_DEBUG); + + $signed = LDSignature::sign($data, $owner); + + $inboxes = self::fetchTargetInboxesforUser($uid); + + foreach ($inboxes as $inbox) { + logger('Deliver profile update for user ' . $uid . ' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG); + HTTPSignature::transmit($signed, $inbox, $uid); + } + } /** * @brief Transmits a given activity to a target * @@ -1088,12 +1133,19 @@ class ActivityPub break; case 'Update': - if (in_array($object_data['object_type'], ['Person', 'Organization', 'Service', 'Group', 'Application'])) { + if (in_array($object_data['object_type'], self::CONTENT_TYPES)) { + /// @todo + } elseif (in_array($object_data['object_type'], self::ACCOUNT_TYPES)) { self::updatePerson($object_data, $body); } break; case 'Delete': + if ($object_data['object_type'] == 'Tombstone') { + self::deleteItem($object_data, $body); + } elseif (in_array($object_data['object_type'], self::ACCOUNT_TYPES)) { + self::deletePerson($object_data, $body); + } break; case 'Follow': @@ -1106,10 +1158,16 @@ class ActivityPub } break; + case 'Reject': + if ($object_data['object_type'] == 'Follow') { + self::rejectFollowUser($object_data); + } + break; + case 'Undo': if ($object_data['object_type'] == 'Follow') { self::undoFollowUser($object_data); - } elseif (in_array($object_data['object_type'], ['Like', 'Dislike', 'Accept', 'Reject', 'TentativeAccept'])) { + } elseif (in_array($object_data['object_type'], self::ACTIVITY_TYPES)) { self::undoActivity($object_data); } break; @@ -1324,26 +1382,18 @@ class ActivityPub return false; } - switch ($data['type']) { - case 'Note': - case 'Article': - case 'Video': - return self::processObject($data); - - case 'Announce': - if (empty($data['object'])) { - return false; - } - return self::fetchObject($data['object']); - - case 'Person': - case 'Tombstone': - break; - - default: - logger('Unknown object type: ' . $data['type'], LOGGER_DEBUG); - break; + if (in_array($data['type'], self::CONTENT_TYPES)) { + return self::processObject($data); } + + if ($data['type'] == 'Announce') { + if (empty($data['object'])) { + return false; + } + return self::fetchObject($data['object']); + } + + logger('Unhandled object type: ' . $data['type'], LOGGER_DEBUG); } /** @@ -1548,6 +1598,20 @@ class ActivityPub self::postItem($activity, $item, $body); } + /** + * @brief Delete items + * + * @param array $activity + * @param $body + */ + private static function deleteItem($activity) + { + $owner = Contact::getIdForURL($activity['owner']); + $object = JsonLD::fetchElement($activity, 'object', 'id'); + logger('Deleting item ' . $object . ' from ' . $owner, LOGGER_DEBUG); + Item::delete(['uri' => $object, 'owner-id' => $owner]); + } + /** * @brief * @@ -1710,6 +1774,32 @@ class ActivityPub APContact::getByURL($activity['object']['id'], true); } + /** + * @brief Delete the given profile + * + * @param array $activity + */ + private static function deletePerson($activity) + { + if (empty($activity['object']['id']) || empty($activity['object']['actor'])) { + logger('Empty object id or actor.', LOGGER_DEBUG); + return; + } + + if ($activity['object']['id'] != $activity['object']['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); + } + /** * @brief Accept a follow request * @@ -1743,6 +1833,35 @@ class ActivityPub logger('Accept contact request from contact ' . $cid . ' for user ' . $uid, LOGGER_DEBUG); } + /** + * @brief Reject a follow request + * + * @param array $activity + */ + private static function rejectFollowUser($activity) + { + $actor = JsonLD::fetchElement($activity, 'object', 'actor'); + $uid = User::getIdForURL($actor); + if (empty($uid)) { + return; + } + + $owner = User::getOwnerDataById($uid); + + $cid = Contact::getIdForURL($activity['owner'], $uid); + if (empty($cid)) { + logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); + return; + } + + 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); + } + } + /** * @brief Undo activity like "like" or "dislike" * diff --git a/src/Worker/ProfileUpdate.php b/src/Worker/ProfileUpdate.php index e33aa5d9a8..9123f77e06 100644 --- a/src/Worker/ProfileUpdate.php +++ b/src/Worker/ProfileUpdate.php @@ -1,12 +1,13 @@ Date: Sun, 30 Sep 2018 20:40:40 +0000 Subject: [PATCH 228/428] Avoiding a notice --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index 46b95c75e4..f535bcc0d1 100644 --- a/index.php +++ b/index.php @@ -353,7 +353,7 @@ if ($a->module_loaded) { // "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) { + if (!$a->error && $a->module_class && method_exists($a->module_class, 'rawContent')) { call_user_func([$a->module_class, 'rawContent']); } From fdc396e197be0f9bd42bd1919a3dd9d157b27386 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Sep 2018 20:47:28 +0000 Subject: [PATCH 229/428] "rawcontent" is now a baseobject method --- index.php | 2 +- src/BaseModule.php | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/index.php b/index.php index f535bcc0d1..46b95c75e4 100644 --- a/index.php +++ b/index.php @@ -353,7 +353,7 @@ if ($a->module_loaded) { // "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 && method_exists($a->module_class, 'rawContent')) { + if (!$a->error && $a->module_class) { call_user_func([$a->module_class, 'rawContent']); } diff --git a/src/BaseModule.php b/src/BaseModule.php index 3ad4a4f055..1da9397a78 100644 --- a/src/BaseModule.php +++ b/src/BaseModule.php @@ -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() + { } /** From 9f481c1f5e427645d96deb4153db2ae4ba77f2b6 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Sep 2018 20:48:29 +0000 Subject: [PATCH 230/428] + is * --- src/Protocol/ActivityPub.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index 6fdd0795a5..5bad98eb4c 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -45,7 +45,7 @@ use Friendica\Core\Config; * * Receiver: * - Update (Image, Video, Article, Note) - + - Event + * - Event * - Undo Announce * * Check what this is meant to do: From 93ccca58074ed79954f428fb5cf67df379f9e691 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 30 Sep 2018 21:23:40 +0000 Subject: [PATCH 231/428] AP hast to be enabled here as well --- mod/item.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/item.php b/mod/item.php index 20c0aaf747..d73bbc25d9 100644 --- a/mod/item.php +++ b/mod/item.php @@ -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) { From 72c3a62e7f1ba5679b6503d760409d5345f5a4de Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 1 Oct 2018 05:44:56 +0000 Subject: [PATCH 232/428] Profile update is now done via APDelivery --- src/Protocol/ActivityPub.php | 20 ++++++++------------ src/Worker/APDelivery.php | 2 ++ src/Worker/Delivery.php | 15 ++++++++------- src/Worker/ProfileUpdate.php | 13 ++++++++++++- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index 5bad98eb4c..4c77c8dff9 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -437,7 +437,7 @@ class ActivityPub * * @return array of follower inboxes */ - private static function fetchTargetInboxesforUser($uid) + public static function fetchTargetInboxesforUser($uid) { $inboxes = []; @@ -732,11 +732,12 @@ class ActivityPub } /** - * @brief Transmits a profile change to the followers + * @brief Transmits a profile change to a given inbox * * @param integer $uid User ID + * @param string $inbox Target inbox */ - public static function transmitProfileUpdate($uid) + public static function transmitProfileUpdate($uid, $inbox) { $owner = User::getOwnerDataById($uid); $profile = APContact::getByURL($owner['url']); @@ -750,17 +751,12 @@ class ActivityPub 'to' => [$profile['followers']], 'cc' => []]; - logger('Sending profile update to followers for user ' . $uid, LOGGER_DEBUG); - $signed = LDSignature::sign($data, $owner); - $inboxes = self::fetchTargetInboxesforUser($uid); - - foreach ($inboxes as $inbox) { - logger('Deliver profile update for user ' . $uid . ' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG); - HTTPSignature::transmit($signed, $inbox, $uid); - } + logger('Deliver profile update for user ' . $uid . ' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG); + HTTPSignature::transmit($signed, $inbox, $uid); } + /** * @brief Transmits a given activity to a target * @@ -1403,7 +1399,7 @@ class ActivityPub * * @return */ - private static function processObject(&$object) + private static function processObject($object) { if (empty($object['id'])) { return false; diff --git a/src/Worker/APDelivery.php b/src/Worker/APDelivery.php index 943238a7b4..eb0b3d9b15 100644 --- a/src/Worker/APDelivery.php +++ b/src/Worker/APDelivery.php @@ -18,6 +18,8 @@ class APDelivery extends BaseObject if ($cmd == Delivery::MAIL) { } elseif ($cmd == Delivery::SUGGESTION) { } elseif ($cmd == Delivery::RELOCATION) { + } elseif ($cmd == Delivery::PROFILEUPDATE) { + ActivityPub::transmitProfileUpdate($uid, $inbox); } else { $data = ActivityPub::createActivityFromItem($item_id); if (!empty($data)) { diff --git a/src/Worker/Delivery.php b/src/Worker/Delivery.php index 3a93d92f7b..3585b39989 100644 --- a/src/Worker/Delivery.php +++ b/src/Worker/Delivery.php @@ -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) { diff --git a/src/Worker/ProfileUpdate.php b/src/Worker/ProfileUpdate.php index 9123f77e06..7fab86cbfd 100644 --- a/src/Worker/ProfileUpdate.php +++ b/src/Worker/ProfileUpdate.php @@ -6,8 +6,10 @@ 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) { @@ -15,7 +17,16 @@ class ProfileUpdate { return; } - ActivityPub::transmitProfileUpdate($uid); + $a = BaseObject::getApp(); + + $inboxes = ActivityPub::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); } } From e3a4a9c407eb931118403cbbe855801b6f47ab52 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 1 Oct 2018 17:36:23 +0000 Subject: [PATCH 233/428] Issue 5798: We had displayed the author as owner --- include/api.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/api.php b/include/api.php index 8588b2cf89..bacdd85143 100644 --- a/include/api.php +++ b/include/api.php @@ -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())), @@ -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, @@ -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(); } @@ -4505,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"); } @@ -4515,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) { @@ -4533,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"); } } @@ -4547,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"); } } @@ -4559,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"); } } @@ -4567,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"); } } @@ -4575,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"); } } From b746ddec647956af1258c91b3e1c93f8faf690ee Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 1 Oct 2018 18:16:19 +0000 Subject: [PATCH 234/428] Issue 5797: Retweets are now displayed again via API --- include/api.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/api.php b/include/api.php index bacdd85143..cf5fdc29cd 100644 --- a/include/api.php +++ b/include/api.php @@ -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; From 6020605d5c0cedfe96a7ccc8087887e4d362db1e Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 1 Oct 2018 19:22:13 +0000 Subject: [PATCH 235/428] Account deletion could work now. --- src/Protocol/ActivityPub.php | 37 ++++++++++++++++++++++++++++++++---- src/Worker/APDelivery.php | 2 ++ src/Worker/Notifier.php | 8 ++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index 4c77c8dff9..b5cd102a51 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -57,7 +57,6 @@ use Friendica\Core\Config; * - Undo Accept (Problem: This could invert a contact accept or an event accept) * * Transmitter: - * - Delete (Application, Group, Organization, Person, Service) * - Event * * Complicated: @@ -441,9 +440,13 @@ class ActivityPub { $inboxes = []; - $contacts = DBA::select('contact', ['notify', 'batch'], ['uid' => $uid, - 'rel' => [Contact::FOLLOWER, Contact::FRIEND], 'network' => Protocol::ACTIVITYPUB, - 'archive' => false, 'pending' => false]); + $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; @@ -731,6 +734,32 @@ class ActivityPub return $data; } + /** + * @brief Transmits a profile deletion to a given inbox + * + * @param integer $uid User ID + * @param string $inbox Target inbox + */ + public static function transmitProfileDeletion($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' => self::profile($uid), + 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), + 'to' => [self::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); + } + /** * @brief Transmits a profile change to a given inbox * diff --git a/src/Worker/APDelivery.php b/src/Worker/APDelivery.php index eb0b3d9b15..22b8c8f0ff 100644 --- a/src/Worker/APDelivery.php +++ b/src/Worker/APDelivery.php @@ -18,6 +18,8 @@ class APDelivery extends BaseObject if ($cmd == Delivery::MAIL) { } elseif ($cmd == Delivery::SUGGESTION) { } elseif ($cmd == Delivery::RELOCATION) { + } elseif ($cmd == Delivery::REMOVAL) { + ActivityPub::transmitProfileDeletion($uid, $inbox); } elseif ($cmd == Delivery::PROFILEUPDATE) { ActivityPub::transmitProfileUpdate($uid, $inbox); } else { diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index b457b78008..3ab238422a 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -99,6 +99,14 @@ class Notifier foreach ($r as $contact) { Contact::terminateFriendship($user, $contact, true); } + + $inboxes = ActivityPub::fetchTargetInboxesforUser(0); + foreach ($inboxes as $inbox) { + logger('Account removal for user ' . $uid . ' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG); + Worker::add(['priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true], + 'APDelivery', Delivery::REMOVAL, '', $inbox, $uid); + } + return; } elseif ($cmd == Delivery::RELOCATION) { $normal_mode = false; From 7e9499ac132629e9cfa101c1829f8ee9cbb063c0 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 1 Oct 2018 21:09:08 +0000 Subject: [PATCH 236/428] AP contacts are now tagged upon commenting --- mod/item.php | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/mod/item.php b/mod/item.php index d73bbc25d9..5a0658b020 100644 --- a/mod/item.php +++ b/mod/item.php @@ -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; } } @@ -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"]; } } From 54c7ca58d8aba5fab491a7fe3a0bedd946446e83 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 2 Oct 2018 03:41:38 +0000 Subject: [PATCH 237/428] Repeated posts from OStatus, ActitivyPub and Twitter are now shown as is --- include/api.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/include/api.php b/include/api.php index cf5fdc29cd..4cc1753c79 100644 --- a/include/api.php +++ b/include/api.php @@ -4827,8 +4827,18 @@ 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' ? From d5203735eb2ccfd245292a86e1500f4f8a2d5335 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 2 Oct 2018 07:38:43 +0000 Subject: [PATCH 238/428] The API test should now complete again --- tests/ApiTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ApiTest.php b/tests/ApiTest.php index a3e1ced683..941ed96bf8 100644 --- a/tests/ApiTest.php +++ b/tests/ApiTest.php @@ -3388,7 +3388,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); } From d4f6261b8177d22e7bac1d7fdda24d73a360a74a Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 2 Oct 2018 08:31:58 +0000 Subject: [PATCH 239/428] Avoid notice --- src/Util/JsonLD.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Util/JsonLD.php b/src/Util/JsonLD.php index 2b6fac4ad4..ddf8d93533 100644 --- a/src/Util/JsonLD.php +++ b/src/Util/JsonLD.php @@ -64,6 +64,7 @@ class JsonLD $normalized = jsonld_normalize($jsonobj, array('algorithm' => 'URDNA2015', 'format' => 'application/nquads')); } catch (Exception $e) { + $normalized = false; logger('normalise error:' . print_r($e, true), LOGGER_DEBUG); } From fcfd04bcc9813e3bb59fa73765f1687cfa2bb978 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 2 Oct 2018 09:04:32 +0000 Subject: [PATCH 240/428] Normalize the mentions and ensure to not have duplicates --- src/Model/Term.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Model/Term.php b/src/Model/Term.php index fb7670a306..6042091c9b 100644 --- a/src/Model/Term.php +++ b/src/Model/Term.php @@ -130,12 +130,26 @@ 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); + } + + if (!empty($contact['url'])) { + $link = $contact['url']; + } } 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']]); From 9915523490e6547e9f6971884a7f502cc90d897a Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Tue, 2 Oct 2018 13:16:43 +0200 Subject: [PATCH 241/428] mod/message return to conversation if message deleted --- mod/message.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/mod/message.php b/mod/message.php index e2380fdb5c..bf1895f67d 100644 --- a/mod/message.php +++ b/mod/message.php @@ -165,11 +165,23 @@ function message_content(App $a) $cmd = $a->argv[1]; if ($cmd === 'drop') { + $r = DBA::SelectFirst('mail', ['convid'], ['id' => $a->argv[2], 'uid' => local_user()]); + if(!DBA::isResult($r)){ + info(L10n::t('Conversation not founded.') . EOL); + goaway('/message'); + } + if (DBA::delete('mail', ['id' => $a->argv[2], 'uid' => local_user()])) { info(L10n::t('Message deleted.') . EOL); } - goaway('/message' ); + $rr = DBA::SelectFirst('mail', ['id'], ['convid' => $r['convid'], 'uid' => local_user()]); + if(!DBA::isResult($rr)){ + info(L10n::t('Conversation removed.') . EOL); + goaway('/message'); + } + + goaway('/message/'.$rr['id'] ); } else { $r = q("SELECT `parent-uri`,`convid` FROM `mail` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($a->argv[2]), From 3020b0fdc4f4ccdfc1deccc23b8748066a7c9979 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 2 Oct 2018 14:48:57 +0000 Subject: [PATCH 242/428] Fix missing mentions --- src/Model/Term.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Model/Term.php b/src/Model/Term.php index 6042091c9b..854861ccb5 100644 --- a/src/Model/Term.php +++ b/src/Model/Term.php @@ -110,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]; } } @@ -137,10 +149,6 @@ class Term } else { $term = substr($tag, 1); } - - if (!empty($contact['url'])) { - $link = $contact['url']; - } } else { // This shouldn't happen $type = TERM_HASHTAG; $term = $tag; From c02dea7b02773ccca42cc0beeb105606c5a837dd Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 2 Oct 2018 15:45:39 +0000 Subject: [PATCH 243/428] removed obsolete package --- composer.lock | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) diff --git a/composer.lock b/composer.lock index f163101481..d8502c4d70 100644 --- a/composer.lock +++ b/composer.lock @@ -2044,52 +2044,6 @@ } ], "packages-dev": [ - { - "name": "digitalbazaar/json-ld", - "version": "0.4.7", - "source": { - "type": "git", - "url": "https://github.com/digitalbazaar/php-json-ld.git", - "reference": "dc1bd23f0ee2efd27ccf636d32d2738dabcee182" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/digitalbazaar/php-json-ld/zipball/dc1bd23f0ee2efd27ccf636d32d2738dabcee182", - "reference": "dc1bd23f0ee2efd27ccf636d32d2738dabcee182", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": ">=5.3.0" - }, - "type": "library", - "autoload": { - "files": [ - "jsonld.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Digital Bazaar, Inc.", - "email": "support@digitalbazaar.com" - } - ], - "description": "A JSON-LD Processor and API implementation in PHP.", - "homepage": "https://github.com/digitalbazaar/php-json-ld", - "keywords": [ - "JSON-LD", - "Linked Data", - "RDF", - "Semantic Web", - "json", - "jsonld" - ], - "time": "2016-04-25T04:17:52+00:00" - }, { "name": "doctrine/instantiator", "version": "1.0.5", From fa3bbc5f4575eb8cd97026d6dc3d87d44b72422d Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Tue, 2 Oct 2018 18:13:58 +0200 Subject: [PATCH 244/428] Code Standards + return path for \!local_user() and cancel --- mod/message.php | 10 +++++----- mod/unfollow.php | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/mod/message.php b/mod/message.php index bf1895f67d..4a569155b5 100644 --- a/mod/message.php +++ b/mod/message.php @@ -165,9 +165,9 @@ function message_content(App $a) $cmd = $a->argv[1]; if ($cmd === 'drop') { - $r = DBA::SelectFirst('mail', ['convid'], ['id' => $a->argv[2], 'uid' => local_user()]); + $message = DBA::selectFirst('mail', ['convid'], ['id' => $a->argv[2], 'uid' => local_user()]); if(!DBA::isResult($r)){ - info(L10n::t('Conversation not founded.') . EOL); + info(L10n::t('Conversation not found.') . EOL); goaway('/message'); } @@ -175,13 +175,13 @@ function message_content(App $a) info(L10n::t('Message deleted.') . EOL); } - $rr = DBA::SelectFirst('mail', ['id'], ['convid' => $r['convid'], 'uid' => local_user()]); - if(!DBA::isResult($rr)){ + $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/'.$rr['id'] ); + 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]), diff --git a/mod/unfollow.php b/mod/unfollow.php index 61f99ee489..9b0e206904 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -18,14 +18,10 @@ function unfollow_post() 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.'/'.$contact['id']); + goaway($return_url . '/' . $contact['id']); // NOTREACHED } @@ -73,7 +73,7 @@ function unfollow_content(App $a) if (!local_user()) { notice(L10n::t('Permission denied.')); - goaway($return_url); + goaway('/login'); // NOTREACHED } From ecb67cfcb465e3d5a987f20647bd17e81256d8b2 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Tue, 2 Oct 2018 18:22:23 +0200 Subject: [PATCH 245/428] syntax typo --- mod/message.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/message.php b/mod/message.php index 4a569155b5..38a9ecd9c2 100644 --- a/mod/message.php +++ b/mod/message.php @@ -181,7 +181,7 @@ function message_content(App $a) goaway('/message'); } - goaway('/message/' . $conversation'id'] ); + 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]), From 6d1b98dc0e951445e447a60d3ee17368891d17b8 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Tue, 2 Oct 2018 18:24:16 +0200 Subject: [PATCH 246/428] wrong var name - conversation not found --- mod/message.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/message.php b/mod/message.php index 38a9ecd9c2..264912da67 100644 --- a/mod/message.php +++ b/mod/message.php @@ -166,7 +166,7 @@ function message_content(App $a) $cmd = $a->argv[1]; if ($cmd === 'drop') { $message = DBA::selectFirst('mail', ['convid'], ['id' => $a->argv[2], 'uid' => local_user()]); - if(!DBA::isResult($r)){ + if(!DBA::isResult($message)){ info(L10n::t('Conversation not found.') . EOL); goaway('/message'); } From 518d461a8ffee656983533f04da1ca89a6936b2a Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 2 Oct 2018 20:12:38 +0000 Subject: [PATCH 247/428] Issue 5811: "objects" instead of "object" --- mod/display.php | 2 +- src/Model/Item.php | 2 +- src/Module/{Object.php => Objects.php} | 2 +- src/Protocol/ActivityPub.php | 2 +- src/Protocol/Diaspora.php | 2 +- src/Protocol/OStatus.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename src/Module/{Object.php => Objects.php} (92%) diff --git a/mod/display.php b/mod/display.php index 25bda99d01..fe8e960f9e 100644 --- a/mod/display.php +++ b/mod/display.php @@ -78,7 +78,7 @@ function display_init(App $a) } if (ActivityPub::isRequest()) { - goaway(str_replace('display/', 'object/', $a->query_string)); + goaway(str_replace('display/', 'objects/', $a->query_string)); } if ($item["id"] != $item["parent"]) { diff --git a/src/Model/Item.php b/src/Model/Item.php index 2c9be633a9..19ab371d7c 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -2361,7 +2361,7 @@ class Item extends BaseObject $guid = System::createUUID(); } - return self::getApp()->get_baseurl() . '/object/' . $guid; + return self::getApp()->get_baseurl() . '/objects/' . $guid; } /** diff --git a/src/Module/Object.php b/src/Module/Objects.php similarity index 92% rename from src/Module/Object.php rename to src/Module/Objects.php index 05aae84f86..8f9c3309b6 100644 --- a/src/Module/Object.php +++ b/src/Module/Objects.php @@ -24,7 +24,7 @@ class Object extends BaseModule } if (!ActivityPub::isRequest()) { - goaway(str_replace('object/', 'display/', $a->query_string)); + goaway(str_replace('objects/', 'display/', $a->query_string)); } $item = Item::selectFirst(['id'], ['guid' => $a->argv[1], 'wall' => true, 'private' => false]); diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index b5cd102a51..ef4a48479e 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -663,7 +663,7 @@ class ActivityPub } elseif (DBA::isResult($conversation) && !empty($conversation['conversation-uri'])) { $context_uri = $conversation['conversation-uri']; } else { - $context_uri = str_replace('/object/', '/context/', $item['parent-uri']); + $context_uri = str_replace('/objects/', '/context/', $item['parent-uri']); } return $context_uri; } diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 847809a36b..551971e504 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -1598,7 +1598,7 @@ class Diaspora unset($parts['path']); $host_url = Network::unparseURL($parts); - return $host_url . '/object/' . $guid; + return $host_url . '/objects/' . $guid; } return ""; diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index 2eb8c55390..d56bacc675 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -2004,7 +2004,7 @@ class OStatus } if (intval($item["parent"]) > 0) { - $conversation_href = $conversation_uri = str_replace('/object/', '/context/', $item['parent-uri']); + $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]); From 76cdc9e59459ba3c59febac20749e9a37490825c Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 2 Oct 2018 20:14:28 +0000 Subject: [PATCH 248/428] Renamed class --- src/Module/Objects.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Module/Objects.php b/src/Module/Objects.php index 8f9c3309b6..c52a75196a 100644 --- a/src/Module/Objects.php +++ b/src/Module/Objects.php @@ -1,6 +1,6 @@ Date: Wed, 3 Oct 2018 00:24:26 -0400 Subject: [PATCH 249/428] Fix spaces in Cache\Memcachedriver --- src/Core/Cache/MemcacheCacheDriver.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Core/Cache/MemcacheCacheDriver.php b/src/Core/Cache/MemcacheCacheDriver.php index 9e5246f5b6..207225b1a2 100644 --- a/src/Core/Cache/MemcacheCacheDriver.php +++ b/src/Core/Cache/MemcacheCacheDriver.php @@ -47,10 +47,10 @@ class MemcacheCacheDriver extends AbstractCacheDriver implements IMemoryCacheDri { $list = []; $allSlabs = $this->memcache->getExtendedStats('slabs'); - foreach($allSlabs as $slabs) { - foreach(array_keys($slabs) as $slabId) { + foreach ($allSlabs as $slabs) { + foreach (array_keys($slabs) as $slabId) { $cachedump = $this->memcache->getExtendedStats('cachedump', (int)$slabId); - foreach($cachedump as $keys => $arrVal) { + foreach ($cachedump as $keys => $arrVal) { if (!is_array($arrVal)) { continue; } From b285135ec0fa85dcd57f910aebd6fb47169a37de Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Wed, 3 Oct 2018 01:34:48 -0400 Subject: [PATCH 250/428] Update composer binary to version 1.7.2 --- bin/composer.phar | Bin 1857534 -> 1875611 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/composer.phar b/bin/composer.phar index c8152aded231addb003810c90db4694aed117490..96fa2df7bdbe24e62d2435a043fd8d5e6228d4a4 100755 GIT binary patch delta 64759 zcmc${cYIV;_5jZGKJzA%USH}YkV>ctsf6A_6(JCYWJm^*nJ_b8ny zt{o~()z)6U{wdw78YgtPd-Zx{Q|C-l?)lq09!a4dC~Sygm82YZ?xq)|k?IU#i-T2? za_`*Rilyg=B}jr^FWs&dgdUtuqK*|FTKX{sg+i5UJg+_<)ca8`t zZ;45ITbgJbD0J|RBxQ@`np~VCLwedM2m&V)Dc`I(ydk{(zZzqN*ZZ=0NNN9IfF(qx zw8^c$#Y27V?JjR~VMl96V>|0d%C+~Fxe$6^p@Cyh%H5+>-Y`L4Fgb*WENlcRhfK8p zLD#G^+l9w7SpzAnZ|GML9yQAB5bF5`kaBrv%Wu-@ngnURSum3`_cN~G{hzKrB<(V1 z3P&>-7*giN9&Mof`HeY?_Ov3Q513~bQP|&@by9^TTIl2ll9UzqCSQ$fEfzi~Wnf5Y z`aQc2d2)!FOeUSR3}YX?t)nPVWn8abKb%^$N;*6^K{_Znq}^7V@VJVv2FrxAyYH1= zvyNxOl5H;bvBuWKKF-;uQ$TO^!gYL{^NFOe50KUhajf-DVLJQxS(r+@wIawLC%-dG zs>xyVU1R56ciF3Hk1kw$is9yL6hf>=LX=6km&*cD_R=^$3OCM)ve8jjt9$kObXxs7 zBu=9Aybu*Xsk6;ZHhDK6Ny_iv`us5}MaV+Gin0swoWDpJobl4DVX&(lI;qN`XSk1X zj1-0^F_Mt7Xq5VmF#g9J9RDvJqgnSs(W5C!XSKb0UGM*XQFzAGXhZyXUo%BZgZPpi zA?3yq%>yX|6SQ{3Xrl?<`DLsFDIfj&$~&a=m|Edh1*;_G^r)5r(t=V(qa876bk6Tl zo}5_z(*5D>{4vHRoIu_nbCGgd``0@tSDj8UNrPi!gun8WM9L9jpqOGy8rR0AP>`=9 z#UDBI;PaF=q~Tbs!#0PX5>jR!n=T!X%f@=Wlp5!tgI+@fTLS5AluTrhD~=&}9HHeL zzT(ysoA2;MARnP3+t z+F2VZhk8}_N>?RRvylfAhEuE_K!SgKweTQ^ZI=2c#;_ja6KiOXyRgRqL+R8oYR@Oy zg%MmNkaAq+{FHE`I*AWYNn#UJ;HjT+^p%e!F@-H#O3G#vJeyP@?22Uwk}}tDrV`md zODaf?X1F15U6ECOHUvCx7gd}b2YpDgvrivG)Vc@;OqWGd6ppEoFYiiBwN@d zuP4_DJGne1rOW$HDWWopwYH~Bq%$qTU0pn5&}2H(-%~`^s!PomCRH#5N!h$ld9O4x zEm4}4DzF|4Q~R-xhf+&~0Vs+Ho09U!gv>1I%hV#)nv&L+eN0X(6jJYG-AK7>VZWD< z@&kkue4|KtPxNOCrRwMe>3muqA1^Xm79iwNj^ko8rHPpiVFL;mLM&3+ z-kd&&o=yT6GUMrp6l~~STwO0cQbH(Uls?K#5y}V{97W2tk4>E>{aKqJ&CW7Pg;_e` zTP`L@Ik#Y?S{jyBB+TXWkTUAj_}i$$H#^H9-JfL>wv;k(r2JxFR1&4uM_KH;Y9Qxz z`ae(75yiO%sW_X-1`Y1QQ?T+jX@6e2)RCRTD0W-+1orVwcAanyrw1ud_wQPTVq_>? zl@5Vkc&ri+e@<`d>6`>wxgBv^`b5QF3BWB*4zIU!xZvma7%59Pk84HQ#?GV(<-KLw z{gbJ_S)6N^esT&z6<;bT_kp1kSCc4J7w8a2LmD2P8h=x(XAwI%&vEfh%4vtzK8V+D zf>fNVm)7L6MdqM}kmO7|MdboEWTW2E;qtrvMWGLJ{swW`L&^!}z7I+}a|bahoXq7% zEHAH0sNm!v<&=gE1Eu|`sE6enq}%dLtouWGoO-|IT|sHmjD))P`>|f6NwKuCH@~AE z?mdb2-_nPj+v(U#xnj;zsRXxTWgpJscl6=FzU#wI!_U|)edTq_D4z@YHp!jO0j|y; zmSE@SmXrl+?^*T)_9p-Imp138Nx$bOBS4A zlU!tz&J>!2V<~JFQojC|(`wEFq(ef&eOw7%`(&`euq%Pr? zQfkRyAt{UXBIO3Lmql-ZZ>VP)T1;Y-e8q;%bHyN=FBdOg-RN?63TUQ(_*89$bi zj5PkzH&%FKDw~~@zwK?i2??Gh)s-f(*_%oyvyZ1sM^ZGh5RHQ`oLx`FlGxuO_3M{P z8}31R6#clelHPNqVO>AIg5CY<8H_*saV>OWf3C&e*1uBN&Q$!SXAYAT)iSZ>7>E2f}U%Wr0kco@>eQ2$?)PbW72R} zQ_$yMO18Fd6eBJvqk`&6Brdy7KE$PLv44CxVqlEWmz!&(JiESsCZ7ESi9>}c9~SM^m{wQxV5iIiW={kAzw#l~_@#Wm$jc0P+&>hC zkjIcErStY}nUNh*#=7R#`9sq4NG9t^%G2Y&evRs!1kqzdw9<7$n7;Q3a*F5n-_Fpx zkTnXzG=9&Ma@67B{|HmnQNe{*NkxTlJ=Z5mdF1rVdr)vVr7tUt(jyi8o`0r-E9-{J z3c-@j&>>}$_MI_QX(cmWRhh>2{mx1*5zklhqg-6opEY@^c+Eqhk1whQQFgl%_sI0^ zYvZMbRf&?R+L%1e?GJc--T>K!uW@zc(30}V+<=D5( zcS;Xcr>2bZdPch2I+#drMdg*Ol9c7c_4V|cB&$4C%Z1%fwF4N&B}4hgf}s_xX3x+v z!8o4*Amy5uOpl?$k}5^laT%OjH<;q5LP{STXuLqBmaR@J-B=eVqzG&%DR&$mrNrf@ z#!X)2C73(80!PZ_Czf1KF`v>F=*Ha3&k`voKXRmuj-KjoBct!(>n3IC9j~4wTGa6A z&F;CKEhEvj(8kt&9+4tzC*@Ud&087TDdgN<0e@4`T%Ru(2>M+e1msh^vm_52EO`5| zk)-_co7c;?3@>FA88|#&IJS*7k}_xGq(rHt(ILGzT$Jt~ZWAnApCIMa!Xq|m^EA>} zAne%4Mv-!K@7ic=$b{2Qdy2jnziFh&Bg$-R@irqklk(&Gv(g8Y!IQj7ZAfzux((v}tx|oJs0CI#zg$JBvuUDg8hTSq=g64@?irKl1(yyj1>%@*eue~F7?4xAdWXhZOb1xas0UjUEDU>r|2Ag8tglX*KqX`_p z;(9LDR@O6%=a=1k?9LdVof;no;7DJk=xsr^1YsW{CleLmGHWN@{F zl%3z-I$fGMB2%ir!bI=jyLqEjHElRs$o12>(((Q@rYPNz(5u%SpUityD!8It*oD}W zGf2w(;B3?b5HAFlIH4nmHwuv;cCNvZ^2t3L8+jM4^u-nIG;WzbfUYeMcYplU@y{XP zOvybxnN}8}_vhXl*B_;n=$g){dwe?I&*Uq)-qUd<(|e8~BKvOHFoUy@Uh0~zlL}{O zrSn&EzWwb=ZorJ1Q7i04lZxO^%A2aGzONG^Y<;E#5svs4ae|i4cs-@L)UqzK_|t|;ud$&EN+|! zX7v@coV290-r{^wvb&R{H)b)VbQc;4!IzFqkq&iW(4tW%CC|1Aj*)CuQm$R}`e>V&p%^Kv&YT;=m!`*wav3F(=Ww0GH)o=78=sbxYc7mFB)u_bgm4S5B&GMqFW;j} zJKtzainyiHxd~57^Rb1Z)aJU9!GF~?i+%K->t-L)T<-JzWp2NotTfw~A{Dv~(wrtP z2Cr-4QtNEf7&f@Lc?umvzW%Jls?2Ee-(`VS%csfG87=OfI!?|^%$0FB;8qknyiK6Hd zU+hQC=gN@*S>whQlQe-h-iYiLyZDbObYEAuFqX|Em0f8^!|0L`U$iiX&T?!VHRa_a zl-lJd9Q7mjhl*bqcI z9exCHZ0P8Bjr7I*d|_50>rKk$uU~#%S~iQoWScq$Sz`X#{a$)qh(1BOVL>vZ)WZw7 z|D%nYrB}3FNr8WZL%fJvLDCz7s%z3eu50SS0ppT|FvHZ?J-6nhQQHD2x}*yH6^=I>s9W~TWVmeL*{ zKRmzs`m=os$!_};M#9-0c3}v=Oh~y-J81_Bt4yh}LnA%VVWFcsaMZ*p!bWT;=^^j_ z==IId5&<=5p&_j)xU|DvG?e_C?8ivF5eUza^1z+%oT4HS`=zjcV@C}gHh%K3ECfw@ zk+SOAKpDRV4N}TNeJ1PKL(d(BOicQda${Y(8>Ij=h4UMU|B2x3f*C^w$c1;~GCH|2gDucjNx^%i=>n)7u`z1MtS7 zK8;~%`iDPC@&wp6ZN*0Mz~3*R>`anKgDt3&o)2&@$p--jA`KB;^__J$J)@+Td3>~R z3qN3_ygTW=5E-(B+cDjz_kySD+;+kdlqDr9>%>dGiln-z7_$hI3Uc?#i zu|;K+J?@#*tJmR^@8r_!fy{Jfkv6He)6>R-1gFsiB2Y*<`|7wslw){5$+OrJLmJ26 zIq7@&qn425PL?{B#M?NRWbidfk1n3hw#&MNGkxO{em(A9!h~2Vo}%j?70{NO7A>VN zWrDF1>H6ow9XpU+98$qmOlXM+_36*G524-Rke<0JQQB}7r_j!;=CNsv%i7q-Rm)}z z4{)o3l($cNFJ3aO87UPn=boww%lVk6md_Oa&Xp-ro-Hnql{T#yDYdQO*TQuxS}Eaf zLxRMlUX?>z>sIpCIV+omVt#l?d1C%!x6mHRt9Xw=t2!7~dsZ!EAL*-u?Bmwe91GQ& z79l@_5uTKtZSTv{RcofviO(UiwadnDN3cVr3G1kk*N@^nC{?fZGGLFc<*U!QntyD$ zx|21T*7?}S%5@9a$2XyxIqNwJudQFin(D5Z&psZ##=}0+uH~A*HP>=Mdg@xPHk4gA zm-X3s9iLRVzL8>mAMV%N4~(5FjlE`wBwwGyx}CkA1D|jMr^*XA%w$a&8yeWh+6{Bq z$7dUO_<78Y6NM#Q10bb4?u9?3V^XrTakw?ab;%*F`}D@)!pLYwOHv-Weu`Quzp0SH zY`=;5wUpR>aog3HpwjM;j@&euwHj|8%RXk@%+CL5By;i5{A(p)V_)f;o4It*Z=A@w z&DzMl7k6#s8tZ2pIjGD{wd2WAi9x0EHPgx$Lq{bCA)+t0+2=26!XSY!fI)&K)SFPy z%G?P>{2UR1K_HMa^X>B4sE;@X|GP27$57weG1TXs=b`SJ$M6~=qe#dbyaHXH(;OB535!b{ zE4Oj0kdz;NF|0~jxQX-9?VETw;LIj|aTaYZXZzya%&&r{HV>sWTeffuWcZd!*5$e_ zeCuA_!bitTeJJOy#Z}G_w(da5=aBA`qNEM)TJ_CXNysVPAoUl1;yXjimwMk8i@eyM zLDg>^Af%y8BV9>(U$33}r14uzDBw{jzUR%d{wZzPS|mKcNVHn4YSfe`6(ggtf{ZBmKJVfJbU2A zZSR@Hd@(E7>IoE7HoF&%!`uY1qM|~a=V}YM^U94zqbMDJA?CoUU0)@`K~ZmqBP*49 zY3;#*4jebn(-w65Cv*lUxfgbN{BAh=j=}+l?$c|eg9rQMc;<<@m-MM~FRFJnEpWBC z19{>yV^)WB;h;lcka)v5SBEruSBhfAfpZ7HD1nu?svKI@LHgo+vUJ!SCd2FEs-(*5Owh5P|SSoz0 z5cF`D6sL297vgobyJu0fV5h^Be&EydgU!-&zZDzEPP^+}!PZBApRb3H6D?8MxkDPN z@^Y)vb5VXQZ*9%XTj6mcahrVJAV#hNj6{(BvOd1lxvZ$Du(!BeENbYTTU9o5cJEnz z`Yb2k=|y>Yy&HNLtyqF%oe|^ZCXHf@9)7SYroks>WX%tv6>*SjRcr?3qv{ywN>tcj z&RtPD`D3eMo2I*?j2&wg5uGYy6`t;9FvcnBBU-x##A;x#$8L~sh*Jzz_3W4mX0jrm^m9UEmsTS$O;%j5&>4pe88U3b6gd2WG6B+4 z70VPx`Hob@9a=00Wh=%jq3=D$D0rq?nE?xL(ItS%tLmf3qTkY{$78{0Qd#AkTt%rF zo=;Ph!ne`Jco4r(>dk)lP?qS1kwQ46R2RUP#me!pbBcWcYy`nBC-zsoqIMX?tY%NZ zH5d1;t+U1B4Tu$RAwftpd3^;Pti}lk&*J;!nkoYpWgP0)nmmOt_O=btW+k?I~-(t5vH_PjG zqo+Pket5WIuUcV*E5;~B>y26NCFqhj$`6iFT&dPi4lZp&i6}z-Tt$q4XV8z=v>Su? zv;odMr%bi0B9OsOJY7Mm1J3Ium`v!dFF< zo(B~Nqix<6G1%%B7c~XMdA_!05G|^Bt>4}5TjYlH=M;VW&hz=3++wr4%}vFnZ(fi7 zZojzL6KwT$2E`6PDlb8gw*~C~RK~)(=M+C8##bFwWa?qU$4ZO*>R%PR6)^f;MT~s= zD~baOdHQRLbTyoPNf85g{#9X2H0I=x4G#oeZEf!6;RtV9Q-D+%es_njPex7QSs(wKW?3|~{gC9Or#3=EPntN5TP?DmIoq+-wTMH`jIMuls zBjHt;n}-q>_ucRJG&j4wjCxtvm&Yx|!V1wT7U2I2@rt}W2>9(^ibQzhXN4NPKP%Er z5yR!%epdXfVHiV~TA3_A@~7fUWkdyFg&v+$D&Obp+OAS2D)={!a2EHFnDUSPl&kPm zKxdWmBvNEzwem9soGG^$2)Sb9fwjt7CDt#kQ+}?3!v(6;7|H~AXE)-W=VrC~+TFP4 z;jK)Lr!|aKdh~+B4`>StaF2s-k@OM6JmchBYz+FBqC(Tu8iEYME@djrxlWr5#ixv> z;sBnLrdBcNy9j`o;Vh(>6go5TdMid*M^vvBux1LLqCSI^7T7UTDXPh|@|z=-y$SRD zHcq+Bf#qVCa;}jR==}xCQD!-BiSi*;DvEW&87R#oBKF^gyl`9xw;-LRSS5Z2%vP=BW~27-4e|ArEmb%YUjDvzgx{)#}vm`5p$ zswkA+r5ph5cPQhsh?45~LK+QeZgq6`ZuiP-_M-G%#tVr%<#5j2CQuOKshLZ%<@mAAr>Z-BY%pr(kkC+ zP_4!*P)@O`LY4f-O{O+b& zLr>TQ;-%t>YR6&|**`J20Vd9k%7SH|*y8cRql&FjT*2uya~2}VxWp-nc;GmzM9jjt z41~FgQUBlW?NRbyqE&}gNOYv*r|{L+iZs}9NTrc)Oi;Z;$m>c~`4p%HUaViq$I?`r z$nDUm z%2d%tLWxFHDjP$FNUjkSf-)8lsJwcJ%8`XTApDoh-EP5Kb$#FntX&&9U_=0ZakaU|6_TwL-B%UVXKy zO#yexY9l-{P@|Wzf29&8T&*gE+t;WP;e~5e_3+{v{Fmc8)eG?LTGcf9z3WuD3Q*jj z>T5PuiB9BLs*7FdV|WQAOQNo(haB}t-etey?wpPE8o3A^{o!7PbmfYc1abC zg+H#0bwJj`Du+PVD0Z)(h{Z$)D#vaYkv)G>HmjT?kbIP4+@}y8$?wnro>3|rLw^%CyG$oIyjwLDzWi2ac8#%+<7Q6B8+1}Q`=P5(D#mgD!kfY{2G-Awl38`Jzm>w&1iqY{?GBAT0H~3PkXymF|cT_ zs?v(EhLZL=yrgi2`_~ALj2`%hw}2eI(9&SFq>B^taRKNlYIeIjC=8sV`$(g!1`h32 zjq!!Ht4BY&L4a?0rHe5M%}cT1t|U4c6t%=D#@+a~OuF?7N);kCXwYe9$+wkuaBWl@S?o-u5v!seH?xx58D}FAA zU%FIT(AuRM2G4b=O5wXM)h=h48$;|xII`1^TNPw@5u?qR2W?XnMexCXRSaY8Ug7e4iGCVp_5twGqpCzh2u?Zd->XW7;RlfKd+$@3px|1q zBM}*hV2F-7a`6%ZGWJIW@p3$G>34a`BTbie^A1v(?hnxo+dP3Flmu1L(62)kn{Dj2 zsfh`I6Qaup)i3nhqLP4r5;UNCx*-NONIDDbd_+}`#5(^7N|B9Ss!4W6u`ombkEcmP zSrYa?s>;*k6aOc?|EMY_;XfX(3K(@jWopH>P)?5Q8|LOPJ{PlfWN*US|NV%;#_yuz z;1h+?0s85&W|+B6CCK+2Q0Yvds>YT>*{U=+bx<`lGatPq{*d($V0tWZR*3V^TOkH~ zo&F|RcouJYUk+*vW1m;8L`uH)ys8D}r3>hqo2x97R~}ORN{qLqZ>zj!3vp|9cC`5M zNmj@jP@PpZ5GB6x8`TFyUmvVfE7V+ZG)Fk*^5im;`h;0A5TfGMwU$8zB?H8g0cHIM zmX-9CUGZw!!cD{Y9Cd~j2K7^?$dmi2Urxvt(R&i;oQwXj+$>a+sM$FvkNW0yQ;X5*@rrDYX|=Wj|rH5P*+Z;494AOu0<|19MRNbVribo9|+cj z>hOSZDs*?ld$b!kdcY(4L&^JwxIxUFh(mieGFxsKaW#_jN_o8J=!MITc^aw*!02R6 zlA7q|FeX`(P)Ik4$ToTqLemr1OgZz+^aM0$wTYmO@*wOx}d`Cp30AP?$* z5?U_HGYnRkRIB;ToaMpm4rL}e>d-J$^R%AJ?D24BnK20_)@q93=KIt-HPMaWiaN~) zVfgp4x*vyWt|xVa$bwCgyDkVIkf|N5HGIHF;1q zN2Ax!zhz~kCR-1NMYyIn{h9=MQj6vuBRDTuD&;>GY95P%57ueQ;J`XfjsdS_ytmxV zS3vuXnmD<1z2+CI0WYBdaTk@q#0|Q{n6WzsZh98Gu}q_ z43Q$X9~lU{oZ7^yjLB#=qNCp1;tYsQ7`tw9V>GSpGN43P3-XMZODD~wAo4Qc&{G<; z8K1Q1AzH5$;QYs0H5}P)wvGKi0!E=t0-E{MWdw>REpf5rPVnGzi;>O*38D?7`7>*t zCLJEws(A~xv}j^r>o&~*_Vvj&O)mVpNmD3SZPx(0;9&DVH2JXUNp(7$x0y7=Uu%*} z@6fzsB#e|V4|qT`*$&ql3{mjMFl{BAcv5o^&Yad{!|tav{n4s9{gg&yH%DG4aP~D# z3PS$#HBI*RjF1fLaxV!k2)ggWg25I~D^ z@C%ICkT?(|?J(98cW5e{?=4{G@h4AVLgtjvZ?fcKq;r@MihtUY1ey-^+ zCw!)PKq>!zPE)DY;*%!y62a=VhS;f|z*KhMk+7*J=y9Q&2>le(n0JnNp?MUwXLTNi zG@MgAnq4Hu;KZngle}dn7bp1}4kv2kq5d0<#*sn%(`-U=8u70TdDb_Y!5Y~1kv<;2 zt=8tj!!M$JR{V}e-9)t4Q4`4dVj(7vkFW$**86=eB*n4238Nh7Hwe`e3n4TF`;ds% zcyvjQnh-v^9v=!Vd}|GdRw|Oj?jzk34vwYl31z85GAw*beP(!~*QQlqti>QH-D?rF{euFCkWs&EXbv zmK)xvM-%o&L2Ci2LeU#G4b@`A=^vW!R0gr2z>Dr0l-#?%F(ZR)uyg{60h* zEqDE-snbA9y*a@g^i6WlbE5^(gzk-9e>LU68`)Y1tgh9rk)Qruv!)R4{l=VNBB~zm z2;co|PBUF@SOOfhYZuD80_}qq62ghHj6`V~5J$F54SL!Fu(wRRG&ZZ1{l)h()OPr! zDbJ2ugd5uC^SY7p9_6L-CxBQ@S$o2|tiQ+#Yr9`dibCb3j?)q7?0)kcA zMX*+@jl~!!xvP0L0(?=W%_Ia(At}M zL$;`O#;i_%8`?~EEuNVC5!$~;Ap)V89*OMbp+hfyq_)VYLIDBwleCjG_)(d$eULVd z#$@E9leBq-(0)K+0n|W~|DX zOiU+kV?iZm+PM5n!=ekOtVa=i?=ejrWSg~ud|Lq$Bi7qv}QA=v~c->-Pkyk`8{E7*-qAEvj>tHMKZs28i z{$}mdlxEcM3X+pHYfst!|GoqOFM&>Z<1TG{G~6m{P1~Q)z6*TvX+Mp%VdEfRlo0F84uYSuVd?DP`d5lzO<0Qr+d-|I)#i=-aU=_x$mSX&)6TO=rF9!cT&8WI}`1}}|!pKUK&+qT- zK)HvLqpN2TYH%XgV#&lItO*Q^th<{%B)W;{v={cAom$Y`JtUucLR*%kBAU7HJro{= zC$#2TjHmkM&c_%!atCUQgcC`s0p8bmDKs{up7W;GqSnyR6|}vp-3G@xF-@oIR$VOo`LWgjf1c9X z?Tb-%6ATc@B9BYV4#3!tw8Nm|1H5pWb1l(w%n9vhwmeKAAxKfp1w}6USIE_jid=U! z$(2E|)#qz%A9=#(+TRub+aPgpy$|tUdJ)umpRetrs<6dE{5*8dqhFw;`TG~z7}@@% z_QL--aXxw?rhl!SQLVtBWvVVkek))1NeM`^boI%EM;Bu12~qN>@-dR85U|9F&2w~< zpt3<{gB=TWSHV4vx_=nZ-x}y_L&FCyH0WyJk7#954QH`jG$@fj^O!%YF@VNO6J}|! z0VsBwT74c&OQi}1jg;d}#~Q&kP7&wk?c}mW{j%A;g!*?`ExDzL>CzoDX7va*1fQDL zq#v&dP_JwlDF(6}x_sJbIJ`bC5pp*~Ib^L%x84jlr0DaZxLucmzHM~Vu6|kDPX2Vr zRbJgSQARu`Y;CzvA{nFMbh*JI|6{dIpH3JJgW zK{%#MOlFP(Cy&Tr#E4j5ybEl)S9gmp^hecwx{;B8q{5;7Is?3PpY96>??YF}l(Kr* zm5X}ujt6u$D|beO8qQW49fpvW&iif3(c@B(h)lEG{;Dq4!f@f*JSbk(#aL+GPCC~< zx4)}PB^f&re_AN|d`LaGKG3CZe^95@vZLf1(`z;Q@Q@2Hp|j_{2X+0` zMB#^u*VU;i`~vesy6a%mL%K0x5-i-Odr6ib*4?NGRXs3ck4_o-L&o;mrf9k*PF**~ z4Hl6Mnl%~va)0dvNrNBR*(v|i@>Tt&Z8$s^qi>jzJpb_o~^N9Yu zLO%MG?vEtg?}f*839&To34zu#H!vlfF&EO`)n!2HySm5WyAO1IW$g*wdaJM;vm+NT zUffWaSJmPPwz=f>pXyF3E~$o@pX-)tmIqp074qAk>#TVRp_~_{X`|YLsyL1Kf?|a} z4N~mrojE%~pDd5G>p$!R*ZzufE##FmY)@CKWoLzclo~20>$Bj*-=YObAFVG*VW%n3 zh?-Y3k^97?qvWVZL^_4cP&aYV&v(^cW-`uF>~PH;Osp z%FcFIU_q`_bs!E*P5Q-9XVVMtgaiHBBx)qz)1>zZ(7VKx3|%8E4j2-|=Hp5ex>@Jw zwepIfez%}RL0zz3Kcm*^WRdDXXA9;Y6FEiP#;$BVlLNM=**+Wrc=IS zy?&?zPLI+X;m$|n1gI#8)61B*aZ-IHYDFYC@z|@6w;JXA@2h zxo?T{{<8jCs4*KH@ZLVXIhnh3(T?mnY7pAmaA8)Q1FWxTba3uby%|n*>Fj=cEwNnL=jJw=td_G((tl< zVe@iR3=~&ke(dw_>IB$Qj>OsV2};H9Zq?f4{{Pa)IAEpKkS%*nhE@}v&Eh1(P&pya z5Jz%1@Q;VBkTzANQK2RWb6TQf2D<&mWyTKtQ4^v!Wl`V1yS%%ilej7(E4W7t&W^>Y z#gb@s0=LlF&^(034dDO`$yH~8@lTx{GXB&>YqKaYxKLtBX+WnMieBGjdP^eDao-lY znn{`xPD#_-X$C)m$Y&*DiJg63!6bb;_dAAgyD-ce181Tv>Qxc&2xE3fxur^fuyvXHuxE7}!}eY1%sWrLj{22bDj1R>M=1 z6G{vks;9DxiBqR168{t8t9V@hf5IFy>4@s$oW&x!6x)mje}gxJ;TN$Pp7xG5lo`3K znW{C^UpkY+h{Iq%85EWXp&i;kL>*HQ;f^7D%oqr_I2;1RC^HH-#M zO_}b=C$x&PDKXt>uU1!}m2@J=@a&8TL}n6b$f=||P0?Ucr7SXv-8%oaGs5h7EN43T zMu(UPL1QixUQPr$bp33MUKKhhc!7~T?dHpNWgNF6V)YS7(AE8aCBfM4XD^JPm#qJi zHDSp6-=GN#4yck>@%<-sByVmgClPr_PjhoCGK#MQQ}0RAF8+&dJWCW~k1epBC?KpI zADZx;q9mgmfE-IM+{g-)8sQCXWBI^1zMIrxC?OHakRpQ^erV$2yv`}^_6{n3D5Lf~ zCTIZq$(4F`=C1lkS&lV$eaUn#u#++2YH55CaO}RXNW%WqIxeeU~===E?{)X#oL^++~1I{_#gVeH^A`g zIOzJskcNmX z_6}Srs&jY^1bt-la-9W(nq5oDON4H2gNcL4`y>P}AGz5uUIo4f3<>h=ZH8kNaa={l zOQfLLO;{eC(H?g|9{HAG8F>}-;`@ecs}l)U7@}xtq-;AI0>tZ?Q-O}sGy zrddpaJTuYwgG%0*YJ5`zwSA1)aK6B3g4eQ)i8f3eT2z1{Wv(BSa9i`_w4qVCW9to=FR=%`pyx*$4N%>oYmplU83zflZm-#q8u74+2oBu90`4&^ zKnK0Nd89GX4tuUN4wgT=(s;c|NJq&MT-yCCP+sFUuFymBC$>Zor(>q%H;jc)yYzsAJFs_{A< zjG84R!qe{v6X5wJ(F5U)uQ0Xjkx_WAd~wLOt4sAZ5=z97-w=yd&hi>{Y33|+UKUhh zup;0_*Tz$rNHpXoYcSXmsLCrVDq?a36PX$ceg2lBs;m_r*z^@T#Bcq?WGW$kZ`?9whastP ztP|aaIF2|-3&VrSSeDT6m-~%}jaueyf@+f~EfZl7ZXj}%%-wih%sueq)*_kX1Bv zFQWneaojkMW&6PNH;ujd=h`=oquHnY`kO|TkS}8PlDn{_5Ivzm56;>dz@(*lL3B2| zL;hmo8>SbNeC%W6_q}0OqR}oNv6x0E^r0{a+-Nf;U{(pz2D;qFuXRXRYqutLXo^b;Ws1_7j432u<4%I_yn#a(yA4BFO!^d789L#uOfZ^ z6!hle{f~Ln1h>FajODe9%|7(1dwoGPX*-C^J7QLnM2<60(pK_s7DG8x&TkwwcCh*?M8uZRpk$N=;F4KGu{k+XU0^)8NcMHF_v+ zG2O>}CFT~B#oQ3_RvnJFn6@cId0wkYG^R&15P5`t@yQE39UboGQ0Pd0#BX{w(O7^f zR&zTsJP?HAH=AnZ)|*Vb73S8K?s^&Py#}bf#q=`xG7MVyb%@#|+ix|QFyXpqr1Ouz znzVA|E2c*(dWXCa=~=C)C}E_X2-T2g6KF!}2FBy5b2sP7zi7Eeq5p%b+x%$A#B?gMlBp-c5lnN=(QtI~W*`JV!j^6?t8g#5_mC%jW=$%c(X&HW=n zp=9;&-B7auotly1P#S+!qT|DS%9NximmeHv{y7Qu)o7#Oo~7n0ZFNI)pDavcUuym< zLrb0AIHwZUot3lB1o z8wJCKJAN>YCRpPW?78M7xNDht25kRG9|!eQ%o*~{O=h1Bo<8R=f>3MFMqe(5iSOZ6 z8L+8BYn0~&%+I9j(ZV98WD6()m|J~ny;3KjzUm6PLRqdz%EOX53Bv;Cx0y#5;>#(_ z3Y&+%2n<7!$D!m6l?zWQM$E*ZtA$$cA)xh8vQVFxK$LN`%I0DxJc$8c+aemv#N0Ci z*@D_TW|+DC=!9)sD*w6F{I$Z$l@}BODCe8uqYQlPRriNUfICl{ED!_cf0ghql<-dU z>w6baD}d{~O!>h`suSIe2pokkS-=n|zSSH(vk8$V(gl-i(5XZbW8G*Bi2@Tt5D4nH zx}}%kKbZZ4s@$T81pqD}UAEj}9ySCHb)wGMc8wuUp7yr+W>t2`hlR;rO&AKKs|(+Y zm<8aOhk7O?Y&7hG%q@l|qw&@wwm9!il}z-6Z^CDz&q#*CY!Vs7_l3x8=%MXsb74M+ zvkwlS59vdLz#|#*;Hhn~b~wDn5dU9b!chDHM;ITY*2Az(hBz`$6Sz*BW945@n2&06 zv$&tHuKRHq*&k~~UMgQyJq~@cWf9H{4)Stfc+(|t!u4Vq9DY|7 zU3fXPs0)j}KO=EQYU#6Xb+GGxbkdy|YO*Ks1(6;|X%42F(s8zkm6EU|q`j++v1DWi zGVm`v`MC2?__Z|-Gkwvc5}HkZ?j!SAvyOYfLGhJ2PTT1v-tg_;m}BI-zA}H14qx`c zJLhDz&Mx0=v8*Fc%W~|N>(C6?XSdv?h;AZ@d}wwAY0_3Ml`Zlphvh!4%I{hX-|e=< zk`Gy(X!#&sF&jSWYxyACIS-F+TN$2FlI%%XoS4ocdDBH4tB53Ci7+Q%=?l-6S_YW# zIk3+^fo49*_I{QtqM&*Us(@#{6U_3TCiA-r_^?_RW$AH6z=i#B10h9ku7djuqXej) zX^CQ%;vvbByM3+(mE*POj>X?Bh=t;vrgG@hWj4x1BP@TK;Elf4A?lGW#${mXr%#2V z4pb*+=}bm=wx6~Fieu4(yT4hJ499NK_JO6J#Kb@W(pF8Z3RoCt89*M;edM$hsPL`_ z?<1IdC!|?Scvo7C@b=vbN8Pg7x!r1HZf;>8{E>>XhBESzS5=)?l{<5G(JZXQU!=&Z zTG37q7*$u8I?19Y>6w-+MSmzvxAe{FPh53bu1=Hzs8vxH?9@p8vt$;ArJPWeW0_sh zpM2+rRC}hM4hS6r5;Pb>dcj}bFifZ4%L}Eptj6X3lH3;&wNdRgTF`4k&t#+II`4mgaWVr1k z3?3ElF{;gz>2DQ{qxU$R-;eL_njWx>&PT0)$y%mBQ2{`-D&|2Xmk?_p7c=ad6BqNu zgO=}9JrAO0k7bEEdH^?W2@{4461cI;QqDE?m+@0so!-O1pUpexGQ~fyDr~_p^QWT- zjeq9fLe?X}H8{4U~wqHD;jkM)Hx@izYyOd*4%3mHBG@KB>3}$B_2*4we*I6 zJZC8{B&tkzY@CRePJETyjDn9D&;5!^&^RwH#nqz@1LAHAK8|?HqK?VpdJEEl@Get| zV8@G=fwklZ1-TaEbak*81$w26=9AbPH5`aCfdffJBZkk2Tb!FzEXWUy>rhyver2?! zbx*@p5MJS&Md-c)j=W__&WyyHYx?9Fa*vIjc+e7OA*rSu0H=itfyi4Qw|tGSDo5#K zwGk96r|(6V;E$0|TA-T}HI)v`e|K|Dn6I6%Ab$tl?Q@#*xTP4z7GdbHDawJr^|Dx> zm_!mEF9ks_N+{VM7pKCT5zantiBaMmcJe}00?bJhG%zR~9|w=?ZF0z~j$4K+VD?*< zBsukMi&~k`y&R4UR#2{lGhfC;ga19tP-uVGk^sLc&3)my_bs~NSzKYo0eD0+(5A~G z?^U_3kF~@Qz~6_ztRcWS9+TBUGMY0{#&q{2+!lg^PmZar0O=oU9gvoXv06cA7O1^2 zDgpr~Njk&e`cjOGQ619Lg2_D1;s^>?oKS-j7E|07pdce=EYS$@RX+*GW0s@{p7$*& z@ZC8_e2Q}@-f8Hnb6svI?We@&Euz&PuQWPAWit0s<%>;l`aMhfa1@G#A)HX}ywcZ+ zc|WMYwgr5soTGA!`TCwVOaP)ONGS3}LNAeeX-WPa?x;Ih2sfC_1)4%aQn+x=5v{@p z8gS}8OST^6CORbXIw(1589XXPee!+-bB_NHs~`71o@6qWn!rMx2gM?()6#=sl-o~O zf+jOL;31YLN&9`GIsX?ryOX}0u&@{tWjB4UQOm!5Y^l;1!$y2M*#Blp%_XNFAARE+ zXp+T&m|x;kVXh8PoU=qH4;{}OmGu21+C{`Uj5Y=Jy~u;kS%h3FCPxa^5maBwmGizmYskKz6T2`_Gs>`h7VE%dZK~|qblUqC7(A(1EDu?u6;$q?G2!n;{ z193g|0o1n9m~%DfgI$VF0&%24o7H1DOR{VZh&^f>;IlI8d>DG%J_z1XnxY-Za4dU| zSW5*3E=FJq$XsiU2bEy!4QGDC{A}|H zs}+P;n+AVc1sgiPx0(P1n+WGkwm$NUf=!#K8ar(qr03e=)nm!m!rrz7`L*7*M1?Q` z!v~}5#uT8|=5C+cwiI^uv58i!5o>sj=$2pWWBWh@n_6vlMGc%?fS%>n5?cl&w%JOw zH6!ZB7T|jzzb%2)?pVAwg1wpL8EPxE}rFith>xC>v~Ku2#$=gjlHO9;@C^7-odJf z3DU>e)?Eg6DZDq%R@(zwDU2I`N!4F2tr|GNRvR$^61^1mVBKYA=?h~0MRe{9TQ03q zPrRhpBCP5;OJ6vLb(fi?P@Xo)w!RPiWu+|(Z0$BXtXgR^%JD00Q#9osZ|9N%!q%f| zGs?u7Mv?!MF_yH5W6(}n*2Zw{P`*JgJULL24r8kYzajw7S7XrTf<;JyGc|%43P$M6 zFs@qYjh=d<8~@SaNRh9t5sDm83T8H9vu%8q7=gRpNtyl z-4vAzg@sY6_{28q2Ab+WJ}*kV^8bz!W%d7p(e_epbR5<3FFR&qArvh`O1NDZoQ4bcM&S<()CjTVw5Aas!3Tp&*)KzJzehFe%$qKPKqLXW z$;j_Z6~+tJ$me7$?u$yFjvh)h`jOwN=aG*~Mu!4r=m;hKs>I^rzQy{#Tmj$&U9Q<@8M=CJG>V!yf$bP*BWPI}|J6tmJU0khGvEag@R8VuuJRTOBEIyUSrQ zN6r9u6gv{QBaa$vp{eL^Z4m@XP69E(IO4?EB2WkG&=1)`rYPI$NOf{AVrUWcVaBi} zO>X+%3>wK+hUo<`aH}KTlGTBC5ndA%e>hX@NY~I+$qgkAhph+!2heebPa{csX=uOM z54<2E#4ICDP*$S5b7~yNOc&J^j&sy0;zJmQk;5qn@^Z&`$4PZG zUXDGHCM$H6IpUzP%#mEr98S#TLdZq_W@&d9k0W&Ar=)>A=4m9p%|`N22!op8IiTnk zM@)bG-5pN$NUScc!yi!W9t(#jJ7!qB|0c`tq$Hq755@07vz22VT1s<9 zI^w}M#SsJZhT=n+`r9o6jB`6o&^5&|-VmBqgz7>^+$v5TBsa&91X!4Zj_d(p5b}FG ze22Sx2T&j3mDIn3EhYE>-pEtw!a1DiuVKtVlk_oU%>E)wN31K@T=p}UQ}Oj2 zVd6xt#)JnhGtNbkwE$TPl93lD)AkS~wmTQ$Nj8Trq7l>2T0Qen_;6_W)+h8CxjtA} z=7?_WPB36hSx}I5@j40Q5P&c>Lg*pScPEI3CZstVG~<)5vnH#R9uB6eMXZrA6FE1R zo>MwJG%ZwZbtIH>FriAsCG<&UN9d2p?UbLN>i9z!mS;qBfz(Dv38c<;ywRgt#_A1W zEm6jv5gO#`W=B%E4e+lb`MBG0K`D^Kl8^q%PW&MvdgKnZI(*77U@AXXn_^7z(ghB+ z5`ToI;-C1#6W<1+_3-D-aYi`mair-(J1M`=?)Xw0OP;&Yw77cCiRhL`A7PEx;gDYl zI@ZNsGArP$64c-5Fu<#49GGBqljGE7J1vukZ*=4;LH#`Hpx116e5og&c6sUl)7+cK zIdazrqM7lWHJ+ZMTixoOt7km+%vducsdU@;s7q2wRl0AFX{6FEm9EmwA-uaGF<~DD z2Uj2okbGVO`w|RZ!fIJIfb-c+!sG1&vrcyTJYFz?1d_nxSdtfD9p3j>RZ^>arj7H- zF1$bNY5nR~zxrL@`+Cpvx0TjMrXTqA<<(2`1w8TElV_(deQG&-k4n@ZJ}`ar*O$L{ zKz``!U?hLr+YTIoY<^OgK~}B@<%_?yvN?U~o6A=YU(-|`x#sZd6|n{$m%#cW$4mG> zqHh|_fvffOv%j;ts(STk!K3p50y?B11OGnhErSwo$@}E0$U{y|h7jDVg50)?Kc7I3-#(sL= z4=m*Q4b9)Y}$RyjNCVsel`H?%0y5Q=wxOcnPf$Rp`!yWn2@`Y2k z4JTiG7J_^}@*ALOdHhGqZ^h(||8UnC`NW}>^)pJ;ShG`sT;(*1V45LxglL?HR?eMO z9kv!{AdN(1S4E=Bvr8+h2Nl!J)2F_$eEjnKq+lTV&EM2rl>hso72V0*6Pn(0c%^$- ze(De;`Z!rQd~*7MrIlxnFKOc0CVta$(~Qf{$4*+NZ#uhjcE9}M-yyRLla z`sOVaflA14rr2HD&%Kh?VgOwBV z?|ktj7@%cfh&{LT-pyhVN=y`9 z5HawVOZ8?>e*QBD&2sC})2F9f&#t^-Szg;Xy?$e{t2z#Vlg7n$z>7*$8bKI_AcE-fClN|cxm80^LpMf|=fLm~w)15vvz4-?#&c)*h{`Jc8^iN(~dG~!Y>L7pK z3MldSe!LP=_E9;Yj|FtUw|~FEAbUD|9s~73Hei};QYUJ`q(k~ zb^q(WQ}Wy1bm(sRUw`)4viz}+oxFS!BE3g|+v~TKs%+p7@cu(fD~FXI;2x3vXLnzm zC^go$vh_v}_Mr<21Q3KOf51moqywfC(A#&nz=dk7+uVZa5#V{7oh{{6?Iqv>XN)np zq<{noS_kbBA^cXz*kJap>VPD3AW1F zpTz{1cT8}P*+I(x4y3mD>2KeLHoIFxlj+8-p}BZ#=qTmOii&pp?54K4=dQJYbNHD|?VNVkF5b9h zy!F71M{hlL<8`-Qzvnz9FeZbu$WMO@Ps{*U+T(D+DIMin|LM#~Hx3RSea3P3NhnG8iu4MA2GKZ07QY3=N&zC&xGfBz3=B$C zs4AAjkImO?-Z0}%q;N#fApQ-v*%n?{$nW8}{Z-Il0#QZp86JWc?TFQ#(@UWY=M2x} z@Q+s3_N%P!r33QIpVR3MDx_N8_`L4?oDKq^R@JqLJ4eRO&D%*hFb*0uZmFdIfd_8y z1l+`Sb+6guZ7REKj7h7oJ;-*iI}EZ&40jE(J;q|EJB+b-!_+Y*s7~3g)hzb9!yt=P zWzUH$cDlnDbM!v}&S=j;=DncP9R^uM)O(Jx*y#>qOcqh<-h(XQ-8&4ji0<|rW3kir z7?b%$Tf|Iz4zk#3dyx4UJ5b1;gDmzsuWalaZ<7zrwz+(0Js=fn}7jy^Yr}*WA6Gc-l zDXc2O5fW&7vjC=08w+u-S5ez6WtG}?3uP{C=C_o<1c*|Cv9D|ayBt*``qlVN_#3i^ zbX0L2)IvGUU2)gMu5C^r83TmWODKE*l&;88&5WGGAh)i{Tf^u#K{7{bb2KY(G*cXO zfp=!M;!!5Dl_VkoHh@Y3XqZ6Nas%F(BR*B*JKF(GSF7&FzLuIK_pjf23Y&n^zL`f> zM6~q9-IzU4Fz2gY+wDuUyyDV)KY48sxuU4S!Nvem%Qh~SRO>iMABx&XlD~RE_wD;G z1M-1xMMx~$xq54sz(TzT*EWqPc=Y~FtNiF&vDI79^+CY+2ya8P=0v637)UJfIBK5l zAN<}lY~oD)9WbqYIHo)x0 zY29S^dKI;_prx4EUN_u?%Yv4RX4VR;H^W!vvNey=gTu9X-~qVj3Xv0__}9+OQ8L^h zS1;|7o`9(+Rxnr#%3&-&b+7J{yn3%L{u<@76?Q?&A_&7PvkM6;SM<_wa?%zoS2q0_ zri=a0fN6Q-g6_;@CtkURDn9)*q4yLZupQvL0KMCL@(R%VYFF{ffclf+RKYcWT<<-v6s-Y4n8V@cCjei1~yaOt^8|J(dm&p6>(S?Gq3ZDR8 zm?ew`Gbr59TL2!4dxDazd#;cLr_ahgx;IV$zGey-fFB5(xO%w`mZ>3w2i@ z{WN571Kt#&H0943p1Kp zUSShg6v0q5VqsXca`}bIDM-0=FXUPJ-%+K7%lGQ;gG`}Fk1hWg*KNx8eL;6t{`3Xi z$qRQlyTzlM0vUM2UHfjyTleTb1w6v}%eo&PL_e?V-ZlNu{kng>4;tYIh8T#-P2E`t zXH{d$(blL~Z60R6lf^Y+_s!aV*QaYP{Ebg}zwV1~c@?}+>rZu8UPZUB{1@Gt<5i+%*tne-`E4)iE}35C z%W!uzJTCsi*T~LHUJ8mQC`P53in;_Z?Y{$p0)0!6?xqtB=dniPiP#M~#IcO>VuodTjc>e^{j-mf!TzwbRq(ht{67ErY89M4orLBO2vrg;ek; zS=Hm<-TkHix^_y&{@d#5mD_tQE-BNFWBKV{7Iw0}SyTh$T zk(0_T4@woH1#^b1Ov-P%0Jd=@B9K!9df7Zgf6ej_Xc4&JL5jY!t%FxNdnnAaipB-P zBQ1^#AuHc{`sf+?eSf}o;am*V!6>j43ZmTpDf#(hhgam*?;p5Ze&jEY9F{v%@J{>v zudN-CUwZk(MfsCo*BzF>{a0%T<-hyN+SymLC$+hkj5g;5rOPYr&BB^@k8p=oD~sM< zEMo*HeDZ2VuKUbK8ikGXR4 zAH95Xd9v3u6?d8K? zpyG-EiP2TN8zkjcJYUd#BpUgMQa1?+LeGB`TbBJtbvg^Y6ou+r`7E%6GexEn%(#sg zKr^so0QoCtk1cQ9XaE;><%WQGF%&ZS*p;r>f`C>?Lu34P{kk&x1V#^`ARX{k1mnW1 z9AAOrP^SrLl_f})ROm9uvlU2Wgu4A>u$nt{-C_gmR#bkNSvq_W&GU*nsjt^gtxk5Y zXZN&rgyJaKQDEaB5pXvODiRPu!Fd7QqC0(dafU#hI|5_^*gZiRXO@LRL7W=n#qDcjvq0^{v)+Jy)3E*e6uVh$8yp2^Gj+8Z~nK89>YhRfI9aP_qtH*ToE z9=fI&Ru{&QvnaaC;DHdK`zxnb52-Fl^1EFJE>6@)bqGzsA?XnWrZ>^zl`kqAsr(5F z50o8S3s{&hajtMuIswL-$NnkvEP=}@=ng3Mg2Z7^WhxEeVAQgJw+IXJw*lZR~{&fOFpVwnaVF zd`SyEEN}S zm!PQZL*Au_@~Xiu9g=15QhQawX6+t?Q6q3w|A1iY3+&Q;=J`&|#zo@r<-F2K z(M78Ll_8XQ$Pcnh_Z)z_-#4KWD)=pQ*`?F6%q~3+}8v66{zu7#zR!8yGkihVAvxSxlq<=acLTn=Rymr3?%{u-wYI6%{g7`!zgL-1=qW zUB_2R^-L5Trm>{T$5Ev#@EB74|G_7oYnC{uc~O7h0p-%d7>X$zfvWuW_b=-ppC2f* zLBBLq=6XZ(eSGZR{Nvy$d#?m^0ZvdHwNPzy?d|J|)XoGs#JaAdj7G34%4LTSL!B+i zUZyxdDNLB!fc91WYrfyw(o`rxW)au`btO9wNWORzTl1(NQ9uV`1dx~T!Z);`=DM7nC&`hRz5#bKR*Y=MJ{vJ zS)Ds<7N=~1nz#f~uEIrE&EK4YKaIX)1ex zj(QWNA=p%2g^&@b-M*0f1ArctHCE1Pz6^LrIah7X8V31Cu6Q?#cpLa%-&O#M6#?=> zqAaaS_z+?zFi77nU%QE&*f|MEdZ(QF_MO^m)6p$Mi(lAXZ6UA;SMSYlieT)63y!Xa zItH2m{7{F6IjA7yMHg4?pndd_1(4E=gMe@pjr^Uq5)FyqZ}A#!BjtGt1oblSnz6Qt zD3t}e%Lqnh*Ll8fM#I3$wYbAkqLpYnaV2tJuYu|&AxP6gW6{$)9DnW9*<*0MW`oNY zuN_!6?gUGP9>3BRgfR9~XOYOU3my<^*nNQWy`95?*0OWGYNMj~MhUajpKysaen&~L zq~ftz38xcaDu?`&uwb>bY(AyGrpgw<%gg8GFFmldc`_PzyV=wh!EwPPoc9&^)PqZ_ z=d@N3r=qBFD;QxtY=Gd9fEAVb2bV4(4;i4~8Zib2BNhX)tMuN*BFrAmiLio<(XhKZ zD(%n<0RZr}0!p8ISrsp#5pcCq2v+w`KBgd=o zdI$>ERUrM*;#bk80IRGy7J<$fI9<52fb?hm6%(D7xOHbEikzBtUlc!-REqp>VMo*x z>-12T{cWEBr3Mu?3k^`1PE94LxnFF5WezXUw7@38q_w~Tg;iDmUc6S?d+{3&!;6c% z_DXM}iv~NXLFmGQ;HAYalf&PDTtbh&X6cB$b$fC{R*_H8KP8NG2@gp=vP;(+*}oRqX~OJ|FU@U zFeXY66jd$*@G}b1*|~{85|FtOEJ6#Pk+T$(7Wv$h5Xt*lQGd>`%~&jsu7p$qs{>pr zVnNWq5a{&$$4_5B%|n6PsFLju96XeN<@D-Z=j1>5ID}W5ehAv~lMgK&oT#4!tWqhC zuBx+q-~ok`pHm18`@m76d4rq_YeL07P@b$SC@z0yr<(D+cU#jg{7EJP*tpHJ3Cix&AP)h7q;MXSN<@61PWH} zycvpshU7D}D8)z&gDNUA_^>(?fR5dtP`I+~X^a}e_Sa|c%c1W>0t_TUUxyI@$IMdY z&6S8+(n4*$2;soE^82F4SJzZYS$(oVzaSj;IB5i~N=avg?yV|-%r7ix?7)AsvZd~) zTE##%#*V-9U4BTFh9-ju`EAQV!1yX*L7mfXQaJ~P-M0$)nAnlpZkF=MvQ6udcf*|~ ztmdnpO$h0yU-I6)HqneYGbOF66juQl`dr7LAX2sgMF|lN0|%#v=U7Nv8PeCQosg~) zb+~fB<_I$1d`D%AXds#mDjeQp&QKV8_evV4==5(YoM2(DJAAStitf!1?}<=A6~*IcScJ{-2o!6c9np;0X_$* zy8)A;q}GU2Lw})UhjY+cAO|Wv!WXI0F38kA5W52S6_mb}O(_dTKp=QC=~CsUU~pAw zDSI9PZR3rPfPoHwbZKRx2#Nq9;0uRbjny=ji$J{tB%#m3^?`2MMV`F~WhgeyyO0)8 zQ$=i_e<|M3@=(C~3yA8X+0H2NY@Q0*gMwVBex_m*KxT6yl2)CVRrwZ88{XU0(t{z+ zx7%!PHtWjz(TJcNi?YFh{0`>e3a8W+U!aew(6}(ISuNYFpd68iYQ?KGbYVX=qKZcJ z4iJ|YQ>-CKs8%;`&tU~nVS@e^?8BfyfbzY{aiJL6E6V&xK#5EPlH)fUke&-H#0Iv8B-rjQK{6lUZasUGAfJ^`}BRbpxN zfE%VOlf=?%)xS>0kFOrqW+p#RETz=ubL3KOq8bK(aYKeHI4UKjwSsoHc~;21rFqbA z%SbSs8a)bmRaNH?1=YX}Mq{BDkc_W^8#v~c3Mw2^%7G_xS01*v!N;!M-7ZWQ!c6iF1x{^>_vJabrsUr?GYt7E+Ms#@>|J` zJ(K!xTg!r6rYvPv;!WYvXEYP#@G%@aOKI@GtRP4Wx*L%In_#DE4BT&#X?W*X5VaI{%yt*R5LVi(awi`mQ&f>A`< zD-VH{3}9D~zAj#pJP3Vi<7txH$HfgT{HFf~EV)V_cXQ?Q8?Io4ZK*_q+B-_8bmT!PPsLj1FzP--NkTd z?5Z}IS!r{nT*s_7$4vi=fncdl;EEFCHvN#G-`IrG$5xBkYMK6@|6Fg~cVZr@t_G~h z&%Z@~PJa9?`or>lAsc}v0R z%(Yd;ON(Sb+#(Y{uZLn?@6>-)e(%$IaV@3b z6R(=mY2NGl^v6%@58i%^&3Ea|%BPPgTL_+p^2N94_39y>dzU`AU;d=5|LC!WQRUXV z^^m(!)*q7J`z!jRON(a+`TDost)1fZ4ZouQ+V)55kXB^VWO=}hKLF@d$u9EckLu<94+~CH(dIDcT}5jlCuFTzm$_id z<}F#9)n3Hy7PHNgcbK!qVo`8fZGye%EZT6P;L4k`c)>aSy?>+sO>+9e%lgK(>Akk~ zKR7l0W_X>vH2sIsdh4O-Z~goA@0^={_|Mnh_0Tkab>s4_>CeAyqXXrF|HH-~Z^$42 zn~ja>@BGC^_-^_7k2g+C|LV}0-z>=Q|G@g;=@(vq<{B@L{>8@eY4~$za>u93e{trC z@*3u$DPl7Q6}Y-YJm%eu*ft}=@e3fmqEPOf(1BUUUA( zPx-+}2HR`Wd(C+^W!d!N`i%*m<&#dnY|48JImeg}1P2*IqBt_ASr=X|`>0|fBZit4 z%8~L_>6V?d#KICr)ZLN6u;EH3qRgo1?ntK5z+NbOQn9M1*%o?CqF^tTla&VR>Po)4 zpXzg+N{Xz;8V#mv?zx(EeCVu!mxg_Ux3FM4Bo)FPDK+j?jRgY{@|#TJu-&Op8Aqb+ zr^;nxCy*BDqS?^%$E~ie=#V;+ci^-2dRAjha@cJ~mo@DY8l4W-Dt0rmcCk}W4=TY_ zqs)aXp)og#^cb(j%`?@u5bTPz1S2`P6vta89)H0XX8bl`Wc3H#!xCQ16vc|KJ&47^ zKFmdpY)LWQmdHY`QMTcYcuVBt-eSnucauG5uG_F?Bh{QGP|(pR8Iu*e)!VH%L*tUfV-b6?9_mzFMWK)jWXW=U+#>UlBJa0l zEdCZ-_IAZYzCt##yfe_x8XY3ilsphJ)Qzp^>_FaTWL6dR@TnT@n+Al<*dJ5qUlkxf>=PXI#VrDpS37M41 znM>4Dwjf@w7V1RY=1fHG3viXTKdU?}!=Cs^<0RHzW^Ty!`MTF@{G*K*JE$6VAqf&*g?ViqJk`p#y2EC@MYPAYn5!6Qk2r_B&ZM%n_Hr6LjSq1y3dzXjp8RJ;SxgfWs9{hMc*g6c;jq24~9qyN-s@TWO62COznz zJ0s2_)~#t1j~B&JdR*WGc+xF+T0(MAAN8{4YKZgZF+*rD>W>Q^8`lep6Dn`$m7Pgz ziikK%p`tIzj(nqZnr}vn#sOhx9PMnZ7zy>r$bjv5{eBxA^b78Ri!$VkMt>Odb~9Ov zBkwT=vmS%gFR|W?z1PlhuGF}YZYPHogQHLqv;J7MIq;4R#K>-H^h(2m*+mT#Qfp!n za(;6@>khZ$B#pV9Y!eq;(Tcgxrd<&#)F#G-TDs>NG)s|s#E`8yht9Oy5N?F6nH1k} zNEv63b);IcPD=E9geplUOs+2HV5l(Wl+3+^%U7Wr!&J@TY2*YvUvfxon<0q@E$(!u zXo*ZBxnZ_eu*KX-V=NM`n{%CZI2Exn<8iU*ZI?wUJr-F{r;iz#axm{JQ=L)0&xswc z!D5MIs!V0frir4MrD=vU^<&ZKVAyHLoGpV;GjRet5~EyCY(`?Z!CYph0irZP1;|vgp&iW zC1-M$TSDJdlD~U+KTM^0oW_M2%WRAB`j{KkMo{HR~V5ou0qx_KpVN*pvOn` z0(?*zk)uglTxcZ5c_z>oD)OhFUEi2sd2ek9)6J^{kmucXjm+Y%5$pE#bMT2w%4Y&n zM{+S{;4KRQK9(K;p$Cc!)V0dsNz_)Y4KcpT5BZod;>XZfrN|Z>)gp%wXP6;9CIafm zN<2BKljWS~?xtf5&~bHfx4R)cPOYx=n$Xd#H z;-z@S#&cDs!BcT{w+4d(wzyqkJTc09>S8weNT8gDH^QleDeG~KvZ;t|k@)~RzOZ9t zG>5xP=w&QVk#sm}8p==n!}|3}-)gti3moMu`#Suv;SIY>{DCLh+u7_i=3-B%?PF-k7~+H%tDE zzZcI%9VTevzYG!Q0e2mmKx5R?W=P(SsfDn5ES5JhpUAz>mF=K~78$!{_DDE8P z@@X7OZ3Rl7{{3E}VX;}DiJSYsj1Gw}N zQxzl0(!kv$=DqLGS$-n7u9sieSwD3EBhqQa-mXm;P>#gYW}hd-80;Z$*%XPpn%xLh z%QQ(_htJpoz>{@Di6NP@#XCN~+lGmB(;Dda9GRAl1sW4}j4kn=uV*S-;zrij4+@f@ zoDkfBjGxVrZN|&PP4^d4Lwmbdb#QTi-bZ_jDQ;vokBSqlRxm^=j-ud5W-DW>O$<6l z#bAjm`CO)?$WsY3(XQE8Pd1+kn;Sl|SfK?^Cm|-N4jsw3_{^x;Xz=wW?xpP%)^@jJ zeJK~t_&oU7CE_05m@9UD^`80$}jv8oW@iC*ZSsJ4>zVLk}S-H5MS0? z9074nhFMJr0q$-{jR~KM9N>!7Nsbr9Gvetmh*JEBuLiQvHV)9t2m`D- z42)TvAJ?<|9%N+)Rhhg3S;1ZnUD=zg?4&B#Hd!GRYLQK5T4`MVKb~Dbb^TS57bHpn zeUTsi6D=?6h^4c+s3q7X zO(9}v#+vD2FyHpJ@KL)SG$gu8gD?++04l{1@f{i9SwsU+x?d8k@QyL3qJZ~tB&7uRyf5q)|Hj^QTAv^L0GRASKWv_(>ZGlgUoS2QW(Wb4J zsag7NDICHI(NZ~0;BI%rl1k9kVXdBXO}eoFUviC8jL*dxg`73q!RC9LBo#7;R}_Bk^au^J>oZks1$EJ9>T(8D`(%~T1u z1)`&NMDnT}0H+Stdh=b(k+>&Vb3+j?!$uB-Tt`8#8dQ zgJ`wVZWjh=K!udw)w4Fp3P@k1$88^nQsKR66^0kB<*>&dZ*)evP-f^7DI#M_4+iND zJEv6|sk#(@rOq@EHYlHP@A@*LSf}@^^lE)V_-w%14jkQ{v5W*COgSd zup@b*c-d~Ef~mY;keoy{T}X6N$!64#lYZcR>aG-H9t^W7TicMVR?>|;QS3;TVxxuC zTE(2iWGJUAP-(YP20kgovx!QWYBxDYRj3ZlWTZO@B@B%oNKS?rAFi_9Xn4#SO*LK| zT202JtygchY=k4z$M8XeGbUVhH(e|TL#c5(l1bY*fQhigc*d?UmokipmS)!7BufUi zS+qx__OLJ7iAbx}clpvob0kHv#&R%8TCk{nm?@KO)|sDJxR|AyvKg2$R~+}k#b!z3 z9Gq)hi4TI_a5-#nIHJRG+h8%&8tH7t>&nqF-baoD4zlWuwA{l17GhJx*bof2*?`5+ z?Tf?ou$dW>jaGu~I{9d(YB3m1$$q69FDCIkBp@eGPm?jG&4@nUbDH}Jp9RYjR(&yTYJz|qQ-AE1ZMrdOz$VH8S zFCyu%*~fDg)=si(u!2Y#jMYO$XPJ7HpYV22_zboEZ-qg<;w4 zkm7tj%o7zc=56^su7hU1PcLu=ER#?~2Tg5> z^E5j^y(5k1uh5UUxCfpi_6)I$-xkp za}LVSq<9DlLuz2)ae|9HP6RZ)NNOyVn2P*7xxOKrK7Qu-gbq~=M5LQBH1myI&N6Vt z9hN}VpZ0en&TKUcFbWzaYuM~#rX zfse3rpq?>%8s0Q7X6^lgp*JFmki`9?S8)tWV_Yx`$z;Pu*CMV&P|9>8M6})Tivrd% zjeKrvu-69v85ZHRJ&ncpOeN7 zcbOE~a)PlL2N{zAD~>3>#7k}5m#=_6a9m5_1MnsR)LL?kLu_4w{oxG5z!0#8JJo4) z>n5|Sm|>&Uj62hf+C_I2boD$*5S}WQ9)nU|Z!l^HpmtEi7N}ZCo59?* z_Aq0wmVsMO7l$#N@bXeJ$CSyQ*U=#>3ECerikY0nKPu$R(HQT|TgYIKN=G<)!q{k= zMM?!*8ETAs3AZz3HoLL1K)G$BWT>7Wq@3eX(IeUiqaL64_v(Dw*sP_KToP~Caj$1= zCO}H_cg=}fP--)A!O7KaCaK9*S}AkPYf4EN&{vmj#3t=L*$i~69%mfxFwNPld2eLP zn+2aje@`I&hAvCkY9fQzvrdvt`ZBFpe&DUTJ+WrjP^8B=m*%1rR?Rlqm8k#<1%BHHH4o9OLs&_5F{9pCw?%Iq*<>&rLe?O9x zE}pT(z*^%>&IP5yXp}PzvjpF&DT31eK~a8=USF=zRf5+HG;mQ8k$S=79`g}mK+p9~ zc{XPOEs@6sh8U2YXEG7tip5O>&_%gM0_aN8sYok_TS4g)BlDewCW{c z7$*k$xu_h%*6%wAx~^DQKC$oYjY+5$vSj&AQRs*Leb9SalcH^8&Gj0^velUEw}NAP zw2nuH?z}fUEL*ac+{l=Lm%>I0bGNKqMhYbBK5MFEO$8G@noFmxb{KMuflVCUcpvVHBi&SPAG*qi#1AopDz5vuTd; z0rOMu2dO+4Ytp7r+U>QnWv9J74t7%sAs)2~ev30JRH_YvOHCqqK9{oj3|$foB3OJJ zHyi0ZL| zHWs*+*lOgu9!sd>X~zRYijA?pNRp~qB`n9-hep95P`P%6HvrnxQ2*_iKb9wnnzz|c z*oz5YjA{83j%tPQg>f+%BSHvpFmD9tM$yTT@-vq=^yYvG6#IpWE7fwv>wL7L&IGL*z>j^RIEHHUe@It{_ ztHToq_3$W|&9yxa(uR|`ATY6NrE6gfnRpSaRLgW|GVr)t@d7AAv!i}6Ude{?jz*v) zg-Xrxh%${koY7s%)P{N9Z5D*2K`Ii}NHLnv0ufHz@M@okfq77>V?A@wM>~Q zY7t}G7O`f0)tIYN&6i!}K_(S*(4AV$ZWlu7Y;9DR#)Y22JgLUWilZH;Elqc%$Fk*N zK2mLCg-+Nc^oXj@k{7xyx?Qd$h_=Bwrk%ZFsbjCOp+4S?nzA;@@0L>Gkil856YWTp zh!^vK`N_Vk+R56721{>P#rR>;!VW5-VaX5(Cp!76l(bb133td+%}sh;HW%i+1|e=T zT3Jt}SGSuSWU5qinOLvIQBGuP9Gkbt8l{fI)(-fvJ}C5!y}U(gljgc3-Yum|sZ5l% z;4Ok^IP1|d&G`eVu^CWY+V3iwed5?hR-;LGuQfd%o9T3=E5;jiZ-h5YzLL#Tq`LVQNjYP&3eLE4 z{ZO-5i}q6yB46lLL~F?U9p;%YLTQZ<#W{JuZ-5u zA6lTY^0!~V0mU+>>*kwO6_MC-bWUQyiKRGlx|>ORX+V|IEZ|FaTr~j?%q|jJ1-KNh z?0*2UMYL9<-aLN?V(Si@_yrRUQX0le!vIZ;cM@Bz?UjiwqP5z`{^`UP(OOI+wuclM zXe@6&boTrNBbh|6ouHXkg~uCpXA@wNt5PvQq|j;0tw~xip!eS~Ww7FpV)=GFz4G!HbSoKFL)F zHArY?N#aG-h#S$H~*Jc6uzEIbCu8hHtUwjJ8&dE1_=m@NWU z^XgXdsKUSQv5eU&Fy!X6xQyMaI67a2{GQ&K8|bWVHseW8xX)NE zT&I(FyS&k2zt)q&eRIDPv>QXEfQ2-*(oE9QGPL|PXV9CirJMFiDVT7y^G;WuaEqZ# zWnjQayT3|C(~)eZ*e>UUP`%XUMhsn!bIo2w>RV`AvtqLtvVmbJ;H;TqpqY*g_(8?l zc6(d^e+|A>4ul0F=gO2ZiuAU7ohok61xmI!ZgcpY@r+bYB?J9H8E;r8m1a6hmS(c~^jnx=T(=s@)oeJuPRM^8!DON3D3UB4RFYWt;%FEK`+Z3VwUFihJ|pQaRQs zj94R?s);3w2(V}w*GAy_5l)1XexY0~c?eHBYIE1|WIaR>txAQVx=kzscI3iDu#TgR zY&&UXk{(CWj|T{%V767dpwTXie6Upl-!Skqtyn8DsTvk=e)X7wY%oRN70Dscy6vr)w2AmE)vpcbs=8yre}WgW1x6F~#a6+h%(8 zGAIa323y=2%^7)1%^R>fF+;nbBx}uL#-0TT9_Kj#T8}T0%1Ak5itQ#{DFGxoh9I&E zvQ=%aCqJ@r5IkGvN{5&&&Go_0EN*gjs%ElD)LWKNE+UG}Ms=t0*N~(f=3poh2xYCV zaF+08^JCnUX<==jRl&PEJ&(wwWOZ;<%j~Om4B$@Sab(JZJDw?7HjKu71 zSI{5o8zTO+t6FhYOzlJ%LRUfhF~dbFP;@}Na48f)D+?{Kv}4O=5+cNF^BAZzorqV_CTFqT}Q zc0m+eX|d4r6%r$RkgGZT)~E~2KOx`5*pe7}j0N4%u`!o#jshJ|)yz1helKDn#|_bD zDR&3vQPtqD4gGbip&-SKAI=3t%G_}jqrtkf z+#VQR_FTyp?wMl7B6#scu+AXv$Owf}j`If6Wl#>)$bQu)SWSJ8%aZRf;ek9=qaQF=p%x9Tg&4%|)ez!|hJnJyO2ipbYYJFY7O0n&xLlomIBG#8@P_ zGMTQA1%XVDFiY8xG4o?L=>%UsoJo>q##KxVym13>4zlCoIAhFkC9}U?Qf_fwMaK(LX(XKn_{=Dfu;zpSZOU zFMzVMd~!>_wt*Rqn_5uOCJIDp_PU#D@PK?Oc=p`N6{-mVyHK$kQeHqnR<jC-eA?#8`invrGMmMvShSTot<5I$G`jj+S|Kt zmq_yKmMK%dqW>i-qyDl_nR4^`iUkDr7w)`~7Kk&b`*d6-fz($=Z>EdHVN}0?t0ZuW zE;5|nXS2|hTu$#0Q`E~s4oTqtJdfKiDpwCOBbcn=@j^dE_NCK%V)EtsP*}A-I=q(`}@@I*OS}fs^ z1cqF3=23d7DwLij)lqAUI0S*uy(M{*UM$U`tZ7^&fyOHq_#)e(^b1lw#qjeX(DTrf zztQK-+!#ukfqJ8m>qX%CpZ-wMd-!>k%ls(4l0y<0RdWBW?4&o#Oq5H;AqW)b|FxRs z>`j@D`h!Oh_qP)JV^pi4PF^Mjto&4sC_*91ZJEa?WE88a}#$cjF+vlf7_<>>=f=+ z=%^hgju8Uq)cm!bW#mhRo_f>DAqdR*<)?g>+-`+}j#nC}UHn24`1{)x3c5;}L3#KE zBv6y~fg8sNqxUN*>LWQviogr1r-sIt{dc8_qLMfyfq%Rk6Eh~JkeYVSP_Cz|%ii4* z-_zbR(8jeR@bDX77?650mB4dP;E(zGrg4Eht1?h`Yq%Z+K6O&!VCO7T>!`iq9D+dj zZA0yNuVS@<3g=ayz-y=MTuHmtF=}FGzoNRw-Xqu1d(`37kuZ(~fdxl)?m?Xlpubax zu`RWzdXK0VCa`qBQOoGr8Y30TFD!uvYc%CJ&qV636pjpm*XGUaMSYwlCWF!EH2GX% znzooL3~6&IM#Qxz@RgN&AEA$G%QMd>MO58VffRBD80FQ!0jXp`Z(_?2z+PRh7GKzAOnA; z*HL$2FCqs5SDuLaew^$ogN&YQkaN737>cOU0Ins0dmdRT8R!4Ff#?5A!#u8erg0w2 z(m5$gyYI)r@ezZK3Uj%qg=OmtUc>~pzkTviR#^#KyG&9e;d@smHz0w*JwG?op{5+m zb^%vO;Ht3R^2ZU9|IMTyq{6Xl2s`kP=qKJ!QCo zfMfa7XDv!Z%IRP~1KaZ`ve)Jfb+f`EJ?(xRhbNI_?l=szOpYt1@pZYqZ$(7C}c zYJ8|;W?ycdJ~z*zGWp39_|?eSZoZY8ZnWsA65QR0WC+aK8tI_RQ^~*@dbh=&BXQ7D zz_NB1O8mnssk_I!r}>+>7Uljnw#BX3B3+SE$MSc`Uq_wci4*v*XnHpyvbZim0UXiU zXx|Htz4!rb4dUiY2TbK!JQXmT3gaz;z+3!x^`PQM&~brAjvv(LhKQNx$Y`MpTs?W7 zp>DUw-s0>ds|{-$gvP32kw3ha)4Pu~a`v~D&>j=-s3UiyY!7~)Sa z4yL#PdxKNC!ac!B)EB&N5!ksV@e{f`(L#$t_+<+UN#>f?gv3+xZ{esC_{AsF0&xM- zsdstN5;$vkj+M?fTIlm3FB;WX*NA~5!$#m~`)axL_d2qhgKA)~(I zXGLIBv{^;xM%7PnXjA>747%N3S&8Y&giex-q14x}GDkY5>a7EMVi{m2S7;oTO+!4=*IN!$SQVVfv zgbf1E#fg5vWu8HK_+=xoD|q!x*3XmGxj!Lagv{kAbvzdOw=@buMLeK>#tAJQ6UjrCj!6P7 z%sY^jZwI2>XTR(Mx|=tqey{{Rj`?SY)yZcQp3%=Ahn3)DFS&q z`0Tl>=>y@Yk2u=FRBj`<9jBV`^U67#o*_b;HkIu`5cSHfP4wo>2yCsO-Dv?F&Gl(~ znE8HMKHIbd&GU{Qzkg+XD%I(FYKT995IAM!Pmi$fos3+WC82kw^UAzGJ&z^v9IE?_ z+G#KG6Xsg2$WYL;GSu9tr5UAM;g+$&*BND8&FsuVuCOk%k}JHI$&uZMobA#)p=KA0 z8=QBo?ksNCxED9(m|a({7$5k9EMH2%hmiz|n##Uroh0f0)C}e1-Eu3xg%P;=%DaO2 z6=B=a%Vy{}W;V~TQPX*85P0zFMO)Emd7h`wTDao}J0>k(ybYRXv5nUw6-mFZr(eprV21yuLAacU3G$gTOtsWye@6`qf!F zR`#!kPnmM2{OhA^NLe{sM;mAJ`kF9%7UkqwAh05|!oUiO@OS%ceyjiY?Aerwml%OT zZ;XCNlVAf|1=Tye6Rdp7OMyV=TYKa9>G;q?bNpFWenGeO!u*BT^4+z;)y^J|*EJTM zJj(k80tNTJS;$7LWL>0lc^42fm-nN~=kf;s)Z8?d^kYcc-G65p>w0$1mC-@jToi^e z$&|Y;y`&jOEanlF=xEk%5D4FFqdUd1o%qGn1RnP4B{3AvSL|SL4o`LH*gx5g@Sa*NzhymITwU=kbB! z=XqHy6CyP0gBi*TtY5d)%^pv`x4+NcLr6Y}lOZxA&{VwQ7B))q7i;}X$76Ok9%D!o0&lpu z@E7`UK?*0cUkavMMz(TT0v~zh@ug#267IxLt8QeV(qK{)9fKH=*6t(&FrP zb@vSP$2*6eQ~14%4l0^Kg*R{{2@LrB{3spViRryUIenr?9xy5A@_iWBj=-bUCqJWg z4dK{^-xR(pD&QuXRm_LcD~fAb9XNrT(oGxF_R)K4!f%+zM|Yv~xWmaG$oE54vd3_u zh*Z({&(l-q_)U<&wTiRP)5qrJQBU&bLty8wc>7p~$`W2*J4y;EVIapMfy%{KAHzm@ z99N1`ZmT*XoHFIL;dd9&`zpif8@3OFbIGIp5?jctki`If|_xnf`4lZL@PC zd9_SQ$CmN&UPW02+o~1ku*a5j@1$1KxKV#Et6^K*i7gB-zg0w^?C0pLDCcSHDKBGN zY{M3(znPv+rbP!;gtC>%IM?b|8r#PScUAC&cT`kyBb={Tz!l0X>$$?+mHh7fTP2s^ z7{aapNYVLtcD)j7Wb|ki=lFg@FZz_aVhwF=4WL)o`Owc*@jmWM6_@0>8`ba@&+jSY zE$XWI7CqHm5c(2n(P~Pg4^?yfsRNDU!o|(Y>5Uy6(Tp1Yj9pp7EkWm0Jf~T{wWB_8 zqb$NbW6QIRr&#F_KKyFA!$FC0%9L*cUnQC|jc%>gQwn~42`u&dEtURuDL2T&wY*-P zs+~#QjmAKXkU-}$Od^I3l2%5#td5T*7T0mCXwgSjRqqdG2iR06q2I6Lw#1{j9QM(W zKzjY6aGJ=BAYzDIlpTav&B_L8u&uApK2pqD8~P0+eaJv)I9hTl%HQ&`!cqI>2mDKk!(a82N^f0n26NGbiud_E38 zIzOG&y%^m5n3(*f;{zo$@?ma8V-crmI~w^A=F>(#?3%HF3%ib!vA3^ZK--GL={XB! z{uKlL#Py&sw)3eR0z-OQ7qO~ECW6iAiwn3Mk{|Y;^0hRQRoOWU{itV9hY8;Vitm_J zjOrFnuUp7(`u8p5$G^0YH}}Ft{N8-!BEIJ3MO>IgSc~jFa+21ShSLu&lG25XDeCbM zjy!?)zD0dKZl~8R=I!*s#r#}H{cd?=M=ucFrRtPyxy;T7Gqb$}blZCB98>;~!@z5#)E zm%cLtMUh5XQaBC>bbWqZDxKck$mtHa4EPTd=Xmr^Ylxr=@TfK z^DY^EwpBrIZ{_0J^=P(>2RoBcZ^w|_@oNXFW0~x)05tM3gq%)q<5o2pooiLX3%Qpe zui%j;L`JK>nTsYo(eqfFo}C5BE&B$|n2XjMMr+%7(Im9v@-sp6}xF2=}9U%>QJ|t*q`4#9kMlRD0Fc$O#M={A)+YYh9r0bznxZUM86q8BR;UK83SWicN=l)&!uyX2&{|udmnXSuF35g za`xrgz3i@(Y~xzcLtgG8Y7bUu-%-4ZE}o?aL6H^>^$;JA6S(}kdtPHV`0W1aoS=I8 z>$t*8{k$TZ2lz$w4DhHI2YA)C49=x);+ZFKdBveGP#*&5?0z}DevmsPjSG};K@dj< z{irs+7l9i-drZp9jJwYJ4GnfL{l*%WZ_=Z3$d6i#=0=1>V4K;O+cY_(l-@nWN2vRU z=1?EbeAZ$}tA~eqTCWVxHIWfZh)w-_ z<@aOffIzxx)a=8rT^K(Rx^RRO`ZUx*%hsL?sGLUn&>S=56L_h2*RC-(FtYq_$C1DBMtEFz zVXkwmXXJnHNe(hj|6zMq4|iu6g{%=75Lg^2!KVks#>BrJe#jv%*X^ogk3vLMb5UTV z6M-jIZ0NyG2Kx7_{OQ1DDo*&Z%lMPbz_M1Z=FBoTSEyLNgi`Yd5dvTPVyS^XyQYZV zwOmR2tl(nDr;wdX)~Z|R70Zg~{uTU!ZCtUCn#mt*2n&DE^ElArl6V}-V>1~}B&t2`{1L%3k& zao;aQIn1KJxk5?rxtiZ@p1In?HBGyQAAZ+0gItYeZ3jQVS{GONaV@|7FI>l)^uz0T zzwC2uGdq$11?#ykb_KoZ%31XF*ZI&dUdv|@Ke@JvZE*)G)9ZJY;w|i2(jtP?r5m#uqekoTta6NyOZrxBty})n&1pa!p=L7T% zXThg5NZ_tbl^x}~lA8LCZ|!?82Osg}CJyX#X22x{BuFlBKw+)^+of=#$$F^k$lmf*+;% zDEJbc%MDR*V-8oi{>C|6;nQVH$t%3CZt^B3L ziLGhWcI1axCxN#HF1roq8%Xclrhwn4S=90tBtWoq`L=ZGS^k5-*Pi*KkA8dWRQkzn zYF6UK=w1hUKADB=Cs6nEW<%fuy&v2|QxHq7;jgg?yu$WT3+o4#KqwV-vxpspK>v3S z-bHT$b1Vr7$jAhqSas{{u_@p%Q+S6K&$Ir>Yw)&88Z%R=R9fl7&zl}ObNg3;aDKZV z1*=kYx!pTrU#MW&xKX}(D7=^DQHF{X$)ySA0li&`?KQ(6P070w(9)I0e2h>Hm4n7PN zxc;GGESv}uBu`KTq^N+B*K|rIF<4M2`iCxMlUgqg6{uCoY3b1stuD7SMhQ(pf`ZHW zj)k|v1k<@bt6vctm}%jHjRLqeTNnawM+lZNwNnMRNSO<6a_))uM!`S1?rYFiL(Uf#IQM7B!=ltR2=hDj$pG|7SZi=Vp@;cULklu z35$+%915=@MisnJU)iz`5*5d|^t ze<_d&z%)~$hmBW?WDwIJ@I&f@aZxd>UQ(|Kec_Tzp*Bvp+DXI#v^@CuskSYFI zFjd5Oe--2@!66bFAW$Nls;VriY^u+%t|_i4XG$f)UnR^ul~5`I{5Jwdw8GO&gOAW( zK)wT+8z`YFkwF!^RSC08gzqu_rNU1I5I4eEG$-wG0)lx_Pc}z zrr>JfO(OViKo|tR>xC2?T_;q+1J??F5wn6^eGM+y2iFN(1QXwY-!kUP>xFj)39R70 zM`(e-yM-z!zgKu#ZjI=+cR8n9A>lsZ$$+u12#j9poqb-Hr&}3A2rHEkbiXhij@*l^ z-Y+w&m}3tJ^+M*{Ug1m;llF-4PC4`50pa^oT( z9ST(;s3Ly`i@L??809i$gxAsM>go5Q6h%|vk#Nx<%#09C3v+qm<_z_@`km2HR%?_s zo|_Rjg+6EhKwtN^Yt+->?9akBX!=k%0OvmtN}1(RqWgt_<9-60n*|X}a;)eLF(XeD zc{n*T=T?Y(1kB^fqU8!EWtJ#J0&gkBeoSbts7C?c2MSHX=~m{RQqc?%efwhuXbIqI zd@4nT2qwH=v|P*-jfe)7u<9C-6+9n`Wb+F=eO>l`YgmWZ(;a4Yd99vq_lVUy(9`4T z>vy(TTRnZ&9=oH{-sZHrUEY2?|9GccTkUQ)maNT)vG#jNE0#(>x}UHpGEe5oD@8*> zNE{GJq567}5$0bb3WF{CME*>|TG3S^Sayvl;{RV3;Nj~;eemcpVHos$E5toxy(k?@ zuNV2Vya-k>z1NHK72q|<_3-spQ3~9Cv#3z(#dnvy(xG30tR12%AF}ol1W{`5cY6E5 zf1BuKD7!^ek1EM&2e#aEGrHC8T_P#-#Ws;k059Gs(!jmDL<58cb_74rE)mL^E4Pb6 zgz(ADqB^*4hv->m&n=>90zovqyi=6S{IOG%CxE_PqFDIkn7|LRZx+d!IlD#2W$^D% zp^6E*Th#B%x$DhG&^_IEP^5+*swDwX^&kqg`(BX=9(W1s9tsiqLyujggtAMxzddLd z8lgE%Vul%qupN3eUzmMJWRand>i2X;L+DQAD zsoq%$2&_}R=qn@mK3H;i+@3y!ea_wibk^mpAK+`@{%287D;EpIaP^C#5?Jvxe$IYb zsfD|r7EOa+pB2r4kDeBVz^s=uLpAk?fY9HR4MDU6W6%UFc$3>$tbAH=8hV~YB z*Wwh=`y4zXvS_RkZs(xWZJljR!rlFoBcdEQd8KGB_&+D|k@9XTv_W8i1@8+&p!X>9 zu=IV0{;BMDo@9T!u zFN!K*|I4CiG1&*<#ET+-BN5_EWki3w%NsYR#pUgB+ehH*XGOC?{}RgWL%GoS_^YCD z75wW5l>w+OoX7mPMR_o<3sqyu*CILW6pB;9dRjCOI!}w*;Qef2858l2=ywBS{Z`bi zX6WBU!)it?6Tf3&KC_AiV#YXC{FYjf4qqpUb2LeDiD}lPv>C~nGg6b7naN^C!~8N= z9HxbUa&Z8YSuQ?efwS+*#SqypE|5jBQA-q*cZf5Xz3t)%!G9tdL^jJ|_kM{4PRtN1 zVRx%k50#X_y6suYzyx~5r={?5wXczh7!~hZXpH8k@ABrky!K|dvju~o5Ar2u=C3!z z+tOfF9}+rzzgWr~S4rL!!9gF%tk?)VVvy|y7vJF-=un*c@Zqhx*I@db!wJ;I3 zv9%uJ?CCpj))-Zw}-^U*}38h4|8*vi@=!-;j0P(cj6^hFaKUMP{l>K=uJ zp_(Kbfhjt|g|^`BN9XQrA*_+N%CKd&Bn+yTO13~Ki_I^iu(u7RixH0zG-QE~DuuKv|@sb{|WiBj}OqFZw&EDt; zzA}ahzDn}6684RV6im=2$)kEu-X@8H6MG~xndI9f79ZICkfcHy;lfc8LGy^@;^qB8 z^Qa{EZ&mXjm8AWxD)d1~By-?V2}t1F8`9};;&X8*gDUrl@^A730YmvQ&mNK3bg*|Z zD&qS;BRh%h7)95L3G*Umvd|Q&rbiXYT>tM|n5`PSPZuvqo6}EgPF*0YqkaYRL z*?Z+tu=*nIP)lD|&W97NQXgpYS4io(Hz~mSnlu8I`bs6R`!`7`JlQ1E!pkd_K8*Eu zNsnS$D6ilSyQAG{UA`Q*C@f&~JJ3Y})rpT#*e{lbiLpf}oDoaop-d)CW7bHdcL`xA zQH7!t$$VgSqD%qPB~o7|S}vUktkXDkxjZ9UOG)cf9g=7J&wo3=$cR#5D z!keWQWyC+wYQAD#Wdrvjf#5xIz~nmR{u_LB6Y4l^?8#e1?CLh7uo{ibSwYM%jXFQH09_xf2BKakMjlEos+EIRe|0L(8E` zc`zhRmHLX%O|T@{uZeEZdr}q*hb!elTldI~uL5;lkmgG8HtwCR+<1za}e$hhE3L&6c-hN0?tu$*vcWZwqt%8?wLHq922(B`W6e zk7R!afb%z*4uS=8c>wFRx}8In{BeUYuZ)hyG{+ERBZFHd^2eb34_V4%U(2u7GHZS0 zZwkPxlY5!3baHKsKkjf%?3tF^b(&q>d9FSTicpL_?@FR%d<8Rmru^4fSl1-hFimap zY%y5RiRJM1GP%DGVF9V2k++aN9|Sw)RrIR%fk%MEbhJ?y8wN$$fqcFFfp5^MBS-14OR;q)_#L(J7LC_bDW;J_De95Y%$4_LFnCzVCKzIh zKdFv{vx7=0{4u1Y;7}wUuQAbzr8gx~n0ry8WCE5e|3#s*KXkn^i}~ex<#j53bf^>G z6poPnp3Q=IW0)=5l`G_M;0HWbV~pkpyN{`)Pz;#tbst<*u)Gs?wW>G(6s zIZWWQ%Ev`iG;2sPm=0o7w=?0=PkPf`)C(x#aI;Fs?0ZkSS1H45zX3NUmF(ZC%&_-a zr7RR9mPwl&o|V}K#C5O*^c|tw^ahyo2}XzR&y|0MC^&90VFM#_RV#cfS4{(hLN!k_ zj)?d4wSi8lN@n&bRL}V^TP&&{r-A2gg@W0drz#S_XqF)q_HGiWAf-@MW-ctP$Z0CG zRhL+oTiJ3&d1+%_aW(8K6HbTK?J7MStW#;Y6WY>nnV!f+&YUk){aFtW-lD-*`|DI` zT*%vV0E26cdo|$QrHX>*cB!^7^}AJ8Wegsd2JP->Ok6v=2cs{0zB*$@etG>^Ml^QGq)X4-7R3Yzo43~5EK1`fLK+=wv(#$c!8n{VfLO>U5qEuX%OtagwlL@8OAu@ z{i)JDc1eB3Yz?c?5$)*i@!ZGUH%EP5Kyq7NJUwGd%ZZUSM%7MsQ!U~e;chE9kCEol zwVEVLL?7mZN?l!eo@v2QufJ~qJF-^0bFMm-`7>Ls5sJxf#29ncaROL;uffc0zFLF( z)>mD4Xsyjt?@xq8Ne;4C zsu(yls+RboTj3%-EUZj(nM<6!YO7Ukgu^>DeUNCy$T{;C z4PMfW)ob5Yt9{9~HD)gl3taZ;T>i$PtwK_tXv zaD`c8Von$}$E0xcvkDbc8KgO?W@@Hs-U*dP<4b0D3^Tn{bGHcIsL-rqmQ-qP6)=Ws z&23U&G$_0=z~8(^M~sEzB$hupU-OO`?(fySBSL$F_xdy$@Y;wvgbDU)8uW1XCTS!b zzC(kjXs=jBTelk^`v4}=tVv=O>?=`+!lwNy3-j?h%_SAQa*M_i&n5t@L~kpqiwld( zZKbFuQMnaml@&Gl)#H^-#pT5{Q8VG(GxE?_)P0*9<7JXxMkBxuyfu*gJ7)xA#Ne5) z%sGBa_AEjU8{9t4+Yp5QX*NO1*XA4G&{uxAO-5+&9`Hk*598da395mPe!TLkxS%;F z`Y+-D6o-Xz{-kLV`y|C+(hpg0@9*!Kk&pmy|EihEn19pE6vEzLH709Hj5Tx;{xUC< z(323wZ2m)&Dum@h+Nt9HVN8^01=_Cz;FW5LFS9mSn;WQTAL5_OmzZm4%5oO z)}#r8UF{fQ?*3jSW)?+iXR9z;mYSi&r3q&ulC>cc=J^aQs^ptZ+Cs*37%7Szgs&)#C+DPt&zdK`6m6g z0|In3S7}YK{&S6<85z~~OL0$4T!WGjtkL>0ervQxM6j<9gE)5oW!>JVS7}pZf+PsM zURwr-Lh*!!c^3*sqNrdvQH~js85^`3_~1jc0{S;-Ya#9F%FmW-P z{f+*@Tu5P1z+o^pB!4~vHvc5@gTr5#eOHaOMccsF$z+H9`*8e7>?X)sG(YBqXeTU< z%P4XTB(V&PQH>&Zm*~@)YI1GmO&BE1j*7>2m=VFe$K(S9&&7YVXYY{EaCw{Nnc!A{ zFz_GT^B1LHJAl_rE#H}q@a%WykN{R}V-Xy;jGR)$#K5}q<}5g*FzWLECQvs% zv6j_&OyzRzVCh`~<5bN2=64Ue`aIoT=nzn6#tEb68l#BEbYHv%t0O|70DXE&}r^vY%a z)8mOS^D9bml9QX`1qC^5H?dvD`xlG{7UVBC7*$uQ1A&Tf+z z33V4Y+dg~O_-@6GDGA8zjW(#X$CHStuOuG~(@1lR|7{ zSA`cS+W>_Ly4TExFnhO`J+ia4#MoWkO`L8-#l^8mNP5j23a{?cS<50kt*vNW6XwbF zLes?SlVrTmK@(*=H{m55rW`nTjSJ27n{G`cYQ~X`fm4L;cM5#8pgv``K>8_jCPaOr zF<{ze>nZbWICaXr(T`nWOo4j(*`S9jVX}AVb#o-V{W|uW@rIcK$s1;~4z(2-Lhgti zks<`WVa8)=FD5OrH)_wv3F4WQr?hurD)eP-DC|3>H8Gpt(SAJwl*uOuDnHSx!S;&Q z0)N!_=-`f8AIr8SKEBZNZ!O-${afn`_r9W4!UwfJrSRZ99}QDi=OguJXpfJ-fRXh2 z9G1X&uaAK_Fy!;09z@H0ro$!LM+$FU=aV$)GiN=1{%~##`vCczXl%KD(x(D8T$g;1&B9ZhP~qQPst{q>Pe(-y!i?%RfciCy7Z4E6C><_fohx_Q~|!%>ctZY6aY#M`_G_^ucXZoYFdn@$arM$LCQmiDbODV0M*L zw+Y6+0KewJ!CR>e=A}yNi3}CzAV_eW4d>TUCfIl_{`0^(s!-4dKdqxGfVxRzg8Oeb z=(YGbACszmO-}Zb0G__XU;xpzCY=aR?D$u;vB9R17b zS{J^#<|4E>+yh|OPJIOP#>@D3dHxYI;|*#k`yVkMm~_f{V*@bXHR)>O#=Zc*h9F^| zK?yH!(CwaFT?li04JvqUqwd+utCw0066T#vx*4XidM4lw-Bjt=7vNV6({rD$C2+hd z;orV7u%SpF$`WM~U)0?;9S+Y@%bA9sbl+>C(ye=n`C6>+3xv7T%zD^-!YBsnZKH%) z7OMX+@-jLM(&>qWYkKr1_A;S+soqx^ff<_tC)o;M%`}Y#EHm-p;>x9Z`BLu9Tp}Ah zVVH}VN{nGWold;YLa)cY+>7u!?fAD!NC;3%Q0T3&Ddynu)dD)qC?fwTb{{5KvH?$Y zfX!;7v2daZ%Lq0hky}(07r#!l=E&m)`JbqIoB=%Tuk{Q4TXS^P6E&oj6GHJ80KnNadp&I)I~(T6CB56MQkxQ5~IH+p|aPcg+q;;)$ZoPCEf2dtm@sTu$8^pUyX zBh^co&Sb+@e|Q=H{ulU_8NSj-vB5h@QV^C%Ob-_xH3T!&<%XH6abX_++&7bXrO}XN zHDH>RRY5l3C)x4A7)V==Inh0P48Cx9)DR)Z7=*nF0cz9`$ShfIpnO1kjbSPrUT=7n z*>Sz$n2H(NZpal#S(S{2hpt1XbZNao&ir(f;Yl&Ho>b_d?P>#sTl|{EDwEu*w60M0 z_ljztEWt*ESjRy>YAP5r~m=_Ni-jXs8KV!Jr%#vV` z#IRtTS|{Uq-w-Vv8<4s6jNx}Vv*&Ze#ql~=bHtd*y#1BIHw>P*lM08;w^D)N^Mygm zq-c$E!#PX9%fY2HjCzPqH_Dk;(~NJ5p>IGE%)CFt7$plM`Cit?WOsG47mxT4`im~y zH>R`6;279-yCH=3dC;Wh19f(90^4k3JbasDREEsJ2Vn8Uxp7@t^g=wtuz9Vh#mwFu zqe866jvna7_m=od@6`h1G<9DWI~x1`9CXp*0J!~jLjWY#;PqqTJY4PCLSq=5o9X8V zNzGV#u+TW7&YslkA3I%HWQ<@tnK_*%dKQ|^56nJx|Hp1qi;W@NSdI!~2s2V_yiTc( z@N}XZ=Q8PV=zUQj1lJlZnotbmJ-AD=H?xqGr7_IHOa-2l^6;W|%$D$U&vlf4NeNd6nO@wN<>S|*}}agq#jbd7#;_e@xS+!(~{e#ZFD z_zW0qA39;A_{Ft?%8!j1gbg1i?**f5ygixJOgKBDkTEyDWPIW>_A(iyA1$6dB->QV z{C>*#lJ@fY#mf{*hWg0(ntXD7CM3!YGA8r5tzH5T8hLQk|jaNC1&9rIj`X_5!WCCG)pq`2c~7nvTBK<#>iMTEb1px5jR zfw{Q`DTVe&&idqOYc%`tcltf}HfBk)$(QphH*CSThnt&CQjlcgZ+h~@c#njJpqC}3 z#w8~vr86tMCVW}`+mItH#2c+;~wr?Q(b-jr)@R1msuJ^Lpp(rM9gK4=4?%ixU z#B^*i{U(82*D;4)t*&7wK9qnJ3w`In^9z0VK>H%!#<6(nal7v$0(i99H^Yz32jUwO z;=S4IBA-3H(Ck|XyBxm3u=9JllFcJRyTdn~)Wt9vExs92s0&qCncF&i7YpF#VX;B0 z#OG*ifW*cFaAsKS3(pAfB6hyp*9X2F7HgRfx9?p7QAD?u@#*&c86W&LAjzXHUk!6Z zukT(7^bYw35;P#%3il5AroqJ_-^EP#uufp7y)6wp+M%CCytnE%r zlUk$6%Qo`Nc7_#`pqRGk_TrDJaTBTeuMfJozxIQVZpWxKdIqdqKW7V)!Gs4#B%Y1< z*u*0{?yAcM=H7+k^`{{Vwl$B1*z188y2PAwonGUa0JRwM$rkfgf*_dOk!+SV zNJ)N-hL4b~P2>WgsVP2c(W3bHMT_uyV$mW9?9ug@F@1@xyq(bB#{e)1&h@V@oelnkFRg!0Y*8_5q;M3i4jvv~uDv#$G^@V4p<7 z+?55ZawPWWG-2%E^>-=popDT(H#jt`yGDduz%^<--)$VxSyI?&gpa^kM#dr#drNK? zxlJO!6+!;k!%>vO+m6qK_RIA(it}l*&*z{Fa{??)eDGeDW6Jw!G<=B4UEx@!Q`tL3}bbO$|Pw z?y}e5pWnlKW#)}6^SesWKBU&i@ejDX3nN_kcg6Z$tuALDcjd+D5u1%3f97S&HyhI@ zHAJ)I2`o%uli6cm$%`kUk_igd1^8{f1%9q`%;WQ`^wGN3T6C4!qcD0{g|m$=Ep^v=(#h7 zT>b6K8;Wa-V&F`z`6eYE%$M8B^Ok%1m}PZlfq+?2Z~k{5yjfzRn9xgRf2%AhEh#-Y zEt$y)v7`zhIN4%hKCoIo75K0l-o(RY2o1Fa>2VXB{1@){WCz#HKfJ*1~wDCUPW3rz63CBsrR#yImuhUI$$UV?m3VzEe!HO?N4TC9mFGm?^L z;4hdkg2`Z1RTdD=Np4PVX?CV1r=~g+6H_ysiJ6&>w5*J*tjx^J6nj=uN^80!t+lna zCCSm8=16RHrrA@{GaZ?!>FJKA1Za_q!$-v4m6LX4(E5+s<@72wYhcWZbx@@QgcmCURABlSum71 zRMufjF00KSF3YP*E*o{*l~_4aK02wg9&7(M7XBLt%Ky#+Y^wB6SXGujtQ@MzsI5&I zEuZH|ZLI7}$nPkOwb{EXiyM-PQoFKB9Rou-4zE2gv!$wXpsh8xIKx$5lkRM+FH24K zmR5BavIvbnw8XL+++nWm)#CBJf&71G8?`SV? z@MI)Z43~D~c)Xdbsxp&Hh6g$pxb2UT<@9Ph&<=eP^z1DBotYm(`Z#0T6Z}DF>P@Gbc5$mWM z@Fom+^J{9FORLfqGYWFcY8%sr5|oLJ4m=Uo zm(@ATa{3zUTM9b{hLh%(RrQotjtmy2b!OG~G<2496y7g|^Cnh8p57B+CF8npLHMiZ~)r`+d zt)5mZd0yqjAQvtjviQTkXZ;i9`Gd7+`{@mkeb7Gu&Y!kOK)KUGttzOm&F?PDtt+%8 z)#c~5mpPSHb!BZ;$p!rj=FjW0&!5-dSd&v*h1OhChs#ylhK5@;TGr8)QdUzoRLr@D z(){5bPfJntP=zaVuqCA>rL?Qu)7X&YQX-L2dqc}WX;;?Bg3)|eS+0#8$u?ZJpenh& zUEJI-&kdXJ^S8w2@y=q@mR2@u8&;NgIHf$VY@{O3FrNg`7JE8j&r+m7}}7XF+o6Ky%8xZe>|b@ldgi^@Vx)!|ptLVL^C* zV^{r%V?r$FGo?nnqQdm5%(leOh z@D$f{xa*X|1qJE-Ej?}N9c`Iy&84N8&4UX%YswO8Yz0Ft_RfNm-o#c%YvsK9yu_BA zt{z+Es=l(ac4wNSFr_=U(OZ*R?nzCWUzJ~0JXBqzEVuVIH|D3eE$B!oo!8dus46K+ zoWH=8;II$4ZG~;U8I9%XdFjP<{Vi24Z))yPrES<=*U;JDkmIV%SkUFnv}a&up*gua zy`w>yXNw(bDClS&N^VTSKh9ZQpI4TW*t4q2VejmiH_}?-PVTKMD^759EHL#eJTTUteGXGvvuYivsu?riB5xwg8hp|-XHTUkzVA#Afwn|Q|1jer&Qa>fXct?VOg$&m`_W7TUA?GPI^vJ zA!ldA%p6@=gDv?v6NGs7k^7+roVpU{-j-94KU6#V|FHM&ue0oHeitEQCR3Bl^<-w& zT6@NQ#stQ6V%N31%Os9v@XRVD;awY$^zhzm}Br!ZS8AQ~6=dakn*N>_rwr1QGn#r>EK{*y+<#{rqjnS5Nhw zE@DajJ{KrMBX@ZDcUy1=%*d9jO_<%7964_1%ag8#sIeQDqfTv{m2lRs+uBFZ(KeJ$ z5yhSu@qU`chodvc^EgOql-cUxxHb1)tbm;lmCd&6dmd3%_XS6<<_XcRkM_mdZWeAa z4I)>~t&&TV$e0-A@4*x;V0RU(~>+e%Y&#-@#ZHy<=)uOAn;*~oc| za}vb`n#A;S@HW-W5Mqy;=)-A&GVxw?mgloBUqsw5Y8DOHsiWC6q&zlhzMUn0fAjD5**Jt6ehI~H z(mN_YCKa<_Y77B0-?eKu+ys2uw4C4bITlZMWu^@;|K;C)_p?9ynJZX>`U?!-CyxMQ zYu+5ezxsDR{7XM5jIWO1jj6up`P36^LXR8CaW$+TbK)TP3Q~cG&*KGy+d!E;ur+a+Y z)gk{+eBGx*{pjja(!r-ppGw5iiKsG83jstKBo+ zz7TGe;`@y;_Bm#%ieV7*sNY$+zJ?JxOieUN(X4HmQ07#uk9~Iwirc-x7UAA2%9M8K zE@~5~cOwga>z>eX+ix7x8g3|A~_!o`z{*UaNQ~{{0t7S zRonEY%*N|>+@O5pQ8BVAxvS8)*@R|BeVAK!_F~Vj?EL0$;sn3w9z7_fKkp41*EsAKpMluZqr3)U-{S$nNe?l6;QL)paO7?D z@~i#3Z@v87fB5bPABfJk!|8Yu9PVI}2cn%<+1z)C(r_JJ?FF9=%tq44W31g~hiSuU z%3h7+wS1I4w3yHLxQu$3g$k%m`$)QzS=Y~J!%kbD?)L1Ypw*>d+Ql}moXOoLTi>TM zFTdW6z)3gU?Qy;6;_kZ6tBB1`j*~AJR$t#wteR{QeY?EKUbDsKi++w5SZyARK7<%q zcGu2Op3Sy*#oKnhI#~5ycXc$_I4HK7jVZg`Rg`~gC38EV<(*eZWW!3@(cVlJI7nL~ z;zMi<=h=6s-+KS$_js7C&BOg>jaRb|Ne6gd!puN6fG`?OZOJ?-g>Y55 z)7u9|HQ(b-k$Bs3Bbc!IO4N4;NK%}8vM#I8)v{#0PxsG&rz$&GfkOQ;QW7B1NdL&^ zdw=;Gzx4hmUoJ2=`sJ7Z^ACUM!TaDh1VXh>D5M-J{^m@+yYY3~_d1jBIfc)E$MX!3 z-`^<^-~SxGc?w^J+6;Zek{EXQz`x)SBg8> ze!9uc!_<|;>ZHn-G&t3e4QYK!Qn@}v6+Y@3c1JGc9txN$-SX-cz0dl2*9?YJp4*$T zJ{rv-*?8_@e`hq}dfXX~Fu$-C%BG$p(q-O(^a6h8;7-nl z?h4%{_QZjkTG^uJ+%}&tTGNl?!XfU(m{7NCw!Pd!?Ht5R(xM{g&6bgy=FB`n4(g?q zhJ&XvLK~mY3$yiYxdDq+Hyv-8M7iqb3B{~;kT>f-rn;Fc*L-$bOo~(0x9v4yjwg90 z;`-HW5nK-h($jKj>V>{xZ6|kbd*e(rO)vLEL`OkCos({^yWxr#!{$n5o6@coVv+cJ z?L;PF87)q#`e6E5fGlR&&Gy(xcHNi=>tvEwta=#K1ubifT@xQ>K}X+{if8K$hEp6l z%?}%!T9O7f%e*eyBJin6AmZY2uY;DMwjND2j%9rT5d~6N zj?KvsyHdm}NmVasDCmX}F7N94)!Zb~U?!?~8x)yoE?mCeemDIuAcRAevxfTcU&P1h z_BEEf(^GKP3g5ztxEkJ^HrJ(c$egp>xg?K|!pGB_fBN<}zYLM(XWs@Xzu{vx=KmBN^46x308@bNi$IC3@n9FDOvEB$H8gL}sRS0m+hAq*tj@%LrTqCvD zW#(7qE%ZzZQ8@Mmc9)9vke-vvUl4?FHaEJ1g_p2$@5 z;&tV5dU`}H%4SdEO%&IZsBNoJo((;nWYh>E>1BosU4OAI zkDbZ|h;Ru@sY*^)!|#+uIb`6yc;dbdj_%IDj9o+HWy)83UuDpH5P&gJE!w0vhb0;x ztByDaJh~~mZl(_na_<{%-|+nvZJpDsXWJu_=ZgWgb3bQgkY6N6Zf6cH&7&;!R)vlp=~dC?PZi*BG|bQtG!l0B_U1jL>2_)Jp>D94(Ey=M0cy-j{QJU zjgx{rW^5U6;dB+su*KrOI9-fgQW)~woi8PKj+BEUa^`JAhGB`K>q~yG-v(#Qw7T4okhU4VbT)C4QCQ}NBR!_@(+IC z{ZIXY=;c5C;{CTD=DIwCEqFfa_A|!-D}=?>K6Rum78AxO*o^-43M_N8Il;6Y4l)YV zu@Tjb2k}kS;Dvz__81tYy(aEKBnCa(*NRVqGgPJu<_;AqO0%=4-aKm4r)`h7jR?4m zZxqNJTeX-$dZtNGAQQ$!fWvzlq8mKY&lD+3B@nD^$A(EYTPrAZ z*kATngWbliBQfJl&p088=j=KVi)of$PJT`qn7m9C(aHVWIBOpqkz6TOx496hxlJh& z`bFv#`^q)6JEa+B)e43=G&$8ypCoNKY`t(6NJpmFq*q{P$(X*lIH`&ecN=8ZyAv2$ zUj}5&cE~{b2Xeeyh!>gxg8e zf$XE}`ixKYk=O5tS`3vrznr&>vOQ*4lnWq@6wc~sd$m%9W?buznnyySJN9L%B~|Zl z?_UKX(nj4#;>UZIAi^^O84TEMHzxVE^9@1K6UvFq47>2L1AuCGkHMFokmNX`L zU7zL&)@b({OQ`G3YdXGR%t#eagERQ@YufJaAzgoZdUmS{@z;HH(SD^ayw+9D<{e2q z4GknMd}`3(M&7)C=mxcqi{Px)K3>yM0@Nr4eO+EHIPp{9rQK_O{0+?-;k?b-&N7~# zdG4fYO+Jas!)A6#m+6~!E9-vIhIf2LiqxdQiKzlJb8v(b{p)!PtP z60{>s5l!7YFs8&#&p=2U=VV9lq5_F29nvwmIu&we_%inHRmvYqfd3 z#R`4z25spdJgT4IfZ+-ak<=6iD`=9^A{PAf!tIsNU(3AE*|F7?*Kia5V`YBU} znXv!({gb%cav8?YVnc? zZ2+N4jdvHr@(@=#_Zy+%AdATR*>L1%6(p&|$afaGW_8smf&>jNhrN5FqKd_H-cVLc z-MnoH**|PgQY^07WmXU-IUzx`+i{L#>5)s%hvW6?iVmn=br@uFbK=GCsH0gX3{Rbs zMbDsxXoz;qla>*3ym+dkSn2kh8D1F=vq>a6)Y}QeZq{PnSGTR}sXpeMwv8&zxn>^a zx;>lj=2}FW>%q@85sHJ2FD=@m{A7+zu+@vAg#Y|DHI3UO{8V`=5UKd-xYW z_44isNFfr?GqL#3eNnHR-Sil(Oq zdkcYC7;fkMDqUTTVtd@i@E$NUt2DdkfIZQfS+_IX-_iOR4W_-cfG zXI#MN-+sP*`r*qz{iXGBN8I((57n0h^5lG$&Skvk(_m zFKxb;w%5=rL9yFHidD8y)4pw_0P-EP3~>rlFuH*v;w?42Z8iopIx6Dh9=SqlJvA{f zDH{$=9d#EQH*0`+T~YVxV7?uO!t=BfNzU}t0Zn%-LjoLQgj02RXK{$Rl(;H~1pFXy zDv)l9cRzNIiE53nRDj?-GrKxbcYsXoRiX1XFMm1s;>(A+ zzYNw>kT49M7sUNQjohfPdt-k~o#%J=`xLQOI~)$ce(DHMhaBQ?HtTW$c`yn=VK#2* zo9~^4o2v^q5B@x_p{T>PQuuz2rcjlB1*QOZAR&4&M!;&oLMNg4cnwM!QZ2xof86*a z3gqd#=K5)^9dR?RdB%Oa6R`>mK zr^Yk&b}`7bhctPH*=y$-RrKTaLc+PRaV3e!nXusmUfB=@WLYfo_NfAq?q^qJw0L&? z(PgMQ=G-7`c?R)f1bc+ws0WX6eJ%(DRuQ-o76q}Q53AGX3*vP>m@YLvK5xG4og)H$L7z1 zBHToig<8?uPGRv3%is$4t9+*ZbpXfd&n+zFlKk6wX%Isu42#=IxH#@)#)F;IG8&V0Y&q0FEXsC*w-ty((~CxL9%KOnuK0+mVOAg zDu1{Ac;ha2#X1@*oAibcp@w>VsFikVqS77I zW#^d&$i;(S5QnRpM!Na>iLMX+Dt8*9g5ra{&o-U z2HxFkqqw(i`tlq9$NQiAb$j>z-~V$z0;&MNfvI$_Q7-cG+yBYC`TJ*ZOW~g!(#H1* zDJyPln(m)z$hRJY`B}|~83yf{%bP;UBQ^@p-ZR|f1yyBUYn}o(4E$bbx2mxk_%{(i z=9%F23-I}`r}8IA<=;YNu)4f4?sx$Q>wABTkvHUXTdq!DZTuY%<(o%>yh3&Vl!x;2 z8_FO28R(XVZ2w!2IVC%!o34|qal4Dz=HBCs!<7z@BJrilH_^ps?a|24Y-i#IjQle^ceTWbsie8oxKd#URc$%FD&^kx zNl7-xap|#-z&m6ekNAwS&?}Fh4Cz2Lw#zHcj%ZK9GD}>D0Cj(kX=2(D2jZa4EEhvv zJP>k9Utf#r$sk+{)a)FQ)BVGMsJ`1DoF<-k$nQnjN*R8HRI3?v2pRg4t8=5Eud{664-=yncCk~+_AC~eUu zzEUMy+3l82B=`HdZZPe@Mwz{FfhekRc^90GJ=0`S1qm`85qOhTcq@9gjg0bkYu)_STBWYE>NmOW$7)MOYN@Q6Q*+nvl1#_p zUQf@!O7Y~>&y!H25E7 zAAamZI3c8UyIN7?#fx=Q>U)+Vw9=MG>qY$!KKvN8q3M}?Z?|omOqa0PBeWr% zA%;}1A~OIT_f|aNQK&#M6bmV*WHF2iLf_|wlCRfE=nSeHClE$@1j-v_05t%hHqU@T zU@>5SAo2IXnl3=nU2`w{fB5bv9?yd6PGMSW?{2Ci)YMaQF4Aq2BB9jkr*hfUk_u?A zCfrW8a)w#rhdo4OawPEqp|t&FzB^A%PiFRdnuxT&fYz^PT9|pm?noE=)%-MVb>y)2 z`D93Zfa^EMVrd)8CF-Odk1SKnER>A+{#^$xsuimnp2F@C9F8Nb()lHFQn29x)@W-hXMd+ z2E`)F+sh?Bu5Jg0Gae;|*co>zCVbsVdvoB-Jg zJVjb6=$b3B(pNWcmM+_d(9>w2Wvj~uk#iMTW9B-|@V&dZ-w&-K$-rB1RI6F}*k<-> z8yDl5Y|k;fygsgh*M^L%yC<>LfwrTM!!5W_Kmm&zP#yl4uM)SG}4X=hW1b-u@ z6Dj=JB{$W?1!+&d7M&??R~`1l?RGp%2^>6CXQ!RL(>okTXZ$HK)8pwjlc!X2g6vSg z0UE#g@4Wxx-+B4_zxnP5-sR^D2u_eFG9C1rY<0oi`a zz*r!qUz03IB;69w9Td_A2L)F9nbp;R3&O)*cEQV!86Q5pod5MNe&Vsk#WNY%%-GZ^-d(qZ*6=x{tpJsi2>$3;^kcV-lQ9~~JEC-i1M-To zaxwySxs?rt_UdBeCN6>#2#oqnH?fs$GTuF0b$}ZJYT*_8a(1=OmJR$;6XWho(ulh@ zfF;M&+Q|7;=%04%?y}@&my3Ip>KtF2vxPk00jGSn(T9wlxC6yvg?;O@>skL;B4s5a7N;8D^*3BO?BG>Uz3+PbsppwKyO92cc!b4YnrE|XN=1XuUkDCAOiDC>>1)N}Fq` zGBa}tKMPBP>hk-dPsHn_?@D=x3FkBRurBz_RkCs>=~{%05GQpwODA|BIhze5xa>{6 ztuH&aze1yljddhRAGssn&1b4Fv1o3A0HiI#P#Jg@+{;vz*T0gL8X-fJ!d9G(E|pvnNEO!)l?oeRCb} zp~46Xt-2V#KaI4Av4ww9?Vi3}dSXtd(PkISN5pN;$)-%5W^=V~2mj9b8$QzDrO@gT zdM7SS6rJ6r+!9pK+G+28l$G^L7R< zHe5@qRTMAq{lQNzv8qnB$DeU+PnO{A4~K5frR3&8t@b^S%Beh>%=|8;Y`i~{zF`W> ztD9vQ`z+cOd7^K*SuS_yrnnF)q4_K=T+=B*8FJ9;gQ_X_w%LtXBReIzj`kf^+xm>5 zL_KoE8y`95@fH<5vQ@DDJWBkC+Z=z-^6cRThxNI;x3gKN#iu}Bn1+Jc0@9pxQME-M@-q>x-K{#iqkSxhaz1m#UiR!mfv-l1 z+MOX@U6TR?cD8A{O`QnI`B^^X>_??#cAhQJ2yu^&P|bTUA%-I?q5NVo;pMguW!=b_ z8QI~`gRr=sgR~8zwW7 zt&W=aU|27)BN$*-DJa{Ew<~OE>nwC2uA-E2+LI?{zATf`u^5D4-MP!O(&tE@wjei> zgf@%(WP8Y~z4P)H*)M+f*Z=5mzQ6v7?*k(Kq?Ccu$-3WFIu-lnAN&p5`p`t8n#EDL?ER-Fbx6~N)Uk3I42+l;q$K*B=leb zWmq{`0Qe#FEbP)kl2Lex)1V*t?JE z!y7aKb*N{NK*RtWe9dEk4KzNolfVTAS?G=cC646=FvHDvuTuHiF#64_gnaWl|BekB zzXK%r*;OdW^I!|qJa24~o zm*rmE5hbGm{5cz`p*in4*4cVAe#i`MF&Lo6`!jr#UqPpa4jQ*YG(wl=``)rc)HBp< z-52eAf1LO>-H(KdiyKgg+WBKUdRHbKuZ^7(xn*5EkmG0kJfF3SemvF6twndShU~8C zZ0ZA&ZYXK1Hic$KyKxmtm3F<&X4QSl4^ghF!sQ6sk(>AT4-n@*nt9eWg+R=Y+bT~chOn7gatUDQDU!f zX5U?$I?TnDL_ll&o$-(ZJ}eEZjLC2e(HK{&S({4c`9{y&0q;v{Ejyx)mb^nN$yVFn zE_2*0tOG_JZhQ7o*XrTEUhW!nV6%cja8IVZr(g5cV?X&qM3{tz)Pwio^jBY zwTAXf;)rh9Qtyw~?3Oc`MWZ3km2`704$f}K9G|@*QokSWvT9IJmXR}K9LRlJY;))t zto7VEwO#x;5|WzB#}${b`)g&K==_4Cb`3*bTC z{rnGn>KFN$mv0B}|M{0+`_u1#;U`4@S(Qe+PelNB_Y(daAAU-+ztN!hJ-ruS>yG%? zK63lm{`BksDL#Xb)33TG{^$cSr_EbSq0K-$A$$@9M3ra8w}9&e-&CJ}upRuHTd=?D zfgsODmd}6D?{y%?%isJZs6Ig}$`Ab@*zHqlPA}+R1sq6Ue)!P`p4&mhF5^_Y;#@Za z;G5YwhX(rZE||C72BkbEtZVoO=!Fy0nzf|eilA@B0u2VOSsn!4T5)FPu_7tR2O>We z7z0g}EK7CTjqi`UTA`&iLNasZe7WqoYfjT;kgsCr-WHqkfk(>JyPn8fV}}LMQnI-* zhG}sT%A{NP20z~)j`t%`DgvQLN9hDJ=@8~H(dFixP3xttwZ6Rest%hhE;!OFhUO0AIoKk9bR}X?UL*Qe!fntBiegbiPu4Ek zjFJljJk`-PEgO?W>$5}1cGtXMkwGQ4k5vM)qvq#pX8yA=-BW|+L!~Is!hF;Eg-L@xX zi9M?*Pb$b+O}9#4M&-Gd&bxB48XV)1Y@O*`z|l|#&g(*bXQT({y8)xOvF8H^oyiMm zrl05gec^TMSw9n~nM&mrBCa=!#MSk~{CY@>uI{FDJ}T&qVU`vH=J*BEJ=b2C zQF16mwBqjgP|lF8-!8jSw$8=!GD7`K-?4Ixx7kESu`!>|H%GGYEK{Z*iPrM?Mqr%- zhgZ-_bayE0PVLuzuPRX5SR}$40Z8X=UKbcZOhm(oNqLi4ELwEinBPk2WxLtr8Gk!Z z5sGsT!=yDW>l9z^#rr~&u4&Yb9bKKsrNG-Ua^7V2a<6Hca+?BuiC z_o>|mD=R$0OpRt*iqjEYUNexw8DmCj#%yn4NiZ_vQkl)YGC?Bf)bJ*L#mI|Zg|=9` zx-aTQm>nnOiNlR?7Rxdv-NH((mi`&$ri`eRdSp0XsNvbC9&$*5&MP|{w~3K*MMZ2! zs^k?OFx0Z?HYH7CpDhm-z+N)WEKE+x34yaOe1KO%)rrArbGc-RlO&2{@;M73+OE8< zcNMbqS_orcLWpd4Rclw|<=9v1>7Hgny}1qy%)mJ)f7X~YMOR*LmsQ8M1+couwa}aD z+-AICC51b&FPg)(LM~BF!C)A_Ej3R$Mh2NAn>WPk@gpDp$M=}MH)Y%01MkkgAzU%M zsPBn$_3#dk+n4(F(!;Q^>ub3iraYm`H>~ql<{yYZ1Q0dH++WaVpCrfjlQ0Kp=M`yz zA~)2#cJcny?)RnhB-=&gYxE2tDqj&QzXzc54HpVlL(q|Dsq0yyW(OGb?RtP&}zOsx`oopdnCIp^LtfLdYvR^l^g;EKE{4U9>&} zD|7maf`TvILns(1H}|0A%*DUI@jeltS>fXjY$^|&Diq_9S76oNfI=vc(A+=1l@6Yb znwvXNP@lF9X|x*kiGcwO&mI6(g-RlS7PpEcZk;Fc|D?l^Cm!~Z4*Lua`X-$9_y(P2 ze=l3bPmK0Tn6ON&vL~?%abU}A@t}&s8;6vRuTZ;&Y{H%xAj;i>$7;q%k~w8 zgR2QQ^y3EM_-6nF3(5$TV*tf~TFdG~g~2yQNSoj?Sx|G!$y8peZ$z6r0Z4WOQ^yS2 z^zwK9^)SNpO}bWL4tQi45qIZtZ{jE{h-`a$=@Q`08) zy#w)3wr{SQk=Jz4q^p7!Tz3xW4hfj&@cWg3_6NFU5dI;1y$ zT2bnfAY2xo`Kxd?4&K#EZI^7a14^nl4te<^{^H#S?kt|p;eEva@ZAqT3_iJ%yKcCk@C>C_!BSv=k74a`dpo}&`ZyELuCw># z)MZZmBFZjAwxjQ7-Lb7gs~0J>i|wTiNLx8)R0zcZ_?8#hVCPNk#gl4%h*zTC)pQ+P!|#~sbd0c=tQB3AJ3F1CJv3NqUOscDrtKLeyBntVY}(6D z%PT3k)Y*w0+6mn6m^l{85yFbq`o7*06amAx+zTx(=YSpU)oY{mZmaecAE7IKA2g$w z+~uf{%d9cdGv5cBDkwJEvk@-QXFy0XGE!g62DMB2)d;^_<{#ewdiXDXF#gC7>lO#r zHU=vUuQKj|blqmqO$xoKU*#0sGpBeZT}^V-3ug7vaM;@Zng7%G&^4bD!wCV5^mCN} zikcu2Kw&ZTpm%x=G^+q@J!|n4-B~w)g6E+E`{7dkH%zSyn4$ru_HD=sJE{^)*LvK2 z=vs$r1c5vJNsJQgTNXqtyTc5qUl6P4L!4dvHY z-}014${uE1{r>iD?FVEt_*?lBY(PlS7~{l>S&%_zEL^pki3uQfU%U1n`!2xgTscFv z^%cE>ybBEble_|h5A67Bofuf5R}Zk6H2d@{9s`pqjBnNGQm3iUM z!^y%15F^7jj7h*YtSdj?7+EXGL^o z_-pDAT5y|fmn78Kj_GD)WC=zqM8_b66Egv)lhN%_&C2~e152DjDbJZAsqfD zI=hAITvl3QwayRw6>Ta^N2^NZ%#7oP1cfr5PNz$Tm`z@D@-)(!z~RB(Jzvni?0k;! zJWk~55WAK1HdffVT%WUpa_d`hrRzUoVm+e@&wF53q140l%Q*|EQK;bpWKw#FD?D`D16_f3 zT%DIPEZuxJuWE5wL6X#LUE!$2`_-PqmK!EbtIMsgkt^QG>-Y%HFT%*A!SLgK9!~{i zXNNv&41!GK^QTI8nyMbq?Ysap=3#W(vn85U`L9Nw4JxQ zbKvxzvj4+*omrS{26(;bK7NYwe9BsFci$w)2!kh>u%MHYwN5kKANF{MF4oXT5uRX% zQ~reXr9ya}t@aGHL1V%`ktzW=k5^j@&FRlL9s$%GY|_)DlTVDMK0IxW`+yb)X!-NO z_-w>yeCRAdn|=a^U&mO>KvYd;cpWrn7!q_WCj2v?2h%dC=4lY2xeMACKvHLg5O(+k zcEESRXV}-aRhXwWKuO@Oo%N2{&(8#qDLys=m4Sf*J^eYE>**Xm9`NVK`;4=nK*KZ4 z_Hkh}CYF7(t2cXB!o7M%{?BOw(2R({UtsM7aHG$$Ezs@(Cl1zc`o24tpDktI*!$LI z3O0T70mxTQ0LUXS-}T|dPS9=eIu!vb6z2%vbO|hP#<;vf-w$D}3U5=F1n{|tDp(wU z{$8hXVfSkmn)p3{YcC)WawSZ{yu<2&rKIw5x*mKHIyetZD#P@y!PuY5HKOb`d2?9lxu6Rv8J$UfwkPa zIc8geFztAg2OtC9@45Lni(;2kLjH2lHP-|xG(xBCqIrLZdi^WyzATRkrtP%8!W z(7+U`uMHK zV`~Rhp`B?G+;Z4%)8&reQ#i3kXV^I<5(_&jWwMCzTc_>&wpw!a&0OLVjGH)3)zR%4 zzS59%IjefxnJMBhYS1!-&$Sa1GdAGa`8#(PY+-Eq^-M7s}^YBk*5?$BQls#e;X6t*Jt@0H$F zFK8dNC*LB(rKw3U?%~4prD3Tf89lo!w++7vDssKtho+o0H$^aDbXx@#A**O$PKD+| zv&8-C^EO7vbOi%2e1JAORKy=_ltj?EClAZi^2A7Y(ve>56nz#XijxO>7WHQP%o6WDL*eu`jTC960j+U zl)F*)WGD+dimAA|KVqUjQNs>SB|7_8jy*>+h705JM873P#=E$hgFrYI?6b$ z$;<0B?w3El_|VKgw(Sbwxj_A}VE`^P!f3B;yU?2OwQVo|{o=#*4+t;VUwsE}QGHeq zngOUXVw)E=Rv(fvzaxZUo_JiRVRqOS27X+c#>>xKxZibo5R>UEb9%j_}gmAe$Dvv!;Le-&e zW^%Kd_p4KWx-TMiW}BXy0#8wkE(xidd;@cAcQxa46D=xO{~-dA zK)=1(SiGNaF?zEma9svE?BW_x%4x13Iyzy%6&XWrTdmt^tcqQbEFM5Ad&KRq#GQqh zma(TUYITA1b=6gaTwLRm+s4bpt4s2jU8v(#Vc5`S(#9=JYN0O5JKnF45tY{(*qivW zphS9khv7T-GuG~Tf+-Y4$s*Ykm}#*-@=AB8%-zK_%>fH6^zblU0hZIIs{?fMT#q!4 zr|wP}b7`Tfss&J640@!)EymM2y6R944ZwJLE)Brm1=WG*T3qsDrGs6}?M1oVo|3k? z(mSFUaK6WmC+^PS$8-Tyvk{(E$8#pM?VsZjMl8P}-fHwCDv^uDBt_DsI(EX}Ye&cK zGl8}%fVfyCX?mrygLX^B`^zP22KN@G?aNR6%O9jKa-%_aTQ#JbzN?_kYIfYO^ujX` zl-#^v|2qtnmd&XKya^V$&F`4Y(dm)FU8}G9cEX|R0w`SWnLMA>GxKu?nd@V zvxqW2?gC1lC9=J6NeAKyKC!@_^AZ~^N)@9oYU-o6Jc)Xj4imH0ZSNvATiw@UNj~21 zmxYx?nQMUwRuS$B;~lk4VDGo^|ba+2K z&;-ww$ZzJ`6Eo%F(%XKPI(w*H#qbSBm0d3^YEA3>(~|C5&&+M^cC$l%MVn z_~~e!BTHRygl2GsiGo+WO4gjc`HteXqQs@{1f`Sid`V;rNno@tKP7&xZ>`vk=lmuk z(+#X?Wq&+XyBSOkm7RPD8yQ~P>p-QNhVD99x}Mz0C_KC;hW-R8#`;|3j}a-E(Jywa z(-dtH1|rvq^!3$Ll-~PGrW= z(-OuHhPu4yXc$tl#^!~Rk1NfLmJ24)AuO7%FzvBC65~l;6*t>h3?p4D`gt)Qd@Nnp z|95BS66-pC*YQ3E6)Y|-v}&1q@4$>yT9DiN5kIR6aQsZ-_?3s9fLd(Fv17-M9mkJE zsD~vi5G`VefJzAVRE!Xs4FaT@6`P6;5-Si3K;0m*Kte)-U(UIAm^+%54vVXEPo#5n zteo?Ie1G5X=gXZd%ZSMr%BG)&LPd@)Mn;Z3vct@wQy*zbgPhG5tp$q2Ui&cZ}cu&UBmhV=W;Fv#_ z=BexhI_yD#PNvS1Jf7ZCRl^%yV|&z(8@wIsho ztPuK-Oq1)Ee&yxYe)NXzdj50YGH_qGL)x%1j{43~mcAE}Czz$^kHZt_)34AZV3-kcq`M9PQwpHxV(|!K?^eG&!=z@|R7$jaQQ)bqNp*aOZF4mu=vvECJN zwwvhZ|qg5HQcgIz5lqTTB@%^oJLE*v7wRZtzdLFOx zWH()~VOXV$hLM^(jEpzfJPXi`NRq@PUmft74*RM(6GU-BB3!BoR%fFO&Bf8ir-r$c z3905)Au&TKNAc}Un4J3MjE?bq7CG7;H|A}=eF8P9Y|+%+I7KHKSv<+*k&G-oR%%NTjsEK)&Y-6 zxQINY-wY90InQ&(pL<0yl^njegK&YNpSo47SPWofJQ8bb^mg+5%q?*y9)Nx$)I~7d z7A<#l=jpU)rdE%pMloycIosGNMK}vF*9A%;^Ka zS@32#3k6o;H!GHcQ4nx-6LW3yb??DFiag@{s>XDPlDHzP+)=PQTQy9L3Nx~`qc9=W za?KT&v7TRo<)U^IG8%ijDKcc$6U&{*vh0dA5=S&s1a@~{Y9oJ`4I)A`%+VUKD9e+l z&G?O|P~!+(AbWOc#0+H+jSt>?;ewBIS4hReY9V-u-%W47{wkB%B0?5$yflPMwav7i z_7Z;15}v0rT@A1jBx>G?^eJ9kK$fGsGn%L@>ee|OPi|6V7^F0^LO25F|KwW~ z2E>b!#~_$5+ZG@%%+l|0$Lf1N&X4JFl7&uLY`EdXb)0}qeZ_=^jCEwE8}S@ly49s5 zmVv_}R>P=Qh52%`OptuJ;TmB4t`-?{cP?D+Y*%xO3{ANm9jH_eIwf=mUBaoMf=Zyx z!PKAJDko53d!|LDfH%rnyP>8xco&i_%;j0Xbk+$UZ_^=sN??L-U)DHrfHByTWg*~` zs5`Zv?#fL_3Mc{r0m&T92; zG;&4|+KD1sPT*{=HFkvF7n3}C*wg?%zk?{t^~1mZ^oyT!Zz>utJ|DpV?|FE3QVAR1jXZq(D&4s-2<0jg*NDLR{@`LPW^6EuB z?Ood$0=gL>-rj#d`&rn~0vHBAX!2b*yKQ##aUwA*5st7T%}h`r5$5^z-+tri7w>R6 zOSByro;bPcs!Omrtkik4wKrhUVBH0QL9BKsp&7zy*ij;QTBq_J3;NWRqIrHvsT0wZ zka2{7_Kb_ikrBvkzc3bXY^n~bSGjcQnj4e!#64*9f)@mKO(Tu1U=?KL$h-WK4=*fjWs$rRCR(Va*CzIL~*&=hNdIA>^w_a;*d{^p9AX5o7Uy}1~ z6`3?5Z_tifMzP9(yw9sGd9J~2G(4m+?C~9{8_PJ5`wKou-9+3ET;{~h0#0Imd!vS@ z^N^42R6&QvCQ<+b!wPU+Y7=T@CIwz@j@&sw<57G{pj48U*}DV3+#feR2LPwgk=1N= zXpehOFZp<%4JMG72cQ!(Rd=Fmh6u|@!JH$Q(h(mm__*fr6+709NwM!RpxLr<%6T z_VaCHuYF7_qkW!2XkAgzRna$GK#~|IEkLadY|{gz%F-2EQ(Z8~Ig6O12+D4Po&nB^ z!JHi4SbA`9OQ-}Qz}41Ih!I^hmgW1E#7N%#mGL%NqyX9t1YVfFnkIu8U#oB3))oU&k%Aso<5BZ{T&)$y9wN9Kw z_&7FK6B9Vtle-28np^_(!=Qc8aMr6fW66Z{` z^H*FyPGrm3DA)$2ik-JKCvd&VnRF(jx=rF!SI zT&E$o^!PixABR}5GW?;VjY1}XL?N*zdTX;t!$~C~)Xf&3G_~lH=>s$$! zbeN`=sj3iZoK$GhZLt-Srj*q1aaCJ~#W)x{KDCyT8KsSSP}mk1_M}c(;0NNY)1<(A zp$J&II1LV-yv<7ct=t|7d~Xt3P7KyV#5CY;4o9)lVVv*;E=fAP^u`pW)SR4Xc`UAQ zXtm>qVHT^{_|VX2uqHEl1dM{l67m)z)9}^%n}fYYAT{2_xa5sNC!zuPkHe~`!J!o= zJBrnWP`7(k9<3nOX*dKqX?r2phqXs9S0Ohi&VEM#*l@C{saaf`NH!vwgMF<&4!Dx= z51!ytZvNJ{p8LCGP_ItML$P~bTG!iu2%N6B-w5A+qkj91SGDUmKl+rp=ixt*$2V(p z_f8B=6GoJW?d&+7U;V#>X+Zq}%tpo(tVFkAk{I{$|JQ8vqSxr|{mn+b4ZrvgQ=IA4 zywQ^0<*Y)UgSY-~XBA8}Ucg>K3H3uaU=PSE9RA$_hWh6Gdbn$z?_W*h?)hs|z?HuH zU;uaCdk5Ql3~UenHOS2%vxiyN1gNV&kb&*)#=81m1~%k-I@nSuhm)T*nspuhp7-KK z)YUVy-fhTt1nT}AG&_y-=9F8g&057hm|52^IbP$@Hkn>hY{^) zoeQfWMj7i%W>-4KCYM~0FsMZ-p}@swcFYAVBn6QXeACqpJz$Y^IW8%>D`dsGl!C65 zusx{xo(O6%`U879U7K1tP(5j;Y58_P!|%?0>MdQ48FIs!zK^kNJmDe3aIA?OiAq}8 z<;j4`l0(7hJ{M_2d5j$`F&~zwd=`ya40RCj2Tr{Sh#<4huxlOlhip4%hlWfLL zfp5dfjTMZ8$pNfD>m@>^qk)I@@MxF;j8AQ(^G08F*k;Lv?0f>A&rI;wS~}{JIb&bH z@ykyiKV6oYhG-|VmehTA5_;R=X$hE9ac9-f?{kl@e|&%>4uD(7w6ZB`Zzkzyb5xgY z#JIDJ8LGPCIA_Vg)maY?-Lm!(t#4YO9)o*Db-lj@w6GJ)m>HQt`k>H+5l>L;rM_o9aQVi z4qZtiR-=k9kAy+5eH@b~W5I2qT`hrCvpW%Pus$1;%k&rqstbZWR%}ZceJ9ek>)P=i z*_RW0gNY}8ES0jCdKpy+mfbKDDB8-`#5rxqjs7*1nQeWo#|V;{k|Jb~DNU$U83JPH zKCXP350kmR;gBKCoAVTPHXvjbfWjC=et#|$L+(R*TrbMeteH>T%0;WwkXkgPVYfow zFYe2&?g18WUjOw;_UQh<*Vn)L@~3_TiVhzx8xIkZZ~Q$V4*%k%$DjDL4`K7&VYk_W zDSQZlqbOGtN4k&w{_bBrdGzHEB$?@R0S2Y_-qQK_`r7v8PhS7)J1;+aQ8wERHLzjc z*nK^ePeF_Xq%&zjJ;O=k?|p5m#69vt-RisU8sG1#0XL1)^w!WueEi-@kUj4}0TJ=L zk3aL{_w4)UBHBm}&);(mX=_hDh!bJ9KrwO^I{n^Cnhxbx8rt%Qk*V?LE=@@flwU5r z9NTqzQigOLqo(CS(G8Ie{T%`bDKHN2G!g7PbxG_}o@p}xj}u}eEioFYR0@GG0G&bb!P=tAF>tm2%S-f6WW5luh!U-Iii`S zd+UhM2bRNa8otS>I#fV%{)k&zb$m*F*zsyl&21+nnr)-PCCm$fyk+g`CsKRL%CyW)q_+FzpHz;C@%&>e*YSQhF4eh7Qu zOwo%(DFc0YH*GJY%-PBpB_1I2xShIfm;k>*3RL0bn5S8)2>i+IW(0N^H{|&|J8H@< znsYb-wTaFajmnvv4svozqYj`9I?*BU70Zc?^jdiOAoVhz6tW z#DH3?b=nxP3=$nRfYGq5*&ojE1QRB_d!R8onS;+?03Z`$_LN zdE(`}n>g`YU*8QC8wal-;OdagL*wZWwqkrAapJaMKtJ>QixX?-QIiKiJR-Jq72?OAzW(*+pML84-~8iG z+*R#h=~fn*Q1v<44jg2Zbm#GLFl zlk=i9V|b5YNrKFpk7dSUeon}FizAZXlm$zhVO=SNQPijTSb4*?VS@TyRj&_(Z`c8B8n=a-j0d;Rw7Pha`iXCJ=i z&3}0P>EWeEMYG?3;nnA_8NdIOc3{Xhd%Tn IbvPaV50135VgLXD From 5063095d8d58d77a57535d8be0ac57e09303c8aa Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Wed, 3 Oct 2018 01:35:12 -0400 Subject: [PATCH 251/428] Upgrade Composer dependencies --- composer.json | 4 +- composer.lock | 675 +++++++++++++++++++------------------------------- 2 files changed, 263 insertions(+), 416 deletions(-) diff --git a/composer.json b/composer.json index 68e5cae99b..a37010a9ef 100644 --- a/composer.json +++ b/composer.json @@ -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", @@ -37,8 +38,7 @@ "npm-asset/jgrowl": "^1.4", "npm-asset/fullcalendar": "^3.0.1", "npm-asset/cropperjs": "1.2.2", - "npm-asset/imagesloaded": "4.1.4", - "friendica/json-ld": "^1.0" + "npm-asset/imagesloaded": "4.1.4" }, "repositories": [ { diff --git a/composer.lock b/composer.lock index d8502c4d70..a07d56e692 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "ece71ff50417ed5fcc1a439ea554925c", + "content-hash": "c2306df3b19ec46d53bb16ac2cffa51a", "packages": [ { "name": "asika/simple-console", @@ -41,16 +41,16 @@ }, { "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", @@ -135,44 +135,133 @@ }, { "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/password_exposed", - "version": "v2.5.1", + "name": "divineomega/do-file-cache", + "version": "v2.0.2", "source": { "type": "git", - "url": "https://github.com/DivineOmega/password_exposed.git", - "reference": "c928bf722eb02398df11076add60df070cb55581" + "url": "https://github.com/DivineOmega/DO-File-Cache.git", + "reference": "261c6e30a0de8cd325f826d08b2e51b2e367a1a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/DivineOmega/password_exposed/zipball/c928bf722eb02398df11076add60df070cb55581", - "reference": "c928bf722eb02398df11076add60df070cb55581", + "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.3", + "source": { + "type": "git", + "url": "https://github.com/DivineOmega/password_exposed.git", + "reference": "1f1b49e3ec55b0f07115d342b145091368b081c4" + }, + "dist": { + "type": "zip", + "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", @@ -195,7 +284,7 @@ } ], "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", @@ -287,16 +376,16 @@ }, { "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": { @@ -304,7 +393,7 @@ "php": ">=5.3.3" }, "require-dev": { - "composer/composer": "^1.4.0" + "composer/composer": "^1.6.0" }, "type": "composer-plugin", "extra": { @@ -342,20 +431,20 @@ "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": { @@ -365,7 +454,7 @@ }, "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": { @@ -374,7 +463,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.2-dev" + "dev-master": "6.3-dev" } }, "autoload": { @@ -407,7 +496,7 @@ "rest", "web service" ], - "time": "2017-06-22T18:50:49+00:00" + "time": "2018-04-22T15:46:56+00:00" }, { "name": "guzzlehttp/promises", @@ -670,16 +759,16 @@ }, { "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": { @@ -718,7 +807,7 @@ "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", @@ -729,28 +818,6 @@ "reference": null, "shasum": "30dc7a7ce872155b23a33bd10ad4c76c0d613f55" }, - "require-dev": { - "npm-asset/babel-core": ">=6.26.0,<7.0.0", - "npm-asset/babel-plugin-external-helpers": ">=6.22.0,<7.0.0", - "npm-asset/babel-preset-env": ">=1.6.1,<2.0.0", - "npm-asset/cpy-cli": ">=1.0.1,<2.0.0", - "npm-asset/cssnano": ">=3.10.0,<4.0.0", - "npm-asset/del-cli": ">=1.1.0,<2.0.0", - "npm-asset/eslint": ">=4.14.0,<5.0.0", - "npm-asset/eslint-config-airbnb-base": ">=12.1.0,<13.0.0", - "npm-asset/eslint-plugin-import": ">=2.8.0,<3.0.0", - "npm-asset/node-qunit-phantomjs": ">=2.0.0,<3.0.0", - "npm-asset/npm-run-all": ">=4.1.2,<5.0.0", - "npm-asset/postcss-cli": ">=4.1.1,<5.0.0", - "npm-asset/postcss-cssnext": ">=3.0.2,<4.0.0", - "npm-asset/postcss-header": ">=1.0.0,<2.0.0", - "npm-asset/postcss-url": ">=7.3.0,<8.0.0", - "npm-asset/rollup": ">=0.53.3,<0.54.0", - "npm-asset/rollup-plugin-babel": ">=3.0.3,<4.0.0", - "npm-asset/rollup-watch": ">=4.3.1,<5.0.0", - "npm-asset/stylefmt": ">=6.0.0,<7.0.0", - "npm-asset/uglify-js": ">=3.3.4,<4.0.0" - }, "type": "npm-asset-library", "extra": { "npm-asset-bugs": { @@ -859,67 +926,16 @@ }, { "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": { @@ -967,7 +983,7 @@ "full-sized", "jquery-plugin" ], - "time": "2018-01-30T23:49:01+00:00" + "time": "2018-03-05T03:30:23+00:00" }, { "name": "npm-asset/imagesloaded", @@ -981,22 +997,6 @@ "require": { "npm-asset/ev-emitter": ">=1.0.0,<2.0.0" }, - "require-dev": { - "npm-asset/chalk": ">=1.1.1,<2.0.0", - "npm-asset/cheerio": ">=0.19.0,<0.20.0", - "npm-asset/gulp": ">=3.9.0,<4.0.0", - "npm-asset/gulp-jshint": ">=1.11.2,<2.0.0", - "npm-asset/gulp-json-lint": ">=0.1.0,<0.2.0", - "npm-asset/gulp-rename": ">=1.2.2,<2.0.0", - "npm-asset/gulp-replace": ">=0.5.4,<0.6.0", - "npm-asset/gulp-requirejs-optimize": "dev-github:metafizzy/gulp-requirejs-optimize", - "npm-asset/gulp-uglify": ">=1.4.2,<2.0.0", - "npm-asset/gulp-util": ">=3.0.7,<4.0.0", - "npm-asset/highlight.js": ">=8.9.1,<9.0.0", - "npm-asset/marked": ">=0.3.5,<0.4.0", - "npm-asset/minimist": ">=1.2.0,<2.0.0", - "npm-asset/transfob": ">=1.0.0,<2.0.0" - }, "type": "npm-asset-library", "extra": { "npm-asset-bugs": { @@ -1042,14 +1042,6 @@ "reference": null, "shasum": "2736e332aaee73ccf0a14a5f0066391a0a13f4a3" }, - "require-dev": { - "npm-asset/grunt": "~0.4.2", - "npm-asset/grunt-contrib-cssmin": "~0.9.0", - "npm-asset/grunt-contrib-jshint": "~0.6.3", - "npm-asset/grunt-contrib-less": "~0.11.0", - "npm-asset/grunt-contrib-uglify": "~0.4.0", - "npm-asset/grunt-contrib-watch": "~0.6.1" - }, "type": "npm-asset-library", "extra": { "npm-asset-bugs": { @@ -1083,32 +1075,6 @@ "reference": null, "shasum": "2c89d6889b5eac522a7eea32c14521559c6cbf02" }, - "require-dev": { - "npm-asset/commitplease": "2.0.0", - "npm-asset/core-js": "0.9.17", - "npm-asset/grunt": "0.4.5", - "npm-asset/grunt-babel": "5.0.1", - "npm-asset/grunt-cli": "0.1.13", - "npm-asset/grunt-compare-size": "0.4.0", - "npm-asset/grunt-contrib-jshint": "0.11.2", - "npm-asset/grunt-contrib-uglify": "0.9.2", - "npm-asset/grunt-contrib-watch": "0.6.1", - "npm-asset/grunt-git-authors": "2.0.1", - "npm-asset/grunt-jscs": "2.1.0", - "npm-asset/grunt-jsonlint": "1.0.4", - "npm-asset/grunt-npmcopy": "0.1.0", - "npm-asset/gzip-js": "0.3.2", - "npm-asset/jsdom": "5.6.1", - "npm-asset/load-grunt-tasks": "1.0.0", - "npm-asset/qunit-assert-step": "1.0.3", - "npm-asset/qunitjs": "1.17.1", - "npm-asset/requirejs": "2.1.17", - "npm-asset/sinon": "1.10.3", - "npm-asset/sizzle": "2.2.1", - "npm-asset/strip-json-comments": "1.0.3", - "npm-asset/testswarm": "1.1.0", - "npm-asset/win-spawn": "2.0.0" - }, "type": "npm-asset-library", "extra": { "npm-asset-bugs": { @@ -1194,24 +1160,18 @@ }, { "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": { @@ -1224,13 +1184,13 @@ "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": [ @@ -1240,7 +1200,7 @@ { "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", @@ -1254,7 +1214,7 @@ "time", "timepicker" ], - "time": "2018-01-23T05:56:50+00:00" + "time": "2018-03-21T16:26:39+00:00" }, { "name": "npm-asset/jquery-mousewheel", @@ -1265,12 +1225,6 @@ "reference": null, "shasum": "06f0335f16e353a695e7206bf50503cb523a6ee5" }, - "require-dev": { - "npm-asset/grunt": "~0.4.1", - "npm-asset/grunt-contrib-connect": "~0.5.0", - "npm-asset/grunt-contrib-jshint": "~0.7.1", - "npm-asset/grunt-contrib-uglify": "~0.2.7" - }, "type": "npm-asset-library", "extra": { "npm-asset-bugs": { @@ -1313,45 +1267,12 @@ }, { "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": { @@ -1421,16 +1342,21 @@ "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": { @@ -1443,35 +1369,31 @@ }, "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 " ], "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": { @@ -1518,29 +1440,29 @@ "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": { @@ -1581,20 +1503,20 @@ "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": { @@ -1626,27 +1548,28 @@ "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": { @@ -1711,7 +1634,7 @@ "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", @@ -1853,94 +1776,6 @@ ], "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", @@ -1991,16 +1826,16 @@ }, { "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": { @@ -2040,7 +1875,7 @@ "keywords": [ "templating" ], - "time": "2016-12-14T21:57:25+00:00" + "time": "2018-09-12T20:54:16+00:00" } ], "packages-dev": [ @@ -2189,53 +2024,6 @@ ], "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", @@ -2384,16 +2172,16 @@ }, { "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": { @@ -2405,12 +2193,12 @@ }, "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": { @@ -2443,7 +2231,7 @@ "spy", "stub" ], - "time": "2018-04-18T13:57:24+00:00" + "time": "2018-08-05T17:53:17+00:00" }, { "name": "phpunit/dbunit", @@ -3404,21 +3192,80 @@ "time": "2016-10-03T07:35:21+00:00" }, { - "name": "symfony/yaml", - "version": "v3.4.8", + "name": "symfony/polyfill-ctype", + "version": "v1.9.0", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/a42f9da85c7c38d59f5e53f076fe81a091f894d0", - "reference": "a42f9da85c7c38d59f5e53f076fe81a091f894d0", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "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.16", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "61973ecda60e9f3561e929e19c07d4878b960fc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/61973ecda60e9f3561e929e19c07d4878b960fc1", + "reference": "61973ecda60e9f3561e929e19c07d4878b960fc1", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8" }, "conflict": { "symfony/console": "<3.4" @@ -3459,7 +3306,7 @@ ], "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", From 4d2e5c2bbee82abd80c566051024aa33440ab805 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 3 Oct 2018 06:15:07 +0000 Subject: [PATCH 252/428] AP class will be split in processor, receiver and transmitter --- src/Module/Followers.php | 2 +- src/Module/Following.php | 2 +- src/Module/Outbox.php | 2 +- src/Protocol/ActivityPub.php | 142 ---- src/Protocol/ActivityPub/Processor.php | 476 +++++++++++++ src/Protocol/ActivityPub/Receiver.php | 596 ++++++++++++++++ src/Protocol/ActivityPub/Transmitter.php | 831 +++++++++++++++++++++++ 7 files changed, 1906 insertions(+), 145 deletions(-) create mode 100644 src/Protocol/ActivityPub/Processor.php create mode 100644 src/Protocol/ActivityPub/Receiver.php create mode 100644 src/Protocol/ActivityPub/Transmitter.php diff --git a/src/Module/Followers.php b/src/Module/Followers.php index 98e9f1e0ee..56160aecf8 100644 --- a/src/Module/Followers.php +++ b/src/Module/Followers.php @@ -29,7 +29,7 @@ class Followers extends BaseModule $page = defaults($_REQUEST, 'page', null); - $followers = ActivityPub::getFollowers($owner, $page); + $followers = ActivityPub\Transmitter::getFollowers($owner, $page); header('Content-Type: application/activity+json'); echo json_encode($followers); diff --git a/src/Module/Following.php b/src/Module/Following.php index 6023db4cbe..71e6613f0c 100644 --- a/src/Module/Following.php +++ b/src/Module/Following.php @@ -29,7 +29,7 @@ class Following extends BaseModule $page = defaults($_REQUEST, 'page', null); - $Following = ActivityPub::getFollowing($owner, $page); + $Following = ActivityPub\Transmitter::getFollowing($owner, $page); header('Content-Type: application/activity+json'); echo json_encode($Following); diff --git a/src/Module/Outbox.php b/src/Module/Outbox.php index f6bad56dd6..681d1cccb1 100644 --- a/src/Module/Outbox.php +++ b/src/Module/Outbox.php @@ -29,7 +29,7 @@ class Outbox extends BaseModule $page = defaults($_REQUEST, 'page', null); - $outbox = ActivityPub::getOutbox($owner, $page); + $outbox = ActivityPub\Transmitter::getOutbox($owner, $page); header('Content-Type: application/activity+json'); echo json_encode($outbox); diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index ef4a48479e..a9f3217f9e 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -92,148 +92,6 @@ class ActivityPub stristr(defaults($_SERVER, 'HTTP_ACCEPT', ''), 'application/ld+json'); } - /** - * @brief 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' => self::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; - } - - /** - * @brief 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' => self::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; - } - - /** - * @brief 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' => $owner['uid'], 'contact-id' => $owner['id'], 'author-id' => $public_contact, - 'wall' => true, 'private' => false, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT], - 'deleted' => false, 'visible' => true]; - $count = DBA::count('item', $condition); - - $data = ['@context' => self::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 * diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php new file mode 100644 index 0000000000..bbf4d7b801 --- /dev/null +++ b/src/Protocol/ActivityPub/Processor.php @@ -0,0 +1,476 @@ + $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, $body); + } + + /** + * @brief + * + * @param array $activity + * @param $body + */ + private static function likeItem($activity, $body) + { + $item = []; + $item['verb'] = ACTIVITY_LIKE; + $item['parent-uri'] = $activity['object']; + $item['gravity'] = GRAVITY_ACTIVITY; + $item['object-type'] = ACTIVITY_OBJ_NOTE; + + self::postItem($activity, $item, $body); + } + + /** + * @brief Delete items + * + * @param array $activity + * @param $body + */ + private static function deleteItem($activity) + { + $owner = Contact::getIdForURL($activity['owner']); + $object = JsonLD::fetchElement($activity, 'object', 'id'); + logger('Deleting item ' . $object . ' from ' . $owner, LOGGER_DEBUG); + Item::delete(['uri' => $object, 'owner-id' => $owner]); + } + + /** + * @brief + * + * @param array $activity + * @param $body + */ + private static function dislikeItem($activity, $body) + { + $item = []; + $item['verb'] = ACTIVITY_DISLIKE; + $item['parent-uri'] = $activity['object']; + $item['gravity'] = GRAVITY_ACTIVITY; + $item['object-type'] = ACTIVITY_OBJ_NOTE; + + self::postItem($activity, $item, $body); + } + + /** + * @brief + * + * @param array $activity + * @param array $item + * @param $body + */ + private static function postItem($activity, $item, $body) + { + /// @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-id'] = Contact::getIdForURL($activity['author'], 0, true); + $item['owner-id'] = Contact::getIdForURL($activity['owner'], 0, true); + $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'])); + $item['location'] = $activity['location']; + $item['tag'] = self::constructTagList($activity['tags'], $activity['sensitive']); + $item['app'] = $activity['service']; + $item['plink'] = defaults($activity, 'alternate-url', $item['uri']); + + $item = self::constructAttachList($activity['attachments'], $item); + + $source = JsonLD::fetchElement($activity, 'source', 'content', 'mediaType', 'text/bbcode'); + if (!empty($source)) { + $item['body'] = $source; + } + + $item['protocol'] = Conversation::PARCEL_ACTIVITYPUB; + $item['source'] = $body; + $item['conversation-href'] = $activity['context']; + $item['conversation-uri'] = $activity['conversation']; + + 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); + } + } + + /** + * @brief + * + * @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'; + + ActivityPub::processActivity($activity); + logger('Activity ' . $url . ' had been fetched and processed.'); + } + + /** + * @brief perform a "follow" request + * + * @param array $activity + */ + private static function followUser($activity) + { + $actor = JsonLD::fetchElement($activity, 'object', 'id'); + $uid = User::getIdForURL($actor); + if (empty($uid)) { + return; + } + + $owner = User::getOwnerDataById($uid); + + $cid = Contact::getIdForURL($activity['owner'], $uid); + if (!empty($cid)) { + $contact = DBA::selectFirst('contact', [], ['id' => $cid]); + } else { + $contact = false; + } + + $item = ['author-id' => Contact::getIdForURL($activity['owner']), + 'author-link' => $activity['owner']]; + + Contact::addRelationship($owner, $contact, $item); + $cid = Contact::getIdForURL($activity['owner'], $uid); + if (empty($cid)) { + return; + } + + $contact = DBA::selectFirst('contact', ['network'], ['id' => $cid]); + if ($contact['network'] != Protocol::ACTIVITYPUB) { + Contact::updateFromProbe($cid, Protocol::ACTIVITYPUB); + } + + DBA::update('contact', ['hub-verify' => $activity['id']], ['id' => $cid]); + logger('Follow user ' . $uid . ' from contact ' . $cid . ' with id ' . $activity['id']); + } + + /** + * @brief Update the given profile + * + * @param array $activity + */ + private 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); + } + + /** + * @brief Delete the given profile + * + * @param array $activity + */ + private static function deletePerson($activity) + { + if (empty($activity['object']['id']) || empty($activity['object']['actor'])) { + logger('Empty object id or actor.', LOGGER_DEBUG); + return; + } + + if ($activity['object']['id'] != $activity['object']['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); + } + + /** + * @brief Accept a follow request + * + * @param array $activity + */ + private static function acceptFollowUser($activity) + { + $actor = JsonLD::fetchElement($activity, 'object', 'actor'); + $uid = User::getIdForURL($actor); + if (empty($uid)) { + return; + } + + $owner = User::getOwnerDataById($uid); + + $cid = Contact::getIdForURL($activity['owner'], $uid); + if (empty($cid)) { + logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); + return; + } + + $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); + } + + /** + * @brief Reject a follow request + * + * @param array $activity + */ + private static function rejectFollowUser($activity) + { + $actor = JsonLD::fetchElement($activity, 'object', 'actor'); + $uid = User::getIdForURL($actor); + if (empty($uid)) { + return; + } + + $owner = User::getOwnerDataById($uid); + + $cid = Contact::getIdForURL($activity['owner'], $uid); + if (empty($cid)) { + logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); + return; + } + + 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); + } + } + + /** + * @brief Undo activity like "like" or "dislike" + * + * @param array $activity + */ + private static function undoActivity($activity) + { + $activity_url = JsonLD::fetchElement($activity, 'object', 'id'); + if (empty($activity_url)) { + return; + } + + $actor = JsonLD::fetchElement($activity, 'object', 'actor'); + if (empty($actor)) { + return; + } + + $author_id = Contact::getIdForURL($actor); + if (empty($author_id)) { + return; + } + + Item::delete(['uri' => $activity_url, 'author-id' => $author_id, 'gravity' => GRAVITY_ACTIVITY]); + } + + /** + * @brief Activity to remove a follower + * + * @param array $activity + */ + private static function undoFollowUser($activity) + { + $object = JsonLD::fetchElement($activity, 'object', 'object'); + $uid = User::getIdForURL($object); + if (empty($uid)) { + return; + } + + $owner = User::getOwnerDataById($uid); + + $cid = Contact::getIdForURL($activity['owner'], $uid); + if (empty($cid)) { + logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); + return; + } + + $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); + } +} diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php new file mode 100644 index 0000000000..171771748e --- /dev/null +++ b/src/Protocol/ActivityPub/Receiver.php @@ -0,0 +1,596 @@ + $uid]; + $receivers = array_merge($receivers, $additional); + } + + logger('Receivers: ' . json_encode($receivers), LOGGER_DEBUG); + + $object_id = JsonLD::fetchElement($activity, 'object', 'id'); + if (empty($object_id)) { + logger('No object found', LOGGER_DEBUG); + return []; + } + + // Fetch the content only on activities where this matters + if (in_array($activity['type'], ['Create', 'Announce'])) { + $object_data = ActivityPub::fetchObject($object_id, $activity['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($activity['type'], ['Like', '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 = ActivityPub::processObject($activity); + $object_data['name'] = $activity['type']; + $object_data['author'] = $activity['actor']; + $object_data['object'] = $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'] = $activity['id']; + $object_data['object'] = $activity['object']; + $object_data['object_type'] = JsonLD::fetchElement($activity, 'object', 'type'); + } + + $object_data = ActivityPub::addActivityFields($object_data, $activity); + + $object_data['type'] = $activity['type']; + $object_data['owner'] = $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; + } + + /** + * @brief + * + * @param array $activity + * @param $body + * @param integer $uid User ID + * @param $trust_source + */ + private static function processActivity($activity, $body = '', $uid = null, $trust_source = false) + { + if (empty($activity['type'])) { + logger('Empty type', LOGGER_DEBUG); + return; + } + + if (empty($activity['object'])) { + logger('Empty object', LOGGER_DEBUG); + return; + } + + if (empty($activity['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 = ActivityPub::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 "' . $activity['type'] . '", so we quit now.', LOGGER_DEBUG); + } + + switch ($activity['type']) { + case 'Create': + case 'Announce': + ActivityPub::createItem($object_data, $body); + break; + + case 'Like': + ActivityPub::likeItem($object_data, $body); + break; + + case 'Dislike': + ActivityPub::dislikeItem($object_data, $body); + break; + + case 'Update': + if (in_array($object_data['object_type'], ActivityPub::CONTENT_TYPES)) { + /// @todo + } elseif (in_array($object_data['object_type'], ActivityPub::ACCOUNT_TYPES)) { + ActivityPub::updatePerson($object_data, $body); + } + break; + + case 'Delete': + if ($object_data['object_type'] == 'Tombstone') { + ActivityPub::deleteItem($object_data, $body); + } elseif (in_array($object_data['object_type'], ActivityPub::ACCOUNT_TYPES)) { + ActivityPub::deletePerson($object_data, $body); + } + break; + + case 'Follow': + ActivityPub::followUser($object_data); + break; + + case 'Accept': + if ($object_data['object_type'] == 'Follow') { + ActivityPub::acceptFollowUser($object_data); + } + break; + + case 'Reject': + if ($object_data['object_type'] == 'Follow') { + ActivityPub::rejectFollowUser($object_data); + } + break; + + case 'Undo': + if ($object_data['object_type'] == 'Follow') { + ActivityPub::undoFollowUser($object_data); + } elseif (in_array($object_data['object_type'], ActivityPub::ACTIVITY_TYPES)) { + ActivityPub::undoActivity($object_data); + } + break; + + default: + logger('Unknown activity: ' . $activity['type'], LOGGER_DEBUG); + break; + } + } + + /** + * @brief + * + * @param array $activity + * @param $actor + * + * @return + */ + private static function getReceivers($activity, $actor) + { + $receivers = []; + + // When it is an answer, we inherite the receivers from the parent + $replyto = JsonLD::fetchElement($activity, 'inReplyTo', 'id'); + 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 (['to', 'cc', 'bto', 'bcc'] as $element) { + if (empty($activity[$element])) { + continue; + } + + // The receiver can be an array or a string + if (is_string($activity[$element])) { + $activity[$element] = [$activity[$element]]; + } + + foreach ($activity[$element] as $receiver) { + if ($receiver == ActivityPub::PUBLIC_COLLECTION) { + $receivers['uid:0'] = 0; + } + + if (($receiver == ActivityPub::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, ActivityPub::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']; + } + } + + ActivityPub::switchContacts($receivers, $actor); + + return $receivers; + } + + /** + * @brief + * + * @param $cid + * @param integer $uid User ID + * @param $url + */ + private static function switchContact($cid, $uid, $url) + { + $profile = ActivityPub::probeProfile($url); + if (empty($profile)) { + return; + } + + logger('Switch contact ' . $cid . ' (' . $profile['url'] . ') for user ' . $uid . ' from OStatus 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); + } + + /** + * @brief + * + * @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)) { + ActivityPub::switchContact($contact['id'], $receiver, $actor); + } + + $contact = DBA::selectFirst('contact', ['id'], ['uid' => $receiver, 'network' => Protocol::OSTATUS, 'alias' => [normalise_link($actor), $actor]]); + if (DBA::isResult($contact)) { + ActivityPub::switchContact($contact['id'], $receiver, $actor); + } + } + } + + /** + * @brief + * + * @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'] = $activity['published']; + } + + if (!empty($activity['updated']) && empty($object_data['updated'])) { + $object_data['updated'] = $activity['updated']; + } + + if (!empty($activity['inReplyTo']) && empty($object_data['parent-uri'])) { + $object_data['parent-uri'] = JsonLD::fetchElement($activity, 'inReplyTo', 'id'); + } + + if (!empty($activity['instrument'])) { + $object_data['service'] = JsonLD::fetchElement($activity, 'instrument', 'name', 'type', 'Service'); + } + return $object_data; + } + + /** + * @brief + * + * @param $object_id + * @param $object + * @param $trust_source + * + * @return + */ + private static function fetchObject($object_id, $object = [], $trust_source = false) + { + if (!$trust_source || is_string($object)) { + $data = ActivityPub::fetchContent($object_id); + if (empty($data)) { + logger('Empty content for ' . $object_id . ', check if content is available locally.', LOGGER_DEBUG); + $data = $object_id; + } else { + logger('Fetched content for ' . $object_id, LOGGER_DEBUG); + } + } else { + logger('Using original object for url ' . $object_id, LOGGER_DEBUG); + $data = $object; + } + + if (is_string($data)) { + $item = Item::selectFirst([], ['uri' => $data]); + if (!DBA::isResult($item)) { + logger('Object with url ' . $data . ' was not found locally.', LOGGER_DEBUG); + return false; + } + logger('Using already stored item for url ' . $object_id, LOGGER_DEBUG); + $data = ActivityPub::createNote($item); + } + + if (empty($data['type'])) { + logger('Empty type', LOGGER_DEBUG); + return false; + } + + if (in_array($data['type'], ActivityPub::CONTENT_TYPES)) { + return ActivityPub::processObject($data); + } + + if ($data['type'] == 'Announce') { + if (empty($data['object'])) { + return false; + } + return ActivityPub::fetchObject($data['object']); + } + + logger('Unhandled object type: ' . $data['type'], LOGGER_DEBUG); + } + + /** + * @brief + * + * @param $object + * + * @return + */ + private static function processObject($object) + { + if (empty($object['id'])) { + return false; + } + + $object_data = []; + $object_data['object_type'] = $object['type']; + $object_data['id'] = $object['id']; + + if (!empty($object['inReplyTo'])) { + $object_data['reply-to-id'] = JsonLD::fetchElement($object, 'inReplyTo', 'id'); + } else { + $object_data['reply-to-id'] = $object_data['id']; + } + + $object_data['published'] = defaults($object, 'published', null); + $object_data['updated'] = defaults($object, 'updated', $object_data['published']); + + if (empty($object_data['published']) && !empty($object_data['updated'])) { + $object_data['published'] = $object_data['updated']; + } + + $actor = JsonLD::fetchElement($object, 'attributedTo', 'id'); + if (empty($actor)) { + $actor = defaults($object, 'actor', null); + } + + $object_data['diaspora:guid'] = defaults($object, 'diaspora:guid', null); + $object_data['owner'] = $object_data['author'] = $actor; + $object_data['context'] = defaults($object, 'context', null); + $object_data['conversation'] = defaults($object, 'conversation', null); + $object_data['sensitive'] = defaults($object, 'sensitive', null); + $object_data['name'] = defaults($object, 'title', null); + $object_data['name'] = defaults($object, 'name', $object_data['name']); + $object_data['summary'] = defaults($object, 'summary', null); + $object_data['content'] = defaults($object, 'content', null); + $object_data['source'] = defaults($object, 'source', null); + $object_data['location'] = JsonLD::fetchElement($object, 'location', 'name', 'type', 'Place'); + $object_data['attachments'] = defaults($object, 'attachment', null); + $object_data['tags'] = defaults($object, 'tag', null); + $object_data['service'] = JsonLD::fetchElement($object, 'instrument', 'name', 'type', 'Service'); + $object_data['alternate-url'] = JsonLD::fetchElement($object, 'url', 'href'); + $object_data['receiver'] = ActivityPub::getReceivers($object, $object_data['owner']); + + // 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, generator, 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; + } + + /** + * @brief + * + * @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'; + + ActivityPub::processActivity($activity); + logger('Activity ' . $url . ' had been fetched and processed.'); + } +} diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php new file mode 100644 index 0000000000..7155d83094 --- /dev/null +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -0,0 +1,831 @@ + [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; + } + + /** + * @brief 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; + } + + /** + * @brief 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' => $owner['uid'], 'contact-id' => $owner['id'], 'author-id' => $public_contact, + 'wall' => true, '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 profile array + */ + public static function profile($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']; + $contact = DBA::selectFirst('contact', $fields, ['uid' => $uid, 'self' => true]); + if (!DBA::isResult($contact)) { + return []; + } + + $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; + } + + /** + * @brief 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; + } + + /** + * @brief Creates an array of permissions from an item thread + * + * @param array $item + * + * @return permission array + */ + public 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['cc'][] = $profile['url']; + $contacts[$profile['url']] = $profile['url']; + } + } + } 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']; + } + } + + 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'], ['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) && 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 (empty($data['to'])) { + $data['to'] = $data['cc']; + $data['cc'] = []; + } + + return $data; + } + + /** + * @brief 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; + } + + /** + * @brief 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; + } + + /** + * @brief Returns the activity type of a given item + * + * @param array $item + * + * @return activity type + */ + public static function getTypeOfItem($item) + { + if ($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; + } + + /** + * @brief 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['author-link']; + + $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['context'] = self::fetchContextURLForItem($item); + + $data = array_merge($data, self::createPermissionBlockForItem($item)); + + if (in_array($data['type'], ['Create', 'Update', 'Announce', 'Delete'])) { + $data['object'] = self::createNote($item); + } elseif ($data['type'] == 'Undo') { + $data['object'] = self::createActivityFromItem($item_id, true); + } else { + $data['object'] = $item['thr-parent']; + } + + $owner = User::getOwnerDataById($item['uid']); + + if (!$object_mode) { + return LDSignature::sign($data, $owner); + } else { + return $data; + } + } + + /** + * @brief Creates an object array for a given item id + * + * @param integer $item_id + * + * @return object array + */ + 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; + } + + /** + * @brief 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'], TERM_MENTION); + foreach ($terms as $term) { + $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; + } + + /** + * @brief 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 = str_replace('/objects/', '/context/', $item['parent-uri']); + } + return $context_uri; + } + + /** + * @brief Creates a note/article object array + * + * @param array $item + * + * @return object array + */ + private 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['actor'] = $item['author-link']; + $data['sensitive'] = false; // - Query NSFW + $data['context'] = self::fetchContextURLForItem($item); + + if (!empty($item['title'])) { + $data['name'] = BBCode::convert($item['title'], false, 7); + } + + $data['content'] = BBCode::convert($item['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'] = []; // @ToDo + $data['tag'] = self::createTagList($item); + $data = array_merge($data, self::createPermissionBlockForItem($item)); + + return $data; + } + + /** + * @brief Transmits a profile deletion to a given inbox + * + * @param integer $uid User ID + * @param string $inbox Target inbox + */ + public static function transmitProfileDeletion($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' => self::profile($uid), + 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), + '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); + } + + /** + * @brief Transmits a profile change to a given inbox + * + * @param integer $uid User ID + * @param string $inbox Target inbox + */ + public static function transmitProfileUpdate($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::profile($uid), + 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), + '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); + } + + /** + * @brief Transmits a given activity to a target + * + * @param array $activity + * @param string $target Target profile + * @param integer $uid User ID + */ + public static function transmitActivity($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'], + '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); + } + + /** + * @brief 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 transmitContactAccept($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']], + '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); + } + + /** + * @brief + * + * @param string $target Target profile + * @param $id + * @param integer $uid User ID + */ + public static function transmitContactReject($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']], + '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); + } + + /** + * @brief + * + * @param string $target Target profile + * @param integer $uid User ID + */ + public static function transmitContactUndo($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']], + '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); + } +} From 3ab837f3c783e14e2c8836e73c898041c47f2fd0 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 3 Oct 2018 09:15:38 +0000 Subject: [PATCH 253/428] Functionality is now split --- include/api.php | 31 +- mod/dfrn_confirm.php | 4 +- mod/profile.php | 2 +- src/Model/Contact.php | 8 +- src/Module/Inbox.php | 2 +- src/Module/Objects.php | 2 +- src/Protocol/ActivityPub.php | 1624 +--------------------- src/Protocol/ActivityPub/Processor.php | 24 +- src/Protocol/ActivityPub/Receiver.php | 83 +- src/Protocol/ActivityPub/Transmitter.php | 4 +- src/Worker/APDelivery.php | 6 +- src/Worker/Notifier.php | 6 +- src/Worker/ProfileUpdate.php | 2 +- 13 files changed, 71 insertions(+), 1727 deletions(-) diff --git a/include/api.php b/include/api.php index 004388ac46..cab0290de3 100644 --- a/include/api.php +++ b/include/api.php @@ -4844,70 +4844,69 @@ function api_share_as_retweet(&$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]; } diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php index 90d3d8990c..9bd9339ed7 100644 --- a/mod/dfrn_confirm.php +++ b/mod/dfrn_confirm.php @@ -337,7 +337,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) ); } else { if ($network == Protocol::ACTIVITYPUB) { - ActivityPub::transmitContactAccept($contact['url'], $contact['hub-verify'], $uid); + ActivityPub\Transmitter::transmitContactAccept($contact['url'], $contact['hub-verify'], $uid); $pending = true; } else { $pending = false; @@ -394,7 +394,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) Group::addMember(User::getDefaultGroup($uid, $contact["network"]), $contact['id']); if ($network == Protocol::ACTIVITYPUB && $duplex) { - ActivityPub::transmitActivity('Follow', $contact['url'], $uid); + ActivityPub\Transmitter::transmitActivity('Follow', $contact['url'], $uid); } // Let's send our user to the contact editor in case they want to diff --git a/mod/profile.php b/mod/profile.php index e20836a059..729f11028a 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -53,7 +53,7 @@ function profile_init(App $a) if (ActivityPub::isRequest()) { $user = DBA::selectFirst('user', ['uid'], ['nickname' => $which]); if (DBA::isResult($user)) { - $data = ActivityPub::profile($user['uid']); + $data = ActivityPub\Transmitter::profile($user['uid']); echo json_encode($data); header('Content-Type: application/activity+json'); exit(); diff --git a/src/Model/Contact.php b/src/Model/Contact.php index b6b7081626..c7513567ac 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -557,10 +557,10 @@ class Contact extends BaseObject } elseif ($contact['network'] == Protocol::DIASPORA) { Diaspora::sendUnshare($user, $contact); } elseif ($contact['network'] == Protocol::ACTIVITYPUB) { - ActivityPub::transmitContactUndo($contact['url'], $user['uid']); + ActivityPub\Transmitter::transmitContactUndo($contact['url'], $user['uid']); if ($dissolve) { - ActivityPub::transmitContactReject($contact['url'], $contact['hub-verify'], $user['uid']); + ActivityPub\Transmitter::transmitContactReject($contact['url'], $contact['hub-verify'], $user['uid']); } } } @@ -1769,7 +1769,7 @@ class Contact extends BaseObject $ret = Diaspora::sendShare($a->user, $contact); logger('share returns: ' . $ret); } elseif ($contact['network'] == Protocol::ACTIVITYPUB) { - $ret = ActivityPub::transmitActivity('Follow', $contact['url'], $uid); + $ret = ActivityPub\Transmitter::transmitActivity('Follow', $contact['url'], $uid); logger('Follow returns: ' . $ret); } } @@ -1846,7 +1846,7 @@ class Contact extends BaseObject } if ($contact['network'] == Protocol::ACTIVITYPUB) { - ActivityPub::transmitContactAccept($contact['url'], $contact['hub-verify'], $importer['uid']); + ActivityPub\Transmitter::transmitContactAccept($contact['url'], $contact['hub-verify'], $importer['uid']); } // send email notification to owner? diff --git a/src/Module/Inbox.php b/src/Module/Inbox.php index c97c3b7afb..c190be4d1f 100644 --- a/src/Module/Inbox.php +++ b/src/Module/Inbox.php @@ -48,7 +48,7 @@ class Inbox extends BaseModule $uid = 0; } - ActivityPub::processInbox($postdata, $_SERVER, $uid); + ActivityPub\Receiver::processInbox($postdata, $_SERVER, $uid); System::httpExit(202); } diff --git a/src/Module/Objects.php b/src/Module/Objects.php index c52a75196a..ba9dace2e5 100644 --- a/src/Module/Objects.php +++ b/src/Module/Objects.php @@ -32,7 +32,7 @@ class Objects extends BaseModule System::httpExit(404); } - $data = ActivityPub::createObjectFromItemID($item['id']); + $data = ActivityPub\Transmitter::createObjectFromItemID($item['id']); header('Content-Type: application/activity+json'); echo json_encode($data); diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index a9f3217f9e..c84f5d3ee4 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -92,666 +92,6 @@ class ActivityPub stristr(defaults($_SERVER, 'HTTP_ACCEPT', ''), 'application/ld+json'); } - /** - * Return the ActivityPub profile of the given user - * - * @param integer $uid User ID - * @return profile array - */ - public static function profile($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']; - $contact = DBA::selectFirst('contact', $fields, ['uid' => $uid, 'self' => true]); - if (!DBA::isResult($contact)) { - return []; - } - - $data = ['@context' => self::CONTEXT]; - $data['id'] = $contact['url']; - $data['diaspora:guid'] = $user['guid']; - $data['type'] = self::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; - } - - /** - * @brief 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; - } - - /** - * @brief Creates an array of permissions from an item thread - * - * @param array $item - * - * @return permission array - */ - public 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'][] = self::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['cc'][] = $profile['url']; - $contacts[$profile['url']] = $profile['url']; - } - } - } 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']; - } - } - - 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'], ['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) && 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 (empty($data['to'])) { - $data['to'] = $data['cc']; - $data['cc'] = []; - } - - return $data; - } - - /** - * @brief 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; - } - - /** - * @brief 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; - } - - /** - * @brief Returns the activity type of a given item - * - * @param array $item - * - * @return activity type - */ - public static function getTypeOfItem($item) - { - if ($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; - } - - /** - * @brief 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' => self::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['author-link']; - - $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['context'] = self::fetchContextURLForItem($item); - - $data = array_merge($data, ActivityPub::createPermissionBlockForItem($item)); - - if (in_array($data['type'], ['Create', 'Update', 'Announce', 'Delete'])) { - $data['object'] = self::createNote($item); - } elseif ($data['type'] == 'Undo') { - $data['object'] = self::createActivityFromItem($item_id, true); - } else { - $data['object'] = $item['thr-parent']; - } - - $owner = User::getOwnerDataById($item['uid']); - - if (!$object_mode) { - return LDSignature::sign($data, $owner); - } else { - return $data; - } - } - - /** - * @brief Creates an object array for a given item id - * - * @param integer $item_id - * - * @return object array - */ - 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' => self::CONTEXT]; - $data = array_merge($data, self::createNote($item)); - - return $data; - } - - /** - * @brief 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'], TERM_MENTION); - foreach ($terms as $term) { - $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; - } - - /** - * @brief 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 = str_replace('/objects/', '/context/', $item['parent-uri']); - } - return $context_uri; - } - - /** - * @brief Creates a note/article object array - * - * @param array $item - * - * @return object array - */ - private 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['actor'] = $item['author-link']; - $data['sensitive'] = false; // - Query NSFW - $data['context'] = self::fetchContextURLForItem($item); - - if (!empty($item['title'])) { - $data['name'] = BBCode::convert($item['title'], false, 7); - } - - $data['content'] = BBCode::convert($item['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'] = []; // @ToDo - $data['tag'] = self::createTagList($item); - $data = array_merge($data, ActivityPub::createPermissionBlockForItem($item)); - - return $data; - } - - /** - * @brief Transmits a profile deletion to a given inbox - * - * @param integer $uid User ID - * @param string $inbox Target inbox - */ - public static function transmitProfileDeletion($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' => self::profile($uid), - 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), - 'to' => [self::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); - } - - /** - * @brief Transmits a profile change to a given inbox - * - * @param integer $uid User ID - * @param string $inbox Target inbox - */ - public static function transmitProfileUpdate($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::profile($uid), - 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), - '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); - } - - /** - * @brief Transmits a given activity to a target - * - * @param array $activity - * @param string $target Target profile - * @param integer $uid User ID - */ - public static function transmitActivity($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'], - '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); - } - - /** - * @brief 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 transmitContactAccept($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']], - '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); - } - - /** - * @brief - * - * @param string $target Target profile - * @param $id - * @param integer $uid User ID - */ - public static function transmitContactReject($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']], - '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); - } - - /** - * @brief - * - * @param string $target Target profile - * @param integer $uid User ID - */ - public static function transmitContactUndo($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']], - '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); - } - /** * Fetches ActivityPub content from the given url * @@ -809,62 +149,6 @@ class ActivityPub return $profile; } - /** - * @brief - * - * @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); - - $actor = JsonLD::fetchElement($activity, 'actor', 'id'); - logger('Message for user ' . $uid . ' is from actor ' . $actor, LOGGER_DEBUG); - - if (empty($activity)) { - logger('Invalid body.', LOGGER_DEBUG); - return; - } - - 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($activity, $body, $uid, $trust_source); - } - /** * @brief * @@ -890,913 +174,7 @@ class ActivityPub } foreach ($items as $activity) { - self::processActivity($activity, '', $uid, true); + ActivityPub\Receiver::processActivity($activity, '', $uid, true); } } - - /** - * @brief - * - * @param array $activity - * @param integer $uid User ID - * @param $trust_source - * - * @return - */ - private static function prepareObjectData($activity, $uid, &$trust_source) - { - $actor = JsonLD::fetchElement($activity, 'actor', 'id'); - if (empty($actor)) { - logger('Empty actor', LOGGER_DEBUG); - return []; - } - - // 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, 'object', 'id'); - if (empty($object_id)) { - logger('No object found', LOGGER_DEBUG); - return []; - } - - // Fetch the content only on activities where this matters - if (in_array($activity['type'], ['Create', 'Announce'])) { - $object_data = self::fetchObject($object_id, $activity['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($activity['type'], ['Like', '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'] = $activity['type']; - $object_data['author'] = $activity['actor']; - $object_data['object'] = $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'] = $activity['id']; - $object_data['object'] = $activity['object']; - $object_data['object_type'] = JsonLD::fetchElement($activity, 'object', 'type'); - } - - $object_data = self::addActivityFields($object_data, $activity); - - $object_data['type'] = $activity['type']; - $object_data['owner'] = $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; - } - - /** - * @brief - * - * @param array $activity - * @param $body - * @param integer $uid User ID - * @param $trust_source - */ - private static function processActivity($activity, $body = '', $uid = null, $trust_source = false) - { - if (empty($activity['type'])) { - logger('Empty type', LOGGER_DEBUG); - return; - } - - if (empty($activity['object'])) { - logger('Empty object', LOGGER_DEBUG); - return; - } - - if (empty($activity['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 "' . $activity['type'] . '", so we quit now.', LOGGER_DEBUG); - } - - switch ($activity['type']) { - case 'Create': - case 'Announce': - self::createItem($object_data, $body); - break; - - case 'Like': - self::likeItem($object_data, $body); - break; - - case 'Dislike': - self::dislikeItem($object_data, $body); - break; - - case 'Update': - if (in_array($object_data['object_type'], self::CONTENT_TYPES)) { - /// @todo - } elseif (in_array($object_data['object_type'], self::ACCOUNT_TYPES)) { - self::updatePerson($object_data, $body); - } - break; - - case 'Delete': - if ($object_data['object_type'] == 'Tombstone') { - self::deleteItem($object_data, $body); - } elseif (in_array($object_data['object_type'], self::ACCOUNT_TYPES)) { - self::deletePerson($object_data, $body); - } - break; - - case 'Follow': - self::followUser($object_data); - break; - - case 'Accept': - if ($object_data['object_type'] == 'Follow') { - self::acceptFollowUser($object_data); - } - break; - - case 'Reject': - if ($object_data['object_type'] == 'Follow') { - self::rejectFollowUser($object_data); - } - break; - - case 'Undo': - if ($object_data['object_type'] == 'Follow') { - self::undoFollowUser($object_data); - } elseif (in_array($object_data['object_type'], self::ACTIVITY_TYPES)) { - self::undoActivity($object_data); - } - break; - - default: - logger('Unknown activity: ' . $activity['type'], LOGGER_DEBUG); - break; - } - } - - /** - * @brief - * - * @param array $activity - * @param $actor - * - * @return - */ - private static function getReceivers($activity, $actor) - { - $receivers = []; - - // When it is an answer, we inherite the receivers from the parent - $replyto = JsonLD::fetchElement($activity, 'inReplyTo', 'id'); - 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 (['to', 'cc', 'bto', 'bcc'] as $element) { - if (empty($activity[$element])) { - continue; - } - - // The receiver can be an array or a string - if (is_string($activity[$element])) { - $activity[$element] = [$activity[$element]]; - } - - foreach ($activity[$element] 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; - } - - /** - * @brief - * - * @param $cid - * @param integer $uid User ID - * @param $url - */ - private static function switchContact($cid, $uid, $url) - { - $profile = ActivityPub::probeProfile($url); - if (empty($profile)) { - return; - } - - logger('Switch contact ' . $cid . ' (' . $profile['url'] . ') for user ' . $uid . ' from OStatus 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); - } - - /** - * @brief - * - * @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); - } - } - } - - /** - * @brief - * - * @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'] = $activity['published']; - } - - if (!empty($activity['updated']) && empty($object_data['updated'])) { - $object_data['updated'] = $activity['updated']; - } - - if (!empty($activity['inReplyTo']) && empty($object_data['parent-uri'])) { - $object_data['parent-uri'] = JsonLD::fetchElement($activity, 'inReplyTo', 'id'); - } - - if (!empty($activity['instrument'])) { - $object_data['service'] = JsonLD::fetchElement($activity, 'instrument', 'name', 'type', 'Service'); - } - return $object_data; - } - - /** - * @brief - * - * @param $object_id - * @param $object - * @param $trust_source - * - * @return - */ - private static function fetchObject($object_id, $object = [], $trust_source = false) - { - if (!$trust_source || is_string($object)) { - $data = self::fetchContent($object_id); - if (empty($data)) { - logger('Empty content for ' . $object_id . ', check if content is available locally.', LOGGER_DEBUG); - $data = $object_id; - } else { - logger('Fetched content for ' . $object_id, LOGGER_DEBUG); - } - } else { - logger('Using original object for url ' . $object_id, LOGGER_DEBUG); - $data = $object; - } - - if (is_string($data)) { - $item = Item::selectFirst([], ['uri' => $data]); - if (!DBA::isResult($item)) { - logger('Object with url ' . $data . ' was not found locally.', LOGGER_DEBUG); - return false; - } - logger('Using already stored item for url ' . $object_id, LOGGER_DEBUG); - $data = self::createNote($item); - } - - if (empty($data['type'])) { - logger('Empty type', LOGGER_DEBUG); - return false; - } - - if (in_array($data['type'], self::CONTENT_TYPES)) { - return self::processObject($data); - } - - if ($data['type'] == 'Announce') { - if (empty($data['object'])) { - return false; - } - return self::fetchObject($data['object']); - } - - logger('Unhandled object type: ' . $data['type'], LOGGER_DEBUG); - } - - /** - * @brief - * - * @param $object - * - * @return - */ - private static function processObject($object) - { - if (empty($object['id'])) { - return false; - } - - $object_data = []; - $object_data['object_type'] = $object['type']; - $object_data['id'] = $object['id']; - - if (!empty($object['inReplyTo'])) { - $object_data['reply-to-id'] = JsonLD::fetchElement($object, 'inReplyTo', 'id'); - } else { - $object_data['reply-to-id'] = $object_data['id']; - } - - $object_data['published'] = defaults($object, 'published', null); - $object_data['updated'] = defaults($object, 'updated', $object_data['published']); - - if (empty($object_data['published']) && !empty($object_data['updated'])) { - $object_data['published'] = $object_data['updated']; - } - - $actor = JsonLD::fetchElement($object, 'attributedTo', 'id'); - if (empty($actor)) { - $actor = defaults($object, 'actor', null); - } - - $object_data['diaspora:guid'] = defaults($object, 'diaspora:guid', null); - $object_data['owner'] = $object_data['author'] = $actor; - $object_data['context'] = defaults($object, 'context', null); - $object_data['conversation'] = defaults($object, 'conversation', null); - $object_data['sensitive'] = defaults($object, 'sensitive', null); - $object_data['name'] = defaults($object, 'title', null); - $object_data['name'] = defaults($object, 'name', $object_data['name']); - $object_data['summary'] = defaults($object, 'summary', null); - $object_data['content'] = defaults($object, 'content', null); - $object_data['source'] = defaults($object, 'source', null); - $object_data['location'] = JsonLD::fetchElement($object, 'location', 'name', 'type', 'Place'); - $object_data['attachments'] = defaults($object, 'attachment', null); - $object_data['tags'] = defaults($object, 'tag', null); - $object_data['service'] = JsonLD::fetchElement($object, 'instrument', 'name', 'type', 'Service'); - $object_data['alternate-url'] = JsonLD::fetchElement($object, 'url', 'href'); - $object_data['receiver'] = self::getReceivers($object, $object_data['owner']); - - // 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, generator, 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; - } - - /** - * @brief 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; - } - - /** - * @brief 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($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; - } - - /** - * @brief - * - * @param $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; - } - - /** - * @brief - * - * @param array $activity - * @param $body - */ - private static function createItem($activity, $body) - { - $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, $body); - } - - /** - * @brief - * - * @param array $activity - * @param $body - */ - private static function likeItem($activity, $body) - { - $item = []; - $item['verb'] = ACTIVITY_LIKE; - $item['parent-uri'] = $activity['object']; - $item['gravity'] = GRAVITY_ACTIVITY; - $item['object-type'] = ACTIVITY_OBJ_NOTE; - - self::postItem($activity, $item, $body); - } - - /** - * @brief Delete items - * - * @param array $activity - * @param $body - */ - private static function deleteItem($activity) - { - $owner = Contact::getIdForURL($activity['owner']); - $object = JsonLD::fetchElement($activity, 'object', 'id'); - logger('Deleting item ' . $object . ' from ' . $owner, LOGGER_DEBUG); - Item::delete(['uri' => $object, 'owner-id' => $owner]); - } - - /** - * @brief - * - * @param array $activity - * @param $body - */ - private static function dislikeItem($activity, $body) - { - $item = []; - $item['verb'] = ACTIVITY_DISLIKE; - $item['parent-uri'] = $activity['object']; - $item['gravity'] = GRAVITY_ACTIVITY; - $item['object-type'] = ACTIVITY_OBJ_NOTE; - - self::postItem($activity, $item, $body); - } - - /** - * @brief - * - * @param array $activity - * @param array $item - * @param $body - */ - private static function postItem($activity, $item, $body) - { - /// @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-id'] = Contact::getIdForURL($activity['author'], 0, true); - $item['owner-id'] = Contact::getIdForURL($activity['owner'], 0, true); - $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'])); - $item['location'] = $activity['location']; - $item['tag'] = self::constructTagList($activity['tags'], $activity['sensitive']); - $item['app'] = $activity['service']; - $item['plink'] = defaults($activity, 'alternate-url', $item['uri']); - - $item = self::constructAttachList($activity['attachments'], $item); - - $source = JsonLD::fetchElement($activity, 'source', 'content', 'mediaType', 'text/bbcode'); - if (!empty($source)) { - $item['body'] = $source; - } - - $item['protocol'] = Conversation::PARCEL_ACTIVITYPUB; - $item['source'] = $body; - $item['conversation-href'] = $activity['context']; - $item['conversation-uri'] = $activity['conversation']; - - 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); - } - } - - /** - * @brief - * - * @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'; - - self::processActivity($activity); - logger('Activity ' . $url . ' had been fetched and processed.'); - } - - /** - * @brief perform a "follow" request - * - * @param array $activity - */ - private static function followUser($activity) - { - $actor = JsonLD::fetchElement($activity, 'object', 'id'); - $uid = User::getIdForURL($actor); - if (empty($uid)) { - return; - } - - $owner = User::getOwnerDataById($uid); - - $cid = Contact::getIdForURL($activity['owner'], $uid); - if (!empty($cid)) { - $contact = DBA::selectFirst('contact', [], ['id' => $cid]); - } else { - $contact = false; - } - - $item = ['author-id' => Contact::getIdForURL($activity['owner']), - 'author-link' => $activity['owner']]; - - Contact::addRelationship($owner, $contact, $item); - $cid = Contact::getIdForURL($activity['owner'], $uid); - if (empty($cid)) { - return; - } - - $contact = DBA::selectFirst('contact', ['network'], ['id' => $cid]); - if ($contact['network'] != Protocol::ACTIVITYPUB) { - Contact::updateFromProbe($cid, Protocol::ACTIVITYPUB); - } - - DBA::update('contact', ['hub-verify' => $activity['id']], ['id' => $cid]); - logger('Follow user ' . $uid . ' from contact ' . $cid . ' with id ' . $activity['id']); - } - - /** - * @brief Update the given profile - * - * @param array $activity - */ - private 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); - } - - /** - * @brief Delete the given profile - * - * @param array $activity - */ - private static function deletePerson($activity) - { - if (empty($activity['object']['id']) || empty($activity['object']['actor'])) { - logger('Empty object id or actor.', LOGGER_DEBUG); - return; - } - - if ($activity['object']['id'] != $activity['object']['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); - } - - /** - * @brief Accept a follow request - * - * @param array $activity - */ - private static function acceptFollowUser($activity) - { - $actor = JsonLD::fetchElement($activity, 'object', 'actor'); - $uid = User::getIdForURL($actor); - if (empty($uid)) { - return; - } - - $owner = User::getOwnerDataById($uid); - - $cid = Contact::getIdForURL($activity['owner'], $uid); - if (empty($cid)) { - logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); - return; - } - - $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); - } - - /** - * @brief Reject a follow request - * - * @param array $activity - */ - private static function rejectFollowUser($activity) - { - $actor = JsonLD::fetchElement($activity, 'object', 'actor'); - $uid = User::getIdForURL($actor); - if (empty($uid)) { - return; - } - - $owner = User::getOwnerDataById($uid); - - $cid = Contact::getIdForURL($activity['owner'], $uid); - if (empty($cid)) { - logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); - return; - } - - 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); - } - } - - /** - * @brief Undo activity like "like" or "dislike" - * - * @param array $activity - */ - private static function undoActivity($activity) - { - $activity_url = JsonLD::fetchElement($activity, 'object', 'id'); - if (empty($activity_url)) { - return; - } - - $actor = JsonLD::fetchElement($activity, 'object', 'actor'); - if (empty($actor)) { - return; - } - - $author_id = Contact::getIdForURL($actor); - if (empty($author_id)) { - return; - } - - Item::delete(['uri' => $activity_url, 'author-id' => $author_id, 'gravity' => GRAVITY_ACTIVITY]); - } - - /** - * @brief Activity to remove a follower - * - * @param array $activity - */ - private static function undoFollowUser($activity) - { - $object = JsonLD::fetchElement($activity, 'object', 'object'); - $uid = User::getIdForURL($object); - if (empty($uid)) { - return; - } - - $owner = User::getOwnerDataById($uid); - - $cid = Contact::getIdForURL($activity['owner'], $uid); - if (empty($cid)) { - logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); - return; - } - - $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); - } } diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index bbf4d7b801..69343d6661 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -116,7 +116,7 @@ class Processor * @param array $activity * @param $body */ - private static function createItem($activity, $body) + public static function createItem($activity, $body) { $item = []; $item['verb'] = ACTIVITY_POST; @@ -144,7 +144,7 @@ class Processor * @param array $activity * @param $body */ - private static function likeItem($activity, $body) + public static function likeItem($activity, $body) { $item = []; $item['verb'] = ACTIVITY_LIKE; @@ -161,7 +161,7 @@ class Processor * @param array $activity * @param $body */ - private static function deleteItem($activity) + public static function deleteItem($activity) { $owner = Contact::getIdForURL($activity['owner']); $object = JsonLD::fetchElement($activity, 'object', 'id'); @@ -175,7 +175,7 @@ class Processor * @param array $activity * @param $body */ - private static function dislikeItem($activity, $body) + public static function dislikeItem($activity, $body) { $item = []; $item['verb'] = ACTIVITY_DISLIKE; @@ -272,7 +272,7 @@ class Processor $activity['published'] = $object['published']; $activity['type'] = 'Create'; - ActivityPub::processActivity($activity); + ActivityPub\Receiver::processActivity($activity); logger('Activity ' . $url . ' had been fetched and processed.'); } @@ -281,7 +281,7 @@ class Processor * * @param array $activity */ - private static function followUser($activity) + public static function followUser($activity) { $actor = JsonLD::fetchElement($activity, 'object', 'id'); $uid = User::getIdForURL($actor); @@ -321,7 +321,7 @@ class Processor * * @param array $activity */ - private static function updatePerson($activity) + public static function updatePerson($activity) { if (empty($activity['object']['id'])) { return; @@ -336,7 +336,7 @@ class Processor * * @param array $activity */ - private static function deletePerson($activity) + public static function deletePerson($activity) { if (empty($activity['object']['id']) || empty($activity['object']['actor'])) { logger('Empty object id or actor.', LOGGER_DEBUG); @@ -362,7 +362,7 @@ class Processor * * @param array $activity */ - private static function acceptFollowUser($activity) + public static function acceptFollowUser($activity) { $actor = JsonLD::fetchElement($activity, 'object', 'actor'); $uid = User::getIdForURL($actor); @@ -395,7 +395,7 @@ class Processor * * @param array $activity */ - private static function rejectFollowUser($activity) + public static function rejectFollowUser($activity) { $actor = JsonLD::fetchElement($activity, 'object', 'actor'); $uid = User::getIdForURL($actor); @@ -424,7 +424,7 @@ class Processor * * @param array $activity */ - private static function undoActivity($activity) + public static function undoActivity($activity) { $activity_url = JsonLD::fetchElement($activity, 'object', 'id'); if (empty($activity_url)) { @@ -449,7 +449,7 @@ class Processor * * @param array $activity */ - private static function undoFollowUser($activity) + public static function undoFollowUser($activity) { $object = JsonLD::fetchElement($activity, 'object', 'object'); $uid = User::getIdForURL($object); diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 171771748e..5fc4ecbc4b 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -95,7 +95,7 @@ class Receiver $trust_source = false; } - ActivityPub::processActivity($activity, $body, $uid, $trust_source); + self::processActivity($activity, $body, $uid, $trust_source); } /** @@ -116,7 +116,7 @@ class Receiver } // Fetch all receivers from to, cc, bto and bcc - $receivers = ActivityPub::getReceivers($activity, $actor); + $receivers = self::getReceivers($activity, $actor); // When it is a delivery to a personal inbox we add that user to the receivers if (!empty($uid)) { @@ -135,7 +135,7 @@ class Receiver // Fetch the content only on activities where this matters if (in_array($activity['type'], ['Create', 'Announce'])) { - $object_data = ActivityPub::fetchObject($object_id, $activity['object'], $trust_source); + $object_data = self::fetchObject($object_id, $activity['object'], $trust_source); if (empty($object_data)) { logger("Object data couldn't be processed", LOGGER_DEBUG); return []; @@ -145,7 +145,7 @@ class Receiver } elseif (in_array($activity['type'], ['Like', '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 = ActivityPub::processObject($activity); + $object_data = self::processObject($activity); $object_data['name'] = $activity['type']; $object_data['author'] = $activity['actor']; $object_data['object'] = $object_id; @@ -157,7 +157,7 @@ class Receiver $object_data['object_type'] = JsonLD::fetchElement($activity, 'object', 'type'); } - $object_data = ActivityPub::addActivityFields($object_data, $activity); + $object_data = self::addActivityFields($object_data, $activity); $object_data['type'] = $activity['type']; $object_data['owner'] = $actor; @@ -176,7 +176,7 @@ class Receiver * @param integer $uid User ID * @param $trust_source */ - private static function processActivity($activity, $body = '', $uid = null, $trust_source = false) + public static function processActivity($activity, $body = '', $uid = null, $trust_source = false) { if (empty($activity['type'])) { logger('Empty type', LOGGER_DEBUG); @@ -195,7 +195,7 @@ class Receiver } // $trust_source is called by reference and is set to true if the content was retrieved successfully - $object_data = ActivityPub::prepareObjectData($activity, $uid, $trust_source); + $object_data = self::prepareObjectData($activity, $uid, $trust_source); if (empty($object_data)) { logger('No object data found', LOGGER_DEBUG); return; @@ -208,54 +208,54 @@ class Receiver switch ($activity['type']) { case 'Create': case 'Announce': - ActivityPub::createItem($object_data, $body); + ActivityPub\Processor::createItem($object_data, $body); break; case 'Like': - ActivityPub::likeItem($object_data, $body); + ActivityPub\Processor::likeItem($object_data, $body); break; case 'Dislike': - ActivityPub::dislikeItem($object_data, $body); + ActivityPub\Processor::dislikeItem($object_data, $body); break; case 'Update': if (in_array($object_data['object_type'], ActivityPub::CONTENT_TYPES)) { /// @todo } elseif (in_array($object_data['object_type'], ActivityPub::ACCOUNT_TYPES)) { - ActivityPub::updatePerson($object_data, $body); + ActivityPub\Processor::updatePerson($object_data, $body); } break; case 'Delete': if ($object_data['object_type'] == 'Tombstone') { - ActivityPub::deleteItem($object_data, $body); + ActivityPub\Processor::deleteItem($object_data, $body); } elseif (in_array($object_data['object_type'], ActivityPub::ACCOUNT_TYPES)) { - ActivityPub::deletePerson($object_data, $body); + ActivityPub\Processor::deletePerson($object_data, $body); } break; case 'Follow': - ActivityPub::followUser($object_data); + ActivityPub\Processor::followUser($object_data); break; case 'Accept': if ($object_data['object_type'] == 'Follow') { - ActivityPub::acceptFollowUser($object_data); + ActivityPub\Processor::acceptFollowUser($object_data); } break; case 'Reject': if ($object_data['object_type'] == 'Follow') { - ActivityPub::rejectFollowUser($object_data); + ActivityPub\Processor::rejectFollowUser($object_data); } break; case 'Undo': if ($object_data['object_type'] == 'Follow') { - ActivityPub::undoFollowUser($object_data); + ActivityPub\Processor::undoFollowUser($object_data); } elseif (in_array($object_data['object_type'], ActivityPub::ACTIVITY_TYPES)) { - ActivityPub::undoActivity($object_data); + ActivityPub\Processor::undoActivity($object_data); } break; @@ -346,7 +346,7 @@ class Receiver } } - ActivityPub::switchContacts($receivers, $actor); + self::switchContacts($receivers, $actor); return $receivers; } @@ -392,12 +392,12 @@ class Receiver foreach ($receivers as $receiver) { $contact = DBA::selectFirst('contact', ['id'], ['uid' => $receiver, 'network' => Protocol::OSTATUS, 'nurl' => normalise_link($actor)]); if (DBA::isResult($contact)) { - ActivityPub::switchContact($contact['id'], $receiver, $actor); + 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)) { - ActivityPub::switchContact($contact['id'], $receiver, $actor); + self::switchContact($contact['id'], $receiver, $actor); } } } @@ -461,7 +461,7 @@ class Receiver return false; } logger('Using already stored item for url ' . $object_id, LOGGER_DEBUG); - $data = ActivityPub::createNote($item); + $data = ActivityPub\Transmitter::createNote($item); } if (empty($data['type'])) { @@ -470,14 +470,14 @@ class Receiver } if (in_array($data['type'], ActivityPub::CONTENT_TYPES)) { - return ActivityPub::processObject($data); + return self::processObject($data); } if ($data['type'] == 'Announce') { if (empty($data['object'])) { return false; } - return ActivityPub::fetchObject($data['object']); + return self::fetchObject($data['object']); } logger('Unhandled object type: ' . $data['type'], LOGGER_DEBUG); @@ -533,7 +533,7 @@ class Receiver $object_data['tags'] = defaults($object, 'tag', null); $object_data['service'] = JsonLD::fetchElement($object, 'instrument', 'name', 'type', 'Service'); $object_data['alternate-url'] = JsonLD::fetchElement($object, 'url', 'href'); - $object_data['receiver'] = ActivityPub::getReceivers($object, $object_data['owner']); + $object_data['receiver'] = self::getReceivers($object, $object_data['owner']); // Common object data: @@ -560,37 +560,4 @@ class Receiver return $object_data; } - - /** - * @brief - * - * @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'; - - ActivityPub::processActivity($activity); - logger('Activity ' . $url . ' had been fetched and processed.'); - } } diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 7155d83094..aeb27a819c 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -283,7 +283,7 @@ class Transmitter * * @return permission array */ - public static function createPermissionBlockForItem($item) + private static function createPermissionBlockForItem($item) { $data = ['to' => [], 'cc' => []]; @@ -684,7 +684,7 @@ class Transmitter 'id' => System::baseUrl() . '/activity/' . System::createGUID(), 'type' => 'Delete', 'actor' => $owner['url'], - 'object' => self::profile($uid), + 'object' => $owner['url'], 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), 'to' => [ActivityPub::PUBLIC_COLLECTION], 'cc' => []]; diff --git a/src/Worker/APDelivery.php b/src/Worker/APDelivery.php index 22b8c8f0ff..21d4c78589 100644 --- a/src/Worker/APDelivery.php +++ b/src/Worker/APDelivery.php @@ -19,11 +19,11 @@ class APDelivery extends BaseObject } elseif ($cmd == Delivery::SUGGESTION) { } elseif ($cmd == Delivery::RELOCATION) { } elseif ($cmd == Delivery::REMOVAL) { - ActivityPub::transmitProfileDeletion($uid, $inbox); + ActivityPub\Transmitter::transmitProfileDeletion($uid, $inbox); } elseif ($cmd == Delivery::PROFILEUPDATE) { - ActivityPub::transmitProfileUpdate($uid, $inbox); + ActivityPub\Transmitter::transmitProfileUpdate($uid, $inbox); } else { - $data = ActivityPub::createActivityFromItem($item_id); + $data = ActivityPub\Transmitter::createActivityFromItem($item_id); if (!empty($data)) { HTTPSignature::transmit($data, $inbox, $uid); } diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index 3ab238422a..8945a958fe 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -100,7 +100,7 @@ class Notifier Contact::terminateFriendship($user, $contact, true); } - $inboxes = ActivityPub::fetchTargetInboxesforUser(0); + $inboxes = ActivityPub\Transmitter::fetchTargetInboxesforUser(0); foreach ($inboxes as $inbox) { logger('Account removal for user ' . $uid . ' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG); Worker::add(['priority' => $a->queue['priority'], 'created' => $a->queue['created'], 'dont_fork' => true], @@ -425,11 +425,11 @@ class Notifier $inboxes = []; if ($target_item['origin']) { - $inboxes = ActivityPub::fetchTargetInboxes($target_item, $uid); + $inboxes = ActivityPub\Transmitter::fetchTargetInboxes($target_item, $uid); } if ($parent['origin']) { - $parent_inboxes = ActivityPub::fetchTargetInboxes($parent, $uid); + $parent_inboxes = ActivityPub\Transmitter::fetchTargetInboxes($parent, $uid); $inboxes = array_merge($inboxes, $parent_inboxes); } diff --git a/src/Worker/ProfileUpdate.php b/src/Worker/ProfileUpdate.php index 7fab86cbfd..cebc27ca55 100644 --- a/src/Worker/ProfileUpdate.php +++ b/src/Worker/ProfileUpdate.php @@ -19,7 +19,7 @@ class ProfileUpdate { $a = BaseObject::getApp(); - $inboxes = ActivityPub::fetchTargetInboxesforUser($uid); + $inboxes = ActivityPub\Transmitter::fetchTargetInboxesforUser($uid); foreach ($inboxes as $inbox) { logger('Profile update for user ' . $uid . ' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG); From acd1caa1144f558002214d5991f551f232482200 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 3 Oct 2018 09:45:54 +0000 Subject: [PATCH 254/428] The function is only needed in the same class --- src/Protocol/ActivityPub/Transmitter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index aeb27a819c..17ad0d350f 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -442,7 +442,7 @@ class Transmitter * * @return activity type */ - public static function getTypeOfItem($item) + private static function getTypeOfItem($item) { if ($item['verb'] == ACTIVITY_POST) { if ($item['created'] == $item['edited']) { From 1fe55679fc06af36fabfee4758adb6c2dc3241b9 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 3 Oct 2018 09:53:12 +0000 Subject: [PATCH 255/428] Moved documentation --- src/Protocol/ActivityPub.php | 26 ------------------------ src/Protocol/ActivityPub/Receiver.php | 18 +++++++++++++++- src/Protocol/ActivityPub/Transmitter.php | 12 +++++++++++ 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index c84f5d3ee4..9ccd90eed6 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -42,33 +42,7 @@ use Friendica\Core\Config; * https://github.com/tootsuite/mastodon/blob/master/app/lib/activitypub/activity.rb#L26 * * To-do: - * - * Receiver: - * - 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) - * - * Transmitter: - * - Event - * - * Complicated: - * - Announce - * - Undo Announce - * - * General: - * - Attachments - * - nsfw (sensitive) - * - Queueing unsucessful deliveries * - Polling the outboxes for missing content? - * - Possibly using the LD-JSON parser */ class ActivityPub { diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 5fc4ecbc4b..6b2e02a2c0 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -27,7 +27,23 @@ use Friendica\Core\Config; use Friendica\Protocol\ActivityPub; /** - * @brief ActivityPub Protocol class + * @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) + * + * General: + * - Possibly using the LD-JSON parser */ class Receiver { diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 17ad0d350f..ee4fe20b9a 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -24,6 +24,18 @@ use Friendica\Model\Profile; /** * @brief ActivityPub Transmitter Protocol class + * + * To-Do: + * - Event + * + * Complicated: + * - Announce + * - Undo Announce + * + * General: + * - Attachments + * - nsfw (sensitive) + * - Queueing unsucessful deliveries */ class Transmitter { From 3ecabe0291b159d163ad315b66f51b6d741d879e Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Wed, 3 Oct 2018 13:10:49 +0200 Subject: [PATCH 256/428] Fix goaway url when login failed + using info to display message --- src/Module/Login.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Module/Login.php b/src/Module/Login.php index fadfb20661..e6bb933f0f 100644 --- a/src/Module/Login.php +++ b/src/Module/Login.php @@ -140,8 +140,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: ' . $e->getMessage() . EOL); + goaway(); } if (!$remember) { From 3c9b33176f52790ff669ec2f2e28ed350a3944c8 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Wed, 3 Oct 2018 14:32:16 +0200 Subject: [PATCH 257/428] Static reason for login failure to prevent bruteforce --- src/Module/Login.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Module/Login.php b/src/Module/Login.php index e6bb933f0f..99401ebbe4 100644 --- a/src/Module/Login.php +++ b/src/Module/Login.php @@ -140,7 +140,7 @@ class Login extends BaseModule } } catch (Exception $e) { logger('authenticate: failed login attempt: ' . notags($username) . ' from IP ' . $_SERVER['REMOTE_ADDR']); - info('Login failed: ' . $e->getMessage() . EOL); + info('Login failed. Please check your credentials.' . EOL); goaway(); } From 8841519c0dfae069aff6bee6325fa868e4b9b641 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 3 Oct 2018 15:41:51 +0000 Subject: [PATCH 258/428] Renamed functions --- mod/dfrn_confirm.php | 4 ++-- src/Model/Contact.php | 8 ++++---- src/Protocol/ActivityPub/Processor.php | 4 ++-- src/Protocol/ActivityPub/Receiver.php | 2 +- src/Protocol/ActivityPub/Transmitter.php | 12 ++++++------ src/Worker/APDelivery.php | 4 ++-- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php index 9bd9339ed7..d3fa45d361 100644 --- a/mod/dfrn_confirm.php +++ b/mod/dfrn_confirm.php @@ -337,7 +337,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) ); } else { if ($network == Protocol::ACTIVITYPUB) { - ActivityPub\Transmitter::transmitContactAccept($contact['url'], $contact['hub-verify'], $uid); + ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $uid); $pending = true; } else { $pending = false; @@ -394,7 +394,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) Group::addMember(User::getDefaultGroup($uid, $contact["network"]), $contact['id']); if ($network == Protocol::ACTIVITYPUB && $duplex) { - ActivityPub\Transmitter::transmitActivity('Follow', $contact['url'], $uid); + ActivityPub\Transmitter::sendActivity('Follow', $contact['url'], $uid); } // Let's send our user to the contact editor in case they want to diff --git a/src/Model/Contact.php b/src/Model/Contact.php index c7513567ac..3ffd5b2af5 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -557,10 +557,10 @@ class Contact extends BaseObject } elseif ($contact['network'] == Protocol::DIASPORA) { Diaspora::sendUnshare($user, $contact); } elseif ($contact['network'] == Protocol::ACTIVITYPUB) { - ActivityPub\Transmitter::transmitContactUndo($contact['url'], $user['uid']); + ActivityPub\Transmitter::sendContactUndo($contact['url'], $user['uid']); if ($dissolve) { - ActivityPub\Transmitter::transmitContactReject($contact['url'], $contact['hub-verify'], $user['uid']); + ActivityPub\Transmitter::sendContactReject($contact['url'], $contact['hub-verify'], $user['uid']); } } } @@ -1769,7 +1769,7 @@ class Contact extends BaseObject $ret = Diaspora::sendShare($a->user, $contact); logger('share returns: ' . $ret); } elseif ($contact['network'] == Protocol::ACTIVITYPUB) { - $ret = ActivityPub\Transmitter::transmitActivity('Follow', $contact['url'], $uid); + $ret = ActivityPub\Transmitter::sendActivity('Follow', $contact['url'], $uid); logger('Follow returns: ' . $ret); } } @@ -1846,7 +1846,7 @@ class Contact extends BaseObject } if ($contact['network'] == Protocol::ACTIVITYPUB) { - ActivityPub\Transmitter::transmitContactAccept($contact['url'], $contact['hub-verify'], $importer['uid']); + ActivityPub\Transmitter::sendContactAccept($contact['url'], $contact['hub-verify'], $importer['uid']); } // send email notification to owner? diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 69343d6661..8162605613 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -1,6 +1,6 @@ Date: Wed, 3 Oct 2018 15:50:21 +0000 Subject: [PATCH 259/428] Another renamed function --- mod/profile.php | 2 +- src/Protocol/ActivityPub/Transmitter.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mod/profile.php b/mod/profile.php index 729f11028a..5b306b20fb 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -53,7 +53,7 @@ function profile_init(App $a) if (ActivityPub::isRequest()) { $user = DBA::selectFirst('user', ['uid'], ['nickname' => $which]); if (DBA::isResult($user)) { - $data = ActivityPub\Transmitter::profile($user['uid']); + $data = ActivityPub\Transmitter::getProfile($user['uid']); echo json_encode($data); header('Content-Type: application/activity+json'); exit(); diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index c3bc2eeb74..c4a90996d8 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -187,7 +187,7 @@ class Transmitter * @param integer $uid User ID * @return profile array */ - public static function profile($uid) + public static function getProfile($uid) { $condition = ['uid' => $uid, 'blocked' => false, 'account_expired' => false, 'account_removed' => false, 'verified' => true]; @@ -722,7 +722,7 @@ class Transmitter 'id' => System::baseUrl() . '/activity/' . System::createGUID(), 'type' => 'Update', 'actor' => $owner['url'], - 'object' => self::profile($uid), + 'object' => self::getProfile($uid), 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), 'to' => [$profile['followers']], 'cc' => []]; From ee32459358c6ca818f368e55e49147e4dcdcc690 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Wed, 3 Oct 2018 18:28:04 +0200 Subject: [PATCH 260/428] goaway with argument --- src/Module/Login.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Module/Login.php b/src/Module/Login.php index 99401ebbe4..ad5d5ad0b6 100644 --- a/src/Module/Login.php +++ b/src/Module/Login.php @@ -141,7 +141,7 @@ class Login extends BaseModule } catch (Exception $e) { logger('authenticate: failed login attempt: ' . notags($username) . ' from IP ' . $_SERVER['REMOTE_ADDR']); info('Login failed. Please check your credentials.' . EOL); - goaway(); + goaway('/'); } if (!$remember) { From a9a1ac808b475b4ccd27ab7e2aa833cf098f461a Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 3 Oct 2018 17:36:55 +0000 Subject: [PATCH 261/428] Attachments do work now --- src/Protocol/ActivityPub.php | 1 + src/Protocol/ActivityPub/Transmitter.php | 73 +++++++++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index 9ccd90eed6..7c0a2b706c 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -43,6 +43,7 @@ use Friendica\Core\Config; * * To-do: * - Polling the outboxes for missing content? + * - "about" needs HTML2BBCode parser */ class ActivityPub { diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index c4a90996d8..8463a91e16 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -21,6 +21,8 @@ use Friendica\Util\JsonLD; use Friendica\Util\LDSignature; use Friendica\Protocol\ActivityPub; use Friendica\Model\Profile; +use Friendica\Core\Config; +use Friendica\Object\Image; /** * @brief ActivityPub Transmitter Protocol class @@ -33,7 +35,6 @@ use Friendica\Model\Profile; * - Undo Announce * * General: - * - Attachments * - nsfw (sensitive) * - Queueing unsucessful deliveries */ @@ -595,6 +596,74 @@ class Transmitter return $tags; } + /** + * @brief Adds attachment data to the JSON document + * + * @param array $item Data of the item that is to be posted + * @return attachment array + */ + + private static function createAttachmentList($item) + { + $attachments = []; + + $siteinfo = BBCode::getAttachedData($item['body']); + + switch ($siteinfo['type']) { + case 'photo': + if (!empty($siteinfo['image'])) { + $imgdata = Image::getInfoFromURL($siteinfo['image']); + if ($imgdata) { + $attachments[] = ['type' => 'Document', + 'mediaType' => $imgdata['mime'], + 'url' => $siteinfo['image'], + 'name' => null]; + } + } + break; + case 'video': + $attachments[] = ['type' => 'Document', + 'mediaType' => 'text/html; charset=UTF-8', + 'url' => $siteinfo['url'], + 'name' => defaults($siteinfo, 'title', $siteinfo['url'])]; + break; + default: + break; + } + + if (!Config::get('system', 'ostatus_not_attach_preview') && ($siteinfo['type'] != 'photo') && isset($siteinfo['image'])) { + $imgdata = Image::getInfoFromURL($siteinfo['image']); + if ($imgdata) { + $attachments[] = ['type' => 'Document', + 'mediaType' => $imgdata['mime'], + 'url' => $siteinfo['image'], + 'name' => null]; + } + } + + $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; + } + } + } + + return $attachments; + } + /** * @brief Fetches the "context" value for a givem item array from the "conversation" table * @@ -674,7 +743,7 @@ class Transmitter $data['diaspora:comment'] = $item['signed_text']; } - $data['attachment'] = []; // @ToDo + $data['attachment'] = self::createAttachmentList($item); $data['tag'] = self::createTagList($item); $data = array_merge($data, self::createPermissionBlockForItem($item)); From 221e1976583ef7e0e514f24433250f1ba4d8d011 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 3 Oct 2018 18:27:01 +0000 Subject: [PATCH 262/428] Tags are now transmitted as expected --- src/Protocol/ActivityPub/Transmitter.php | 29 ++++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 8463a91e16..76c233fd5e 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -35,7 +35,6 @@ use Friendica\Object\Image; * - Undo Announce * * General: - * - nsfw (sensitive) * - Queueing unsucessful deliveries */ class Transmitter @@ -582,16 +581,20 @@ class Transmitter { $tags = []; - $terms = Term::tagArrayFromItemId($item['id'], TERM_MENTION); + $terms = Term::tagArrayFromItemId($item['id']); foreach ($terms as $term) { - $contact = Contact::getDetailsByURL($term['url']); - if (!empty($contact['addr'])) { - $mention = '@' . $contact['addr']; - } else { - $mention = '@' . $term['url']; - } + 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]; + $tags[] = ['type' => 'Mention', 'href' => $term['url'], 'name' => $mention]; + } } return $tags; } @@ -684,6 +687,12 @@ class Transmitter return $context_uri; } + private static function fetchSensitive($item_id) + { + $condition = ['otype' => TERM_OBJ_POST, 'oid' => $item_id, 'type' => TERM_HASHTAG, 'term' => 'nsfw']; + return DBA::exists('term', $condition); + } + /** * @brief Creates a note/article object array * @@ -729,7 +738,7 @@ class Transmitter $data['url'] = $item['plink']; $data['attributedTo'] = $item['author-link']; $data['actor'] = $item['author-link']; - $data['sensitive'] = false; // - Query NSFW + $data['sensitive'] = self::fetchSensitive($item['id']); $data['context'] = self::fetchContextURLForItem($item); if (!empty($item['title'])) { From cbfc3d0c28e0b55c3ccf1ddfd321798a8c2532e8 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 3 Oct 2018 19:00:32 +0000 Subject: [PATCH 263/428] Fix error / "about" is now converted to BBCode --- src/Model/APContact.php | 3 ++- src/Protocol/ActivityPub/Transmitter.php | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Model/APContact.php b/src/Model/APContact.php index efd6ed0e9d..ce66ec4c6e 100644 --- a/src/Model/APContact.php +++ b/src/Model/APContact.php @@ -12,6 +12,7 @@ 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'; @@ -114,7 +115,7 @@ class APContact extends BaseObject $apcontact['sharedinbox'] = JsonLD::fetchElement($data, 'endpoints', 'sharedInbox'); $apcontact['nick'] = defaults($data, 'preferredUsername', null); $apcontact['name'] = defaults($data, 'name', $apcontact['nick']); - $apcontact['about'] = defaults($data, 'summary', ''); + $apcontact['about'] = HTML::toBBCode(defaults($data, 'summary', '')); $apcontact['photo'] = JsonLD::fetchElement($data, 'icon', 'url'); $apcontact['alias'] = JsonLD::fetchElement($data, 'url', 'href'); diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 76c233fd5e..b92148e1ff 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -700,7 +700,7 @@ class Transmitter * * @return object array */ - private static function createNote($item) + public static function createNote($item) { if (!empty($item['title'])) { $type = 'Article'; From 11a7f6c3e19cfdc58be2859e91d0e147106d4e23 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 3 Oct 2018 19:17:40 +0000 Subject: [PATCH 264/428] Unused "use" removed --- src/Protocol/ActivityPub.php | 18 ------------------ src/Protocol/ActivityPub/Processor.php | 10 ---------- src/Protocol/ActivityPub/Receiver.php | 11 ----------- src/Protocol/ActivityPub/Transmitter.php | 3 +-- 4 files changed, 1 insertion(+), 41 deletions(-) diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index 7c0a2b706c..9f3d42fbd7 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -4,26 +4,9 @@ */ namespace Friendica\Protocol; -use Friendica\Database\DBA; -use Friendica\Core\System; -use Friendica\BaseObject; use Friendica\Util\Network; -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\Profile; -use Friendica\Model\Term; -use Friendica\Model\User; -use Friendica\Util\DateTimeFormat; -use Friendica\Util\Crypto; -use Friendica\Content\Text\BBCode; -use Friendica\Content\Text\HTML; -use Friendica\Util\JsonLD; -use Friendica\Util\LDSignature; -use Friendica\Core\Config; /** * @brief ActivityPub Protocol class @@ -43,7 +26,6 @@ use Friendica\Core\Config; * * To-do: * - Polling the outboxes for missing content? - * - "about" needs HTML2BBCode parser */ class ActivityPub { diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 8162605613..2e93e1bc18 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -5,24 +5,14 @@ namespace Friendica\Protocol\ActivityPub; use Friendica\Database\DBA; -use Friendica\Core\System; -use Friendica\BaseObject; -use Friendica\Util\Network; -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\Profile; -use Friendica\Model\Term; use Friendica\Model\User; -use Friendica\Util\DateTimeFormat; -use Friendica\Util\Crypto; -use Friendica\Content\Text\BBCode; use Friendica\Content\Text\HTML; use Friendica\Util\JsonLD; -use Friendica\Util\LDSignature; use Friendica\Core\Config; use Friendica\Protocol\ActivityPub; diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index b84dc6cee9..a3be19ce44 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -5,25 +5,14 @@ namespace Friendica\Protocol\ActivityPub; use Friendica\Database\DBA; -use Friendica\Core\System; -use Friendica\BaseObject; -use Friendica\Util\Network; 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\Profile; -use Friendica\Model\Term; use Friendica\Model\User; -use Friendica\Util\DateTimeFormat; -use Friendica\Util\Crypto; -use Friendica\Content\Text\BBCode; -use Friendica\Content\Text\HTML; use Friendica\Util\JsonLD; use Friendica\Util\LDSignature; -use Friendica\Core\Config; use Friendica\Protocol\ActivityPub; /** diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index b92148e1ff..f06122e6e2 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -6,7 +6,6 @@ namespace Friendica\Protocol\ActivityPub; use Friendica\Database\DBA; use Friendica\Core\System; -use Friendica\BaseObject; use Friendica\Util\HTTPSignature; use Friendica\Core\Protocol; use Friendica\Model\Conversation; @@ -19,10 +18,10 @@ use Friendica\Util\DateTimeFormat; use Friendica\Content\Text\BBCode; use Friendica\Util\JsonLD; use Friendica\Util\LDSignature; -use Friendica\Protocol\ActivityPub; use Friendica\Model\Profile; use Friendica\Core\Config; use Friendica\Object\Image; +use Friendica\Protocol\ActivityPub; /** * @brief ActivityPub Transmitter Protocol class From f6277970fa4ce219a76b660eed2ebd6a6c7b574b Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 3 Oct 2018 19:35:01 +0000 Subject: [PATCH 265/428] Added some to-do --- src/Protocol/ActivityPub/Transmitter.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index f06122e6e2..afd9582c2d 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -35,6 +35,8 @@ use Friendica\Protocol\ActivityPub; * * General: * - Queueing unsucessful deliveries + * - Type "note": Remove inline images and add them as attachments + * - Type "article": Leave imaged embedded and don't add them as attachments */ class Transmitter { From 72fc89d033070a72a01fd0b3f7a91d21d7467acb Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 4 Oct 2018 05:26:00 +0000 Subject: [PATCH 266/428] Simplified attachment handling --- src/Protocol/ActivityPub/Transmitter.php | 58 +++++++++--------------- 1 file changed, 22 insertions(+), 36 deletions(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index afd9582c2d..bb98371178 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -604,47 +604,14 @@ class Transmitter * @brief 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 attachment array */ - private static function createAttachmentList($item) + private static function createAttachmentList($item, $type) { $attachments = []; - $siteinfo = BBCode::getAttachedData($item['body']); - - switch ($siteinfo['type']) { - case 'photo': - if (!empty($siteinfo['image'])) { - $imgdata = Image::getInfoFromURL($siteinfo['image']); - if ($imgdata) { - $attachments[] = ['type' => 'Document', - 'mediaType' => $imgdata['mime'], - 'url' => $siteinfo['image'], - 'name' => null]; - } - } - break; - case 'video': - $attachments[] = ['type' => 'Document', - 'mediaType' => 'text/html; charset=UTF-8', - 'url' => $siteinfo['url'], - 'name' => defaults($siteinfo, 'title', $siteinfo['url'])]; - break; - default: - break; - } - - if (!Config::get('system', 'ostatus_not_attach_preview') && ($siteinfo['type'] != 'photo') && isset($siteinfo['image'])) { - $imgdata = Image::getInfoFromURL($siteinfo['image']); - if ($imgdata) { - $attachments[] = ['type' => 'Document', - 'mediaType' => $imgdata['mime'], - 'url' => $siteinfo['image'], - 'name' => null]; - } - } - $arr = explode('[/attach],', $item['attach']); if (count($arr)) { foreach ($arr as $r) { @@ -665,6 +632,25 @@ class Transmitter } } + if ($type != 'Note') { + return $attachments; + } + + /// @todo Replace this with a function that takes all pictures from the post + $siteinfo = BBCode::getAttachedData($item['body']); + + if (!empty($siteinfo['image']) && + (($siteinfo['type'] == 'photo') || + !Config::get('system', 'ostatus_not_attach_preview'))) { + $imgdata = Image::getInfoFromURL($siteinfo['image']); + if ($imgdata) { + $attachments[] = ['type' => 'Document', + 'mediaType' => $imgdata['mime'], + 'url' => $siteinfo['image'], + 'name' => null]; + } + } + return $attachments; } @@ -753,7 +739,7 @@ class Transmitter $data['diaspora:comment'] = $item['signed_text']; } - $data['attachment'] = self::createAttachmentList($item); + $data['attachment'] = self::createAttachmentList($item, $type); $data['tag'] = self::createTagList($item); $data = array_merge($data, self::createPermissionBlockForItem($item)); From 06a59c83122a520f80febccb0e7af485fd9894da Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 4 Oct 2018 05:29:22 +0000 Subject: [PATCH 267/428] Funkwhale documentation added --- src/Protocol/ActivityPub.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index 9f3d42fbd7..0b7d527801 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -24,6 +24,9 @@ use Friendica\Model\APContact; * 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? */ From 9171b2a0f3f4ddf5e03e1f2bffdecbb4607f7ba0 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 4 Oct 2018 09:46:29 +0000 Subject: [PATCH 268/428] It's possibly better to use context links that do exist --- src/Protocol/ActivityPub/Transmitter.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index bb98371178..8104d46696 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -548,6 +548,8 @@ class Transmitter } else { return $data; } + + /// @todo Create "conversation" entry } /** @@ -669,7 +671,7 @@ class Transmitter } elseif (DBA::isResult($conversation) && !empty($conversation['conversation-uri'])) { $context_uri = $conversation['conversation-uri']; } else { - $context_uri = str_replace('/objects/', '/context/', $item['parent-uri']); + $context_uri = $item['parent-uri'] . '#context'; } return $context_uri; } From 1c615f80c4f8a10f6bbaeebb4d9fa15f78c8372d Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 4 Oct 2018 12:53:41 +0000 Subject: [PATCH 269/428] Improved return values --- src/Protocol/ActivityPub/Transmitter.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 8104d46696..965c430a70 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -186,7 +186,7 @@ class Transmitter * Return the ActivityPub profile of the given user * * @param integer $uid User ID - * @return profile array + * @return array with profile data */ public static function getProfile($uid) { @@ -294,7 +294,7 @@ class Transmitter * * @param array $item * - * @return permission array + * @return array with permission data */ private static function createPermissionBlockForItem($item) { @@ -453,7 +453,7 @@ class Transmitter * * @param array $item * - * @return activity type + * @return string with activity type */ private static function getTypeOfItem($item) { @@ -557,7 +557,7 @@ class Transmitter * * @param integer $item_id * - * @return object array + * @return array with the object data */ public static function createObjectFromItemID($item_id) { @@ -607,7 +607,7 @@ class Transmitter * * @param array $item Data of the item that is to be posted * @param text $type Object type - * @return attachment array + * @return array with attachment data */ private static function createAttachmentList($item, $type) @@ -687,7 +687,7 @@ class Transmitter * * @param array $item * - * @return object array + * @return array with the object data */ public static function createNote($item) { From 0ebfa6fc123916754585625ae2823fbb5160840f Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 4 Oct 2018 12:57:42 +0000 Subject: [PATCH 270/428] Added to-do --- src/Protocol/ActivityPub/Receiver.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index a3be19ce44..30d710702a 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -380,6 +380,8 @@ class Receiver DBA::update('contact', $profile, ['id' => $cid]); Contact::updateAvatar($photo, $uid, $cid); + + /// @todo Send a new follow request to be sure that the connection still exists } /** From 4368c922fb18732eced5c726f8813ee16fe4aee6 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 4 Oct 2018 13:08:11 +0000 Subject: [PATCH 271/428] is sensitive --- src/Protocol/ActivityPub/Transmitter.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 965c430a70..3700e6f9fb 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -676,7 +676,7 @@ class Transmitter return $context_uri; } - private static function fetchSensitive($item_id) + private static function isSensitive($item_id) { $condition = ['otype' => TERM_OBJ_POST, 'oid' => $item_id, 'type' => TERM_HASHTAG, 'term' => 'nsfw']; return DBA::exists('term', $condition); @@ -727,7 +727,7 @@ class Transmitter $data['url'] = $item['plink']; $data['attributedTo'] = $item['author-link']; $data['actor'] = $item['author-link']; - $data['sensitive'] = self::fetchSensitive($item['id']); + $data['sensitive'] = self::isSensitive($item['id']); $data['context'] = self::fetchContextURLForItem($item); if (!empty($item['title'])) { From 07489a3a9c4fe191959969255eecf6c4fe57c764 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Thu, 4 Oct 2018 18:53:52 +0200 Subject: [PATCH 272/428] Install: After detecting DB already in use, go back to db_stettings with error --- mod/install.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/mod/install.php b/mod/install.php index d2d322b3b9..8355f61300 100644 --- a/mod/install.php +++ b/mod/install.php @@ -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.'); } } From faa86aa2c0bb52908dc28fd8b0b5c5b093f5c4b2 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Thu, 4 Oct 2018 21:38:44 +0200 Subject: [PATCH 273/428] fix indent with tabs --- mod/install.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mod/install.php b/mod/install.php index 8355f61300..7a69a731ba 100644 --- a/mod/install.php +++ b/mod/install.php @@ -125,8 +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']) { - $install_wizard_pass = 2; - $wizard_status = L10n::t('Database already in use.'); + $install_wizard_pass = 2; + $wizard_status = L10n::t('Database already in use.'); } } From 2802f031d4da307d7c59838ecd1ea6a15183c0b2 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Fri, 5 Oct 2018 00:08:16 +0200 Subject: [PATCH 274/428] Submit button for rss poll --- view/theme/frio/templates/contact_edit.tpl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/view/theme/frio/templates/contact_edit.tpl b/view/theme/frio/templates/contact_edit.tpl index a72ac5c605..6dfc3adfb6 100644 --- a/view/theme/frio/templates/contact_edit.tpl +++ b/view/theme/frio/templates/contact_edit.tpl @@ -45,7 +45,10 @@ {{if $poll_enabled}}
  • {{$lastupdtext}} {{$last_update}}
    {{if $poll_interval}} - {{$updpub}} {{$poll_interval}} +
    + {{$updpub}} {{$poll_interval}} + +
    {{/if}}
  • {{/if}} From 5a5a281ed270ef8fea6220a841f38383f6d9b0df Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Fri, 5 Oct 2018 00:11:13 +0200 Subject: [PATCH 275/428] css for submit button --- view/theme/frio/templates/contact_edit.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/theme/frio/templates/contact_edit.tpl b/view/theme/frio/templates/contact_edit.tpl index 6dfc3adfb6..3db3fde032 100644 --- a/view/theme/frio/templates/contact_edit.tpl +++ b/view/theme/frio/templates/contact_edit.tpl @@ -47,7 +47,7 @@ {{if $poll_interval}}
    {{$updpub}} {{$poll_interval}} - +
    {{/if}} From 3d74d412b23062387c416454f534a980b812dc5b Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 5 Oct 2018 04:04:37 +0000 Subject: [PATCH 276/428] Changed attachment handling to improve Mastodon compatibility --- src/Protocol/ActivityPub/Transmitter.php | 84 ++++++++++++++++-------- 1 file changed, 55 insertions(+), 29 deletions(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 3700e6f9fb..bfbd9f9b4e 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -27,16 +27,16 @@ use Friendica\Protocol\ActivityPub; * @brief ActivityPub Transmitter Protocol class * * To-Do: + * + * Missing object types: * - Event * - * Complicated: + * Complicated object types: * - Announce * - Undo Announce * * General: * - Queueing unsucessful deliveries - * - Type "note": Remove inline images and add them as attachments - * - Type "article": Leave imaged embedded and don't add them as attachments */ class Transmitter { @@ -521,15 +521,9 @@ class Transmitter $data['id'] = $item['uri'] . '#' . $type; $data['type'] = $type; - $data['actor'] = $item['author-link']; + $data['actor'] = $item['owner-link']; - $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['context'] = self::fetchContextURLForItem($item); + $data['published'] = DateTimeFormat::utc($item['created'] . '+00:00', DateTimeFormat::ATOM); $data = array_merge($data, self::createPermissionBlockForItem($item)); @@ -607,9 +601,9 @@ class Transmitter * * @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 = []; @@ -638,24 +632,43 @@ class Transmitter return $attachments; } - /// @todo Replace this with a function that takes all pictures from the post - $siteinfo = BBCode::getAttachedData($item['body']); + // Simplify image codes + $body = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $item['body']); - if (!empty($siteinfo['image']) && - (($siteinfo['type'] == 'photo') || - !Config::get('system', 'ostatus_not_attach_preview'))) { - $imgdata = Image::getInfoFromURL($siteinfo['image']); + // 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' => $siteinfo['image'], - 'name' => null]; + 'mediaType' => $imgdata['mime'], + 'url' => $picture, + 'name' => null]; } + } } return $attachments; } + /** + * @brief 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; + } + /** * @brief Fetches the "context" value for a givem item array from the "conversation" table * @@ -676,6 +689,13 @@ class Transmitter return $context_uri; } + /** + * @brief 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']; @@ -718,10 +738,10 @@ class Transmitter } $data['diaspora:guid'] = $item['guid']; - $data['published'] = DateTimeFormat::utc($item["created"]."+00:00", DateTimeFormat::ATOM); + $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); + if ($item['created'] != $item['edited']) { + $data['updated'] = DateTimeFormat::utc($item['edited'] . '+00:00', DateTimeFormat::ATOM); } $data['url'] = $item['plink']; @@ -734,7 +754,13 @@ class Transmitter $data['name'] = BBCode::convert($item['title'], false, 7); } - $data['content'] = BBCode::convert($item['body'], false, 7); + $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'])) { @@ -770,7 +796,7 @@ class Transmitter $signed = LDSignature::sign($data, $owner); - logger('Deliver profile deletion for user ' . $uid . ' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG); + logger('Deliver profile deletion for user ' . $uid . ' to ' . $inbox . ' via ActivityPub', LOGGER_DEBUG); HTTPSignature::transmit($signed, $inbox, $uid); } @@ -796,7 +822,7 @@ class Transmitter $signed = LDSignature::sign($data, $owner); - logger('Deliver profile update for user ' . $uid . ' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG); + logger('Deliver profile update for user ' . $uid . ' to ' . $inbox . ' via ActivityPub', LOGGER_DEBUG); HTTPSignature::transmit($signed, $inbox, $uid); } @@ -854,7 +880,7 @@ class Transmitter } /** - * @brief + * @brief Reject a contact request or terminates the contact relation * * @param string $target Target profile * @param $id @@ -881,7 +907,7 @@ class Transmitter } /** - * @brief + * @brief Transmits a message that we don't want to follow this contact anymore * * @param string $target Target profile * @param integer $uid User ID From fa7cddc669036c2369103eefcc960d7b5343c9cd Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 5 Oct 2018 06:35:50 +0000 Subject: [PATCH 277/428] AP Bugfix: Following a soapbox now works / rapid follow/unfollow should work now --- src/Model/Contact.php | 6 ++++++ src/Protocol/ActivityPub/Processor.php | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 3ffd5b2af5..fa6966a0ef 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1917,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']); + } } } } diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 2e93e1bc18..c3fd88f0d2 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -283,7 +283,7 @@ class Processor $cid = Contact::getIdForURL($activity['owner'], $uid); if (!empty($cid)) { - $contact = DBA::selectFirst('contact', [], ['id' => $cid]); + $contact = DBA::selectFirst('contact', [], ['id' => $cid, 'network' => Protocol::NATIVE_SUPPORT]); } else { $contact = false; } From fe6e600dc5ace900d913d10e4b8518c0f0248239 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Fri, 5 Oct 2018 19:42:08 +0200 Subject: [PATCH 278/428] Adding "FRIENDICA_URL_PATH" to the automatic installation --- doc/Install.md | 4 ++- src/Core/Console/AutomaticInstallation.php | 33 ++++++++++++---------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/doc/Install.md b/doc/Install.md index 3854c32bce..427299c3ea 100644 --- a/doc/Install.md +++ b/doc/Install.md @@ -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 ` The username of the mysql/mariadb database login (env `MYSQL_USER` or `MYSQL_USERNAME`) - `-P|--dbpass ` The password of the mysql/mariadb database login (env `MYSQL_PASSWORD`) - `-d|--dbdata ` The name of the mysql/mariadb database (env `MYSQL_DATABASE`) -- `-b|--phppath ` The path of the PHP binary (env `FRIENDICA_PHP_PATH`) +- `-u|--urlpath ` The URL path of Friendica - f.e. '/friendica' (env `FRIENDICA_URL_PATH`) +- `-b|--phppath ` The path of the PHP binary (env `FRIENDICA_PHP_PATH`) - `-A|--admin ` The admin email address of Friendica (env `FRIENDICA_ADMIN_MAIL`) - `-T|--tz ` The timezone of Friendica (env `FRIENDICA_TZ`) - `-L|--land ` The language of Friendica (env `FRIENDICA_LANG`) diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index f0f3def2a0..9b6945ecd4 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -30,20 +30,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 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 The host of the mysql/mariadb database (env MYSQL_HOST) - -p|--dbport The port of the mysql/mariadb database (env MYSQL_PORT) - -d|--dbdata The name of the mysql/mariadb database (env MYSQL_DATABASE) - -U|--dbuser The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME) - -P|--dbpass The password of the mysql/mariadb database login (env MYSQL_PASSWORD) - -b|--phppath The path of the PHP binary (env FRIENDICA_PHP_PATH) - -A|--admin The admin email address of Friendica (env FRIENDICA_ADMIN_MAIL) - -T|--tz The timezone of Friendica (env FRIENDICA_TZ) - -L|--lang 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 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 The host of the mysql/mariadb database (env MYSQL_HOST) + -p|--dbport The port of the mysql/mariadb database (env MYSQL_PORT) + -d|--dbdata The name of the mysql/mariadb database (env MYSQL_DATABASE) + -U|--dbuser The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME) + -P|--dbpass The password of the mysql/mariadb database login (env MYSQL_PASSWORD) + -u|--urlpath The URL path of Friendica - f.e. '/friendica' (env FRIENDICA_URL_PATH) + -b|--phppath The path of the PHP binary (env FRIENDICA_PHP_PATH) + -A|--admin The admin email address of Friendica (env FRIENDICA_ADMIN_MAIL) + -T|--tz The timezone of Friendica (env FRIENDICA_TZ) + -L|--lang 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 +52,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 @@ -102,13 +104,14 @@ 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') : ''); + $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') : ''); $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( - $php_path, + $url_path, ((!empty($db_port)) ? $db_host . ':' . $db_port : $db_host), $db_user, $db_pass, From 924b21623cf63120fd259feb2f993227ea5b1a93 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Fri, 5 Oct 2018 19:51:14 +0200 Subject: [PATCH 279/428] Fixing tests for AutomaticInstallation --- .../AutomaticInstallationConsoleTest.php | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php index 79e379dcbc..f83edd88da 100644 --- a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php +++ b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php @@ -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', 'url_path', '/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,6 +265,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', 'url_path', '/friendica'); } public function testNoDatabaseConnection() @@ -288,20 +294,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 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 The host of the mysql/mariadb database (env MYSQL_HOST) - -p|--dbport The port of the mysql/mariadb database (env MYSQL_PORT) - -d|--dbdata The name of the mysql/mariadb database (env MYSQL_DATABASE) - -U|--dbuser The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME) - -P|--dbpass The password of the mysql/mariadb database login (env MYSQL_PASSWORD) - -b|--phppath The path of the PHP binary (env FRIENDICA_PHP_PATH) - -A|--admin The admin email address of Friendica (env FRIENDICA_ADMIN_MAIL) - -T|--tz The timezone of Friendica (env FRIENDICA_TZ) - -L|--lang 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 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 The host of the mysql/mariadb database (env MYSQL_HOST) + -p|--dbport The port of the mysql/mariadb database (env MYSQL_PORT) + -d|--dbdata The name of the mysql/mariadb database (env MYSQL_DATABASE) + -U|--dbuser The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME) + -P|--dbpass The password of the mysql/mariadb database login (env MYSQL_PASSWORD) + -b|--urlpath The URL path of Friendica - f.e. '/friendica' (env FRIENDICA_URL_PATH) + -b|--phppath The path of the PHP binary (env FRIENDICA_PHP_PATH) + -A|--admin The admin email address of Friendica (env FRIENDICA_ADMIN_MAIL) + -T|--tz The timezone of Friendica (env FRIENDICA_TZ) + -L|--lang 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 +316,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 From 9fbaaa1481a609563e00a40db64bdce5e02c5524 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 5 Oct 2018 19:26:20 +0000 Subject: [PATCH 280/428] We now can show "Friendica (AP)" as network name --- include/conversation.php | 2 +- src/Content/ContactSelector.php | 42 ++++++++++++++++++++++++--------- src/Object/Post.php | 2 +- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/include/conversation.php b/include/conversation.php index 1185e9dc3b..43854bb40f 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -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), diff --git a/src/Content/ContactSelector.php b/src/Content/ContactSelector.php index 6a701f25f3..298f2512ed 100644 --- a/src/Content/ContactSelector.php +++ b/src/Content/ContactSelector.php @@ -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,11 +70,11 @@ 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'), @@ -98,18 +100,36 @@ 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::ACTIVITYPUB, 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']); + } - if ($s == Protocol::ACTIVITYPUB) { - $networkname .= ' (AP)'; + // 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)'; + } } } } diff --git a/src/Object/Post.php b/src/Object/Post.php index efd7d4dc8d..35805e1fdd 100644 --- a/src/Object/Post.php +++ b/src/Object/Post.php @@ -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'], From 5ed1c12349d2dacb4f247afda3587ef2550e2a5f Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 5 Oct 2018 19:48:48 +0000 Subject: [PATCH 281/428] Send a follow request upon contact switch to AP --- src/Protocol/ActivityPub/Receiver.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 30d710702a..14b5e93bac 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -357,11 +357,11 @@ class Receiver } /** - * @brief + * @brief Switches existing contacts to ActivityPub * - * @param $cid + * @param integer $cid Contact ID * @param integer $uid User ID - * @param $url + * @param string $url Profile URL */ private static function switchContact($cid, $uid, $url) { @@ -370,7 +370,7 @@ class Receiver return; } - logger('Switch contact ' . $cid . ' (' . $profile['url'] . ') for user ' . $uid . ' from OStatus to ActivityPub'); + logger('Switch contact ' . $cid . ' (' . $profile['url'] . ') for user ' . $uid . ' to ActivityPub'); $photo = $profile['photo']; unset($profile['photo']); @@ -381,7 +381,11 @@ class Receiver Contact::updateAvatar($photo, $uid, $cid); - /// @todo Send a new follow request to be sure that the connection still exists + // Send a new follow request to be sure that the connection still exists + if (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); + } } /** From 5d7968bdf3e65738bfec5ec8df89c32e58540a51 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 5 Oct 2018 20:10:10 +0000 Subject: [PATCH 282/428] Avoid to do the follow stuff for the public user --- src/Protocol/ActivityPub/Receiver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 14b5e93bac..5c644176f0 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -382,7 +382,7 @@ class Receiver Contact::updateAvatar($photo, $uid, $cid); // Send a new follow request to be sure that the connection still exists - if (DBA::exists('contact', ['id' => $cid, 'rel' => [Contact::SHARING, Contact::FRIEND]])) { + 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); } From 065340dc320a165f90b0a1f81e104ebfd1aee087 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Fri, 5 Oct 2018 22:36:09 +0200 Subject: [PATCH 283/428] Creating Friendica\App\Mode for encapsulating the App Mode --- bin/auth_ejabberd.php | 2 +- index.php | 12 ++-- src/App.php | 72 ++----------------- src/App/Mode.php | 103 ++++++++++++++++++++++++++++ src/Core/Config.php | 10 +-- src/Core/Console/ArchiveContact.php | 2 +- src/Core/Console/Cache.php | 2 +- src/Core/Console/Config.php | 4 +- src/Core/PConfig.php | 10 +-- 9 files changed, 128 insertions(+), 89 deletions(-) create mode 100644 src/App/Mode.php diff --git a/bin/auth_ejabberd.php b/bin/auth_ejabberd.php index 7ad28c96f5..55917bf6d9 100755 --- a/bin/auth_ejabberd.php +++ b/bin/auth_ejabberd.php @@ -54,7 +54,7 @@ require_once "include/dba.php"; $a = new App(dirname(__DIR__)); -if ($a->mode === App::MODE_NORMAL) { +if (App\Mode::isNormal()) { $oAuth = new ExAuth(); $oAuth->readStdin(); } \ No newline at end of file diff --git a/index.php b/index.php index bccdebe7b0..0785faf585 100644 --- a/index.php +++ b/index.php @@ -36,7 +36,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 (App\Mode::has(App\Mode::LOCALCONFIGPRESENT) && !App\Mode::has(App\Mode::DBAVAILABLE)) { System::httpExit(500, ['title' => 'Error 500 - Internal Server Error', 'description' => 'Apologies but the website is unavailable at the moment.']); } @@ -48,7 +48,7 @@ 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 (!App\Mode::isInstall()) { if (Config::get('system', 'force_ssl') && ($a->get_scheme() == "http") && (intval(Config::get('system', 'ssl_policy')) == SSL_POLICY_FULL) && (substr(System::baseUrl(), 0, 8) == "https://") @@ -107,7 +107,7 @@ if (!empty($_SESSION['language']) && $_SESSION['language'] !== $lang) { L10n::loadTranslationTable($lang); } -if (!empty($_GET['zrl']) && $a->mode == App::MODE_NORMAL) { +if (!empty($_GET['zrl']) && App\Mode::isNormal()) { $a->query_string = Profile::stripZrls($a->query_string); if (!local_user()) { // Only continue when the given profile link seems valid @@ -130,7 +130,7 @@ if (!empty($_GET['zrl']) && $a->mode == App::MODE_NORMAL) { } } -if (!empty($_GET['owt']) && $a->mode == App::MODE_NORMAL) { +if (!empty($_GET['owt']) && App\Mode::isNormal()) { $token = $_GET['owt']; $a->query_string = Profile::stripQueryParam($a->query_string, 'owt'); Profile::openWebAuthInit($token); @@ -167,7 +167,7 @@ $_SESSION['last_updated'] = defaults($_SESSION, 'last_updated', []); // but we need "view" module for stylesheet if ($a->isInstallMode() && $a->module!="view") { $a->module = 'install'; -} elseif (!($a->mode & App::MODE_MAINTENANCEDISABLED) && $a->module != "view") { +} elseif (!App\Mode::has(App\Mode::MAINTENANCEDISABLED) && $a->module != "view") { $a->module = 'maintenance'; } else { check_url($a); @@ -320,7 +320,7 @@ if (file_exists($theme_info_file)) { /* initialise content region */ -if ($a->mode == App::MODE_NORMAL) { +if (App\Mode::isNormal()) { Addon::callHooks('page_content_top', $a->page['content']); } diff --git a/src/App.php b/src/App.php index 7622a1a0ce..f09c030b6c 100644 --- a/src/App.php +++ b/src/App.php @@ -6,6 +6,7 @@ namespace Friendica; use Detection\MobileDetect; use Exception; +use Friendica\App; use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\PConfig; @@ -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,7 +53,6 @@ class App public $argv; public $argc; public $module; - public $mode = App::MODE_INSTALL; public $strings; public $basepath; public $urlpath; @@ -326,13 +311,13 @@ class App $this->loadDatabase(); - $this->determineMode(); + App\Mode::determine($this->basepath); $this->determineUrlPath(); Config::load(); - if ($this->mode & self::MODE_DBAVAILABLE) { + if (App\Mode::has(App\Mode::DBAVAILABLE)) { Core\Addon::loadHooks(); $this->loadAddonConfig(); @@ -518,45 +503,6 @@ class App } } - /** - * 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()) { @@ -596,16 +542,6 @@ class App $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); - } - /** * @brief Returns the base filesystem path of the App * @@ -1467,7 +1403,7 @@ class App */ public function getCurrentTheme() { - if ($this->isInstallMode()) { + if (App\Mode::isInstall()) { return ''; } diff --git a/src/App/Mode.php b/src/App/Mode.php new file mode 100644 index 0000000000..189573e378 --- /dev/null +++ b/src/App/Mode.php @@ -0,0 +1,103 @@ +mode & App::MODE_DBCONFIGAVAILABLE)) { + if (!App\Mode::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 (!App\Mode::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 (!App\Mode::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 (!App\Mode::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 (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { return false; } diff --git a/src/Core/Console/ArchiveContact.php b/src/Core/Console/ArchiveContact.php index acdacbed1d..8a6bc1f7bf 100644 --- a/src/Core/Console/ArchiveContact.php +++ b/src/Core/Console/ArchiveContact.php @@ -56,7 +56,7 @@ HELP; throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); } - if ($a->mode === App::MODE_INSTALL) { + if (App\Mode::isInstall()) { throw new RuntimeException('Friendica isn\'t properly installed yet.'); } diff --git a/src/Core/Console/Cache.php b/src/Core/Console/Cache.php index d0bc427dee..2d3508894a 100644 --- a/src/Core/Console/Cache.php +++ b/src/Core/Console/Cache.php @@ -65,7 +65,7 @@ HELP; $this->out('Options: ' . var_export($this->options, true)); } - if (!($a->mode & App::MODE_DBCONFIGAVAILABLE)) { + if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { $this->out('Database isn\'t ready or populated yet, database cache won\'t be available'); } diff --git a/src/Core/Console/Config.php b/src/Core/Console/Config.php index db436b8394..d67f6cbb96 100644 --- a/src/Core/Console/Config.php +++ b/src/Core/Console/Config.php @@ -84,7 +84,7 @@ HELP; throw new CommandArgsException('Too many arguments'); } - if (!($a->mode & App::MODE_DBCONFIGAVAILABLE)) { + if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { $this->out('Database isn\'t ready or populated yet, showing file config only'); } @@ -143,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' && App\Mode::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'); } diff --git a/src/Core/PConfig.php b/src/Core/PConfig.php index 2b66189300..3c48a568cb 100644 --- a/src/Core/PConfig.php +++ b/src/Core/PConfig.php @@ -30,7 +30,7 @@ class PConfig extends BaseObject public static function init($uid) { // Database isn't ready or populated yet - if (!(self::getApp()->mode & App::MODE_DBCONFIGAVAILABLE)) { + if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { return; } @@ -55,7 +55,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 (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { return; } @@ -84,7 +84,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 (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { return; } @@ -113,7 +113,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 (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { return false; } @@ -139,7 +139,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 (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { return false; } From 947cc98cc43a82cb3e67b51a897009a7bd2629a0 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Fri, 5 Oct 2018 22:41:11 +0200 Subject: [PATCH 284/428] delete unused use --- src/App.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/App.php b/src/App.php index f09c030b6c..9a09bcfce0 100644 --- a/src/App.php +++ b/src/App.php @@ -6,7 +6,6 @@ namespace Friendica; use Detection\MobileDetect; use Exception; -use Friendica\App; use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\PConfig; From 51dbffd39697b794963eb6a9b87374e65a63f0aa Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 5 Oct 2018 21:00:40 +0000 Subject: [PATCH 285/428] Cache the AP delivery process --- src/Protocol/ActivityPub/Transmitter.php | 22 ++++++++++++++++++++++ src/Worker/APDelivery.php | 12 +++++++++--- src/Worker/Notifier.php | 3 +++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index bfbd9f9b4e..77688233a8 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -22,6 +22,7 @@ use Friendica\Model\Profile; use Friendica\Core\Config; use Friendica\Object\Image; use Friendica\Protocol\ActivityPub; +use Friendica\Core\Cache; /** * @brief ActivityPub Transmitter Protocol class @@ -480,6 +481,27 @@ class Transmitter return $type; } + /** + * @brief 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; + } + /** * @brief Creates an activity array for a given item id * diff --git a/src/Worker/APDelivery.php b/src/Worker/APDelivery.php index 3c2eba8d8f..039cdfbb3b 100644 --- a/src/Worker/APDelivery.php +++ b/src/Worker/APDelivery.php @@ -11,6 +11,14 @@ 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); @@ -23,12 +31,10 @@ class APDelivery extends BaseObject } elseif ($cmd == Delivery::PROFILEUPDATE) { ActivityPub\Transmitter::sendProfileUpdate($uid, $inbox); } else { - $data = ActivityPub\Transmitter::createActivityFromItem($item_id); + $data = ActivityPub\Transmitter::createCachedActivityFromItem($item_id); if (!empty($data)) { HTTPSignature::transmit($data, $inbox, $uid); } } - - return; } } diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index 8945a958fe..186422b6cc 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -433,6 +433,9 @@ class Notifier $inboxes = array_merge($inboxes, $parent_inboxes); } + // Fill the item cache + ActivityPub\Transmitter::createCachedActivityFromItem($item_id); + foreach ($inboxes as $inbox) { logger('Deliver ' . $item_id .' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG); From d72473fd512a63c2831b943834fae3efba3896b8 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 6 Oct 2018 01:13:29 +0200 Subject: [PATCH 286/428] moving boot::check_addons to Friendica\Core\Addon::check And extending Addon from BaseObject because of self::getApp() --- boot.php | 56 ----------------------------------- index.php | 2 +- src/Core/Addon.php | 74 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 67 insertions(+), 65 deletions(-) diff --git a/boot.php b/boot.php index b5c9166982..b1d5b593fd 100644 --- a/boot.php +++ b/boot.php @@ -673,62 +673,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 diff --git a/index.php b/index.php index bccdebe7b0..1a3e213513 100644 --- a/index.php +++ b/index.php @@ -172,7 +172,7 @@ if ($a->isInstallMode() && $a->module!="view") { } else { check_url($a); check_db(false); - check_addons($a); + Addon::check(); } Nav::setSelected('nothing'); diff --git a/src/Core/Addon.php b/src/Core/Addon.php index 4c20c96ad4..aa3a403f90 100644 --- a/src/Core/Addon.php +++ b/src/Core/Addon.php @@ -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 = 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)) { + 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()->get_basepath() . 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()->get_basepath() . 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, From eb1a2572249e7257ebe8e814657f42702571df24 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 6 Oct 2018 01:21:05 +0200 Subject: [PATCH 287/428] Used new select function --- src/Core/Addon.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/Addon.php b/src/Core/Addon.php index aa3a403f90..d5a7a6f1b4 100644 --- a/src/Core/Addon.php +++ b/src/Core/Addon.php @@ -31,9 +31,9 @@ class Addon extends BaseObject { $a = self::getApp(); - $r = q("SELECT * FROM `addon` WHERE `installed` = 1"); + $r = DBA::select('addon', [], ['installed' => 1]); if (DBA::isResult($r)) { - $installed = $r; + $installed = DBA::toArray($r); } else { $installed = []; } From 3ed9e7fe1d76156606264499bd5cf1d925efe7b0 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 5 Oct 2018 20:31:32 -0400 Subject: [PATCH 288/428] Replace remaining $a->isInstallMode() instances --- bin/daemon.php | 2 +- index.php | 4 ++-- src/Core/Console/GlobalCommunityBlock.php | 2 +- src/Core/Console/GlobalCommunitySilence.php | 2 +- src/Core/Console/Maintenance.php | 2 +- src/Core/Console/NewPassword.php | 2 +- src/Core/Console/PostUpdate.php | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/daemon.php b/bin/daemon.php index 159b20e159..e2bad90df5 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -34,7 +34,7 @@ require_once "include/dba.php"; $a = new App(dirname(__DIR__)); -if ($a->isInstallMode()) { +if (App\Mode::isInstall()) { die("Friendica isn't properly installed yet.\n"); } diff --git a/index.php b/index.php index 2bdda90f4a..f34b79867c 100644 --- a/index.php +++ b/index.php @@ -165,9 +165,9 @@ $_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 (App\Mode::isInstall() && $a->module != 'view') { $a->module = 'install'; -} elseif (!App\Mode::has(App\Mode::MAINTENANCEDISABLED) && $a->module != "view") { +} elseif (!App\Mode::has(App\Mode::MAINTENANCEDISABLED) && $a->module != 'view') { $a->module = 'maintenance'; } else { check_url($a); diff --git a/src/Core/Console/GlobalCommunityBlock.php b/src/Core/Console/GlobalCommunityBlock.php index f51ed95fe2..dbab4ff02c 100644 --- a/src/Core/Console/GlobalCommunityBlock.php +++ b/src/Core/Console/GlobalCommunityBlock.php @@ -56,7 +56,7 @@ HELP; throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); } - if ($a->isInstallMode()) { + if (App\Mode::isInstall()) { throw new \RuntimeException('Database isn\'t ready or populated yet'); } diff --git a/src/Core/Console/GlobalCommunitySilence.php b/src/Core/Console/GlobalCommunitySilence.php index 03101cdf0f..0dce00a7b1 100644 --- a/src/Core/Console/GlobalCommunitySilence.php +++ b/src/Core/Console/GlobalCommunitySilence.php @@ -65,7 +65,7 @@ HELP; throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); } - if ($a->isInstallMode()) { + if (App\Mode::isInstall()) { throw new RuntimeException('Database isn\'t ready or populated yet'); } diff --git a/src/Core/Console/Maintenance.php b/src/Core/Console/Maintenance.php index a3e3b80a7e..d693cb6e89 100644 --- a/src/Core/Console/Maintenance.php +++ b/src/Core/Console/Maintenance.php @@ -64,7 +64,7 @@ HELP; throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); } - if ($a->isInstallMode()) { + if (App\Mode::isInstall()) { throw new \RuntimeException('Database isn\'t ready or populated yet'); } diff --git a/src/Core/Console/NewPassword.php b/src/Core/Console/NewPassword.php index 2581d81cd0..56f3ae7c98 100644 --- a/src/Core/Console/NewPassword.php +++ b/src/Core/Console/NewPassword.php @@ -57,7 +57,7 @@ HELP; throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); } - if ($a->isInstallMode()) { + if (App\Mode::isInstall()) { throw new RuntimeException('Database isn\'t ready or populated yet'); } diff --git a/src/Core/Console/PostUpdate.php b/src/Core/Console/PostUpdate.php index 24ed514b5e..a77aae39de 100644 --- a/src/Core/Console/PostUpdate.php +++ b/src/Core/Console/PostUpdate.php @@ -50,7 +50,7 @@ HELP; return 0; } - if ($a->isInstallMode()) { + if (App\Mode::isInstall()) { throw new \RuntimeException('Database isn\'t ready or populated yet'); } From 9dbf8d0b9dd92f81fba27ad6c13ec2e52946621e Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 6 Oct 2018 02:09:27 +0000 Subject: [PATCH 289/428] Spaces --- src/Protocol/ActivityPub/Transmitter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 77688233a8..8d1623c098 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -490,7 +490,7 @@ class Transmitter */ public static function createCachedActivityFromItem($item_id) { - $cachekey = "APDelivery:createActivity:".$item_id; + $cachekey = 'APDelivery:createActivity:' . $item_id; $data = Cache::get($cachekey); if (!is_null($data)) { return $data; From f69c80b9e20d145e98d43ea8b428ae39775b4562 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 6 Oct 2018 03:16:38 +0000 Subject: [PATCH 290/428] AP delivery is relocated to the top of the notifier --- src/Worker/Notifier.php | 47 +++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index 186422b6cc..d40d9068fa 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -176,6 +176,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); @@ -422,27 +424,6 @@ class Notifier } } - $inboxes = []; - - if ($target_item['origin']) { - $inboxes = ActivityPub\Transmitter::fetchTargetInboxes($target_item, $uid); - } - - if ($parent['origin']) { - $parent_inboxes = ActivityPub\Transmitter::fetchTargetInboxes($parent, $uid); - $inboxes = array_merge($inboxes, $parent_inboxes); - } - - // 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); - } - // send salmon slaps to mentioned remote tags (@foo@example.com) in OStatus posts // They are especially used for notifications to OStatus users that don't follow us. if (!Config::get('system', 'dfrn_only') && count($url_recipients) && ($public_message || $push_notify) && $normal_mode) { @@ -527,6 +508,30 @@ 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); + } + + if ($parent['origin']) { + $parent_inboxes = ActivityPub\Transmitter::fetchTargetInboxes($parent, $uid); + $inboxes = array_merge($inboxes, $parent_inboxes); + } + + // 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']) || From 09302367d5d4116bad9c952f392ae930600c1f73 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 6 Oct 2018 03:17:44 +0000 Subject: [PATCH 291/428] Include AP in the contact search --- mod/acl.php | 6 ++++-- mod/contacts.php | 24 ++++++++++++------------ mod/network.php | 2 +- src/Core/ACL.php | 6 +++--- src/Model/GContact.php | 10 +++++----- 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/mod/acl.php b/mod/acl.php index f9589598dd..48c45f2934 100644 --- a/mod/acl.php +++ b/mod/acl.php @@ -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) ); diff --git a/mod/contacts.php b/mod/contacts.php index 8342906952..c33e9b6206 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -471,7 +471,7 @@ function contacts_content(App $a, $update = 0) _contact_drop($orig_record); info(L10n::t('Contact has been removed.') . EOL); - + goaway('contacts'); return; // NOTREACHED } @@ -544,7 +544,7 @@ function contacts_content(App $a, $update = 0) } $lblsuggest = (($contact['network'] === Protocol::DFRN) ? L10n::t('Suggest friends') : ''); - $poll_enabled = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]); + $poll_enabled = in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]); $nettype = L10n::t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact["url"])); @@ -635,15 +635,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 may 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, @@ -1085,7 +1085,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' : ''), @@ -1093,7 +1093,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' : ''), @@ -1102,7 +1102,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' : ''), diff --git a/mod/network.php b/mod/network.php index c630beb25f..58e147d1f7 100644 --- a/mod/network.php +++ b/mod/network.php @@ -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']; diff --git a/src/Core/ACL.php b/src/Core/ACL.php index ffe11363f5..0b48895d65 100644 --- a/src/Core/ACL.php +++ b/src/Core/ACL.php @@ -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; diff --git a/src/Model/GContact.php b/src/Model/GContact.php index 18d8171615..f979abef52 100644 --- a/src/Model/GContact.php +++ b/src/Model/GContact.php @@ -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"]); } From 41123162f14fa83cd566e24da8faafa04b40140f Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 6 Oct 2018 04:18:40 +0000 Subject: [PATCH 292/428] No @brief anymore --- src/Protocol/ActivityPub.php | 6 ++-- src/Protocol/ActivityPub/Processor.php | 34 +++++++++--------- src/Protocol/ActivityPub/Receiver.php | 20 +++++------ src/Protocol/ActivityPub/Transmitter.php | 46 ++++++++++++------------ 4 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index 0b7d527801..e7614afa99 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -42,7 +42,7 @@ class ActivityPub const CONTENT_TYPES = ['Note', 'Article', 'Video', 'Image']; const ACTIVITY_TYPES = ['Like', 'Dislike', 'Accept', 'Reject', 'TentativeAccept']; /** - * @brief Checks if the web request is done for the AP protocol + * Checks if the web request is done for the AP protocol * * @return is it AP? */ @@ -110,9 +110,9 @@ class ActivityPub } /** - * @brief + * Fetches activities from the outbox of a given profile and processes it * - * @param $url + * @param string $url * @param integer $uid User ID */ public static function fetchOutbox($url, $uid) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index c3fd88f0d2..f62566168b 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -17,12 +17,12 @@ use Friendica\Core\Config; use Friendica\Protocol\ActivityPub; /** - * @brief ActivityPub Protocol class + * ActivityPub Protocol class */ class Processor { /** - * @brief Converts mentions from Pleroma into the Friendica format + * Converts mentions from Pleroma into the Friendica format * * @param string $body * @@ -37,7 +37,7 @@ class Processor } /** - * @brief Constructs a string with tags for a given tag array + * Constructs a string with tags for a given tag array * * @param array $tags * @param boolean $sensitive @@ -67,7 +67,7 @@ class Processor } /** - * @brief + * * * @param $attachments * @param array $item @@ -101,7 +101,7 @@ class Processor } /** - * @brief + * * * @param array $activity * @param $body @@ -129,7 +129,7 @@ class Processor } /** - * @brief + * * * @param array $activity * @param $body @@ -146,7 +146,7 @@ class Processor } /** - * @brief Delete items + * Delete items * * @param array $activity * @param $body @@ -160,7 +160,7 @@ class Processor } /** - * @brief + * * * @param array $activity * @param $body @@ -177,7 +177,7 @@ class Processor } /** - * @brief + * * * @param array $activity * @param array $item @@ -234,7 +234,7 @@ class Processor } /** - * @brief + * * * @param $url * @param $child @@ -267,7 +267,7 @@ class Processor } /** - * @brief perform a "follow" request + * perform a "follow" request * * @param array $activity */ @@ -307,7 +307,7 @@ class Processor } /** - * @brief Update the given profile + * Update the given profile * * @param array $activity */ @@ -322,7 +322,7 @@ class Processor } /** - * @brief Delete the given profile + * Delete the given profile * * @param array $activity */ @@ -348,7 +348,7 @@ class Processor } /** - * @brief Accept a follow request + * Accept a follow request * * @param array $activity */ @@ -381,7 +381,7 @@ class Processor } /** - * @brief Reject a follow request + * Reject a follow request * * @param array $activity */ @@ -410,7 +410,7 @@ class Processor } /** - * @brief Undo activity like "like" or "dislike" + * Undo activity like "like" or "dislike" * * @param array $activity */ @@ -435,7 +435,7 @@ class Processor } /** - * @brief Activity to remove a follower + * Activity to remove a follower * * @param array $activity */ diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 5c644176f0..9ffd9c3bc4 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -37,7 +37,7 @@ use Friendica\Protocol\ActivityPub; class Receiver { /** - * @brief Checks if the web request is done for the AP protocol + * Checks if the web request is done for the AP protocol * * @return is it AP? */ @@ -48,7 +48,7 @@ class Receiver } /** - * @brief + * * * @param $body * @param $header @@ -104,7 +104,7 @@ class Receiver } /** - * @brief + * * * @param array $activity * @param integer $uid User ID @@ -174,7 +174,7 @@ class Receiver } /** - * @brief + * * * @param array $activity * @param $body @@ -271,7 +271,7 @@ class Receiver } /** - * @brief + * * * @param array $activity * @param $actor @@ -357,7 +357,7 @@ class Receiver } /** - * @brief Switches existing contacts to ActivityPub + * Switches existing contacts to ActivityPub * * @param integer $cid Contact ID * @param integer $uid User ID @@ -389,7 +389,7 @@ class Receiver } /** - * @brief + * * * @param $receivers * @param $actor @@ -414,7 +414,7 @@ class Receiver } /** - * @brief + * * * @param $object_data * @param array $activity @@ -442,7 +442,7 @@ class Receiver } /** - * @brief + * * * @param $object_id * @param $object @@ -495,7 +495,7 @@ class Receiver } /** - * @brief + * * * @param $object * diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 8d1623c098..7d9d6626ce 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -42,7 +42,7 @@ use Friendica\Core\Cache; class Transmitter { /** - * @brief collects the lost of followers of the given owner + * collects the lost of followers of the given owner * * @param array $owner Owner array * @param integer $page Page number @@ -89,7 +89,7 @@ class Transmitter } /** - * @brief Create list of following contacts + * Create list of following contacts * * @param array $owner Owner array * @param integer $page Page numbe @@ -136,7 +136,7 @@ class Transmitter } /** - * @brief Public posts for the given owner + * Public posts for the given owner * * @param array $owner Owner array * @param integer $page Page numbe @@ -238,7 +238,7 @@ class Transmitter } /** - * @brief Returns an array with permissions of a given item array + * Returns an array with permissions of a given item array * * @param array $item * @@ -291,7 +291,7 @@ class Transmitter } /** - * @brief Creates an array of permissions from an item thread + * Creates an array of permissions from an item thread * * @param array $item * @@ -379,7 +379,7 @@ class Transmitter } /** - * @brief Fetches a list of inboxes of followers of a given user + * Fetches a list of inboxes of followers of a given user * * @param integer $uid User ID * @@ -406,7 +406,7 @@ class Transmitter } /** - * @brief Fetches an array of inboxes for the given item and user + * Fetches an array of inboxes for the given item and user * * @param array $item * @param integer $uid User ID @@ -450,7 +450,7 @@ class Transmitter } /** - * @brief Returns the activity type of a given item + * Returns the activity type of a given item * * @param array $item * @@ -482,7 +482,7 @@ class Transmitter } /** - * @brief Creates the activity or fetches it from the cache + * Creates the activity or fetches it from the cache * * @param integer $item_id * @@ -503,7 +503,7 @@ class Transmitter } /** - * @brief Creates an activity array for a given item id + * 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? @@ -569,7 +569,7 @@ class Transmitter } /** - * @brief Creates an object array for a given item id + * Creates an object array for a given item id * * @param integer $item_id * @@ -590,7 +590,7 @@ class Transmitter } /** - * @brief Returns a tag array for a given item array + * Returns a tag array for a given item array * * @param array $item * @@ -619,7 +619,7 @@ class Transmitter } /** - * @brief Adds attachment data to the JSON document + * Adds attachment data to the JSON document * * @param array $item Data of the item that is to be posted * @param text $type Object type @@ -674,7 +674,7 @@ class Transmitter } /** - * @brief Remove image elements and replaces them with links to the image + * Remove image elements and replaces them with links to the image * * @param string $body * @@ -692,7 +692,7 @@ class Transmitter } /** - * @brief Fetches the "context" value for a givem item array from the "conversation" table + * Fetches the "context" value for a givem item array from the "conversation" table * * @param array $item * @@ -712,7 +712,7 @@ class Transmitter } /** - * @brief Returns if the post contains sensitive content ("nsfw") + * Returns if the post contains sensitive content ("nsfw") * * @param integer $item_id * @@ -725,7 +725,7 @@ class Transmitter } /** - * @brief Creates a note/article object array + * Creates a note/article object array * * @param array $item * @@ -797,7 +797,7 @@ class Transmitter } /** - * @brief Transmits a profile deletion to a given inbox + * Transmits a profile deletion to a given inbox * * @param integer $uid User ID * @param string $inbox Target inbox @@ -823,7 +823,7 @@ class Transmitter } /** - * @brief Transmits a profile change to a given inbox + * Transmits a profile change to a given inbox * * @param integer $uid User ID * @param string $inbox Target inbox @@ -849,7 +849,7 @@ class Transmitter } /** - * @brief Transmits a given activity to a target + * Transmits a given activity to a target * * @param array $activity * @param string $target Target profile @@ -875,7 +875,7 @@ class Transmitter } /** - * @brief Transmit a message that the contact request had been accepted + * Transmit a message that the contact request had been accepted * * @param string $target Target profile * @param $id @@ -902,7 +902,7 @@ class Transmitter } /** - * @brief Reject a contact request or terminates the contact relation + * Reject a contact request or terminates the contact relation * * @param string $target Target profile * @param $id @@ -929,7 +929,7 @@ class Transmitter } /** - * @brief Transmits a message that we don't want to follow this contact anymore + * Transmits a message that we don't want to follow this contact anymore * * @param string $target Target profile * @param integer $uid User ID From 4a7aad3ec898b7713967a67f6c7063e3f5ab5b73 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sat, 6 Oct 2018 10:02:14 +0200 Subject: [PATCH 293/428] PL translation update THX waldis --- view/lang/pl/messages.po | 1880 +++++++++++++++++++------------------- view/lang/pl/strings.php | 423 ++++----- 2 files changed, 1178 insertions(+), 1125 deletions(-) diff --git a/view/lang/pl/messages.po b/view/lang/pl/messages.po index cf922f22f6..fc1e93a206 100644 --- a/view/lang/pl/messages.po +++ b/view/lang/pl/messages.po @@ -4,43 +4,60 @@ # # Translators: # Adam Jurkiewicz , 2012 +# Adam Jurkiewicz , 2012 # julia.domagalska , 2013,2015 # julia.domagalska , 2012-2013 # Daria Początek , 2012 # Cyryl Sochacki , 2013 # czarnystokrotek , 2012 -# Daria Początek , 2013 +# czarnystokrotek , 2012 +# Daria Początek , 2012-2013 # Radek , 2012 +# emilia.krawczyk , 2012 # TORminator , 2014 +# Filip Bugaj , 2012 # Hubert Kościański , 2012 +# Hubert Kościański , 2012 +# Jakob , 2012 # Jakob , 2012 # Mateusz Mikos , 2012 # Filip Bugaj , 2012 +# julia.domagalska , 2013,2015 # Karolina , 2012 -# Karolina , 2013 +# Karolina , 2012-2013 # szymon.filip , 2013 # szymon.filip , 2012 +# Lea1995polish , 2012 +# Magdalena Gazda , 2013 # Mai Anh Nguyen , 2013 +# Marcin Klessa , 2012 +# Marcin Mikołajczak , 2018 # Mariusz Pisz , 2013 +# Mateusz Mikos , 2012 # Lea1995polish , 2012 # Magdalena Gazda , 2013 # mhnxo , 2012 +# mhnxo , 2012 +# Michalina , 2012 # Michalina , 2012 # Marcin Klessa , 2012 # Piotr Blonkowski , 2012-2013 -# Radek , 2013 +# Radek , 2012-2013 # emilia.krawczyk , 2012 # Sam, 2013 +# Sam, 2013 # rcmaniac , 2012-2013 +# szymon.filip , 2012-2013 # Tobias Diekershoff , 2018 +# TORminator , 2014 # Waldemar Stoczkowski , 2018 # Waldemar Stoczkowski , 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 \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 "%2$d people don't like this" -msgstr "%2$d ludzi nie lubi tego " +msgstr "%2$d ludzi nie lubi tego" #: include/conversation.php:1042 #, php-format @@ -755,7 +772,7 @@ msgstr "%2$dosoby 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 "%2$dludzie 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 "%2$d people attend maybe" -msgstr "%2$dprzyjacielemogą uczestniczyć " +msgstr "Możliwe, że %2$d osoby 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 everybody" @@ -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 "

    What next

    " msgstr "

    Co dalej

    " -#: 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 registration page " @@ -1918,83 +1935,83 @@ msgid "" " administrator email. This will allow you to enter the site admin panel." msgstr "Przejdź do strony rejestracji 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 not published." -msgstr "Profil nie jest opublikowany" +msgstr "Profil nie jest opublikowany." #: 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 php " "bin/console.php dbstructure toinnodb of your Friendica installation for" " an automatic conversion.
    " -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 tutaj przewodnik, który może być pomocny w konwersji silników stołowych. Możesz także użyć polecenia php bin/console.php dbstructure toinnodb instalacji Friendica do automatycznej konwersji.
    " +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 tutaj przewodnik, który może być pomocny w konwersji silników tabel. Możesz także użyć polecenia php bin/console.php dbstructure toinnodb instalacji Friendica, aby dokonać automatycznej konwersji.
    " #: 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 "" -"%s is not reachable on your system. This is a servere " -"configuration issue that prevents the communication.. See the" -" installation page for help." -msgstr "%snie jest osiągalny w twoim systemie. Jest to problem konfiguracji sieci, który uniemożliwia komunikację. Zobacz pomoc na stronie instalacji." +"%s is not reachable on your system. This is a severe " +"configuration issue that prevents server to server communication. See the installation page for help." +msgstr "%s 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 stronie instalacji." #: 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 may still be visible" msgstr "Odpowiedzi/kliknięcia \"lubię to\" do twoich publicznych postów nadal mogą 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 -msgid "Unblocked" -msgstr "Odblokowany" - #: mod/contacts.php:750 +msgid "Unblocked" +msgstr "Odblokowane" + +#: mod/contacts.php:753 msgid "Only show unblocked contacts" msgstr "Pokaż tylko odblokowane kontakty" -#: mod/contacts.php:755 -msgid "Blocked" -msgstr "Zablokowany" - #: mod/contacts.php:758 +msgid "Blocked" +msgstr "Zablokowane" + +#: mod/contacts.php:761 msgid "Only show blocked contacts" msgstr "Pokaż tylko zablokowane kontakty" -#: mod/contacts.php:763 -msgid "Ignored" -msgstr "Zignorowany" - #: mod/contacts.php:766 +msgid "Ignored" +msgstr "Ignorowane" + +#: 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 -msgid "Hidden" -msgstr "Ukryty" - #: mod/contacts.php:782 +msgid "Hidden" +msgstr "Ukryte" + +#: 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 " Marital Status:" msgstr " 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 publiczny profil.
    Może %s wrote the following post" msgstr "%snapisał następującypost" -#: local/testshare.php:158 src/Content/Text/BBCode.php:991 +#: local/testshare.php:158 src/Content/Text/BBCode.php:992 #, php-format msgid "%2$s %3$s" msgstr "%2$s%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 -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" - #: 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źć PHP dla wiersza poleceń w PATH serwera." + +#: 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 'Setup the worker'" msgstr "Jeśli nie masz zainstalowanej na serwerze wersji PHP z wierszem poleceń, nie będziesz mógł uruchomić przetwarzania w tle. Zobacz 'Konfiguracja pracownika'" -#: 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 -msgid "libCurl PHP module" -msgstr "Moduł libCurl PHP" - #: src/Core/Install.php:226 +msgid "libCurl PHP module" +msgstr "Moduł PHP libCurl" + +#: 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 -msgid "mb_string PHP module" -msgstr "Moduł mb_string PHP" - #: src/Core/Install.php:230 +msgid "mb_string PHP module" +msgstr "Moduł PHP mb_string" + +#: 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" diff --git a/view/lang/pl/strings.php b/view/lang/pl/strings.php index 82876b12ac..b76d61dae3 100644 --- a/view/lang/pl/strings.php +++ b/view/lang/pl/strings.php @@ -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["%2\$d people like this"] = "%2\$d ludzi lubi to"; $a->strings["%s like this."] = "%s lubię to."; -$a->strings["%2\$d people don't like this"] = "%2\$d ludzi nie lubi tego "; +$a->strings["%2\$d people don't like this"] = "%2\$d ludzi nie lubi tego"; $a->strings["%s don't like this."] = "%s nie lubię tego."; $a->strings["%2\$d people attend"] = "%2\$dosoby uczestniczą"; -$a->strings["%s attend."] = "%suczestniczy"; +$a->strings["%s attend."] = "%s uczestniczy."; $a->strings["%2\$d people don't attend"] = "%2\$dludzie nie uczestniczą"; -$a->strings["%s don't attend."] = "%s nie uczestnicz"; -$a->strings["%2\$d people attend maybe"] = "%2\$dprzyjacielemogą uczestniczyć "; -$a->strings["%s attend maybe."] = "%sbyć może uczestniczyć. "; +$a->strings["%s don't attend."] = "%s nie uczestniczy."; +$a->strings["%2\$d people attend maybe"] = "Możliwe, że %2\$d osoby będą uczestniczyć"; +$a->strings["%s attend maybe."] = "%sbyć może uczestniczyć."; $a->strings["Visible to everybody"] = "Widoczne dla wszystkich"; $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["WARNING: This is highly advanced and if you enter incorrect information your communications with this contact may stop working."] = "OSTRZEŻENIE: Jest to bardzo zaawansowane i jeśli wprowadzisz niepoprawne informacje, twoja komunikacja z tym kontaktem może przestać działać."; $a->strings["Please use your browser 'Back' button now if you are uncertain what to do on this page."] = "Jeśli nie jesteś pewien, co zrobić na tej stronie, użyj teraz 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 not published."] = "Profil nie jest opublikowany"; +$a->strings["Profile is not published."] = "Profil nie jest opublikowany."; $a->strings["Your Identity Address is '%s' or '%s'."] = "Twój adres tożsamości to '%s' 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:
    login: %s
    password: %s

    You can change your password after login."] = "Nie udało się wysłać wiadomości e-mail. Tutaj szczegóły twojego konta:
    login: %s
    hasło: %s

    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 'nickname@%s'."] = "Wybierz pseudonim profilu. Nazwa musi zaczynać się od znaku tekstowego. Twój adres profilu na tej stronie będzie wówczas 'pseudonimem%s'."; -$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 Friendi.ca to learn more about the Friendica project."] = "Odwiedź stronę Friendi.ca 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 Terms of Service of this node."] = "Przeczytaj o Warunkach świadczenia usług 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 default 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 Add New Contact 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 Dodaj nowy kontakt."; @@ -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 Settings page after successful login."] = "Twoje hasło może być zmienione w Ustawieniach 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 here for a guide that may be helpful converting the table engines. You may also use the command php bin/console.php dbstructure toinnodb of your Friendica installation for an automatic conversion.
    "] = "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 tutaj przewodnik, który może być pomocny w konwersji silników stołowych. Możesz także użyć polecenia php bin/console.php dbstructure toinnodb instalacji Friendica do automatycznej konwersji.
    "; +$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 here for a guide that may be helpful converting the table engines. You may also use the command php bin/console.php dbstructure toinnodb of your Friendica installation for an automatic conversion.
    "] = "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 tutaj przewodnik, który może być pomocny w konwersji silników tabel. Możesz także użyć polecenia php bin/console.php dbstructure toinnodb instalacji Friendica, aby dokonać automatycznej konwersji.
    "; $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 .htconfig.php. See the Config help page 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 .htconfig.php. Zobacz stronę pomocy konfiguracji, aby uzyskać pomoc dotyczącą przejścia."; -$a->strings["%s is not reachable on your system. This is a servere configuration issue that prevents the communication.. See the installation page for help."] = "%snie jest osiągalny w twoim systemie. Jest to problem konfiguracji sieci, który uniemożliwia komunikację. Zobacz pomoc na stronie instalacji."; +$a->strings["%s is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See the installation page for help."] = "%s 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 stronie instalacji."; $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 ://"] = "Nie można zanalizować podstawowego adresu URL. Musi mieć co najmniej : //"; -$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 - change theme settings"] = "Domyślny motyw systemu - może być nadpisany przez profil użytkownika zmień ustawienia motywów"; $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 public profile.
    It may be visible to anybody using the internet."] = "To jest Twój publiczny profil.
    Może 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 'Setup the worker'"] = "Jeśli nie masz zainstalowanej na serwerze wersji PHP z wierszem poleceń, nie będziesz mógł uruchomić przetwarzania w tle. Zobacz 'Konfiguracja pracownika'"; $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 account settings. If the user wants to delete their account they can do so at %1\$s/removeme. 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 ustawień konta. Jeśli użytkownik chce usunąć swoje konto, może to zrobić w%1\$s / Usuń mnie. 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 may 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 mogą 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ść"; From f361947044779f77e2cf6dbcf9028821593b3033 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sat, 6 Oct 2018 10:03:04 +0200 Subject: [PATCH 294/428] CS translation update THX Aditoo --- view/lang/cs/messages.po | 1605 +++++++++++++++++++------------------- view/lang/cs/strings.php | 181 ++--- 2 files changed, 911 insertions(+), 875 deletions(-) diff --git a/view/lang/cs/messages.po b/view/lang/cs/messages.po index 7b87e7d327..81d0eb6c16 100644 --- a/view/lang/cs/messages.po +++ b/view/lang/cs/messages.po @@ -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 "

    What next

    " msgstr "

    Co dál

    " -#: 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 registration page " @@ -1891,83 +1891,83 @@ msgid "" " administrator email. This will allow you to enter the site admin panel." msgstr "Přejděte k registrační stránce 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. %s). Your profile will be visible in public." -msgstr "Váš profil bude publikován v globálních adresářich Friendica (např. %s). Váš profil bude veřejně viditelný." +msgstr "Váš profil bude publikován v globálních adresářích Friendica (např. %s). 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:38 mod/unfollow.php:88 +msgid "You aren't following this contact." +msgstr "Tento kontakt nesledujete." -#: 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: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:
    login: %s
    " "password: %s

    You can change your password after login." -msgstr "Nepovedlo se odeslat emailovou zprávu. Zde jsou detaily Vašeho účtu:
    přihlašovací jméno: %s
    heslo: %s

    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:
    přihlašovací jméno: %s
    heslo: %s

    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:82 +#: mod/babel.php:84 +msgid "Markdown::convert (raw HTML)" +msgstr "Markdown::convert (hrubé 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 "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 "Zablokované 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 "" -"%s is not reachable on your system. This is a servere " -"configuration issue that prevents the communication.. See the" -" installation page for help." -msgstr "%s není na Vašem systému dosažitelné. Tohle je závažná chyba konfigurace, která brání komunikaci. Pro pomoc navštivte stránku instalace." +"%s is not reachable on your system. This is a severe " +"configuration issue that prevents server to server communication. See the installation page for help." +msgstr "%s 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 stránku instalace." #: 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 %1$s.\\r\\n
    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 may still be visible" msgstr "Odpovědi/oblíbení na Vaše veřejné příspěvky mohou 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 " Marital Status:" msgstr " 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 -msgid "Show Newest First" -msgstr "Zobrazit nejprve nejnovější:" - #: mod/photos.php:1194 -msgid "Show Oldest First" -msgstr "Zobrazit nejprve nejstarší:" +msgid "Show Newest First" +msgstr "Zobrazit nejprve nejnovější" -#: mod/photos.php:1215 mod/photos.php:1693 +#: mod/photos.php:1196 +msgid "Show Oldest First" +msgstr "Zobrazit nejprve nejstarší" + +#: 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 "" "%s wrote the following post" msgstr "%s napsal/a následující příspěvek" -#: local/testshare.php:158 src/Content/Text/BBCode.php:991 +#: local/testshare.php:158 src/Content/Text/BBCode.php:992 #, php-format msgid "%2$s %3$s" msgstr "%2$s %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 'Setup the worker'" 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 \"Nastavte pracovníka\"" -#: 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řijímat přímé/osobní sdělení." +msgstr "Omezený profil. Tato osoba nebude schopna od Vás přijímat pří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 " "may 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í může 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í může 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" diff --git a/view/lang/cs/strings.php b/view/lang/cs/strings.php index 753b0e51da..0b9a2d6d98 100644 --- a/view/lang/cs/strings.php +++ b/view/lang/cs/strings.php @@ -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 local directory. Your profile details may be publicly visible depending on the system settings."] = "Váš profil bude publikován v místním adresáři 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. %s). Your profile will be visible in public."] = "Váš profil bude publikován v globálních adresářich Friendica (např. %s). Váš profil bude veřejně viditelný."; +$a->strings["Your profile will be published in the global friendica directories (e.g. %s). Your profile will be visible in public."] = "Váš profil bude publikován v globálních adresářích Friendica (např. %s). 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:
    login: %s
    password: %s

    You can change your password after login."] = "Nepovedlo se odeslat emailovou zprávu. Zde jsou detaily Vašeho účtu:
    přihlašovací jméno: %s
    heslo: %s

    Své heslo si můžete změnit po přihlášení."; +$a->strings["Failed to send email message. Here your accout details:
    login: %s
    password: %s

    You can change your password after login."] = "Nepovedlo se odeslat e-mailovou zprávu. Zde jsou detaily Vašeho účtu:
    přihlašovací jméno: %s
    heslo: %s

    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 Add New Contact 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 Přidat nový kontakt."; $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 help pages may be consulted for detail on other program features and resources."] = "Na stránkách Nápověda 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 EU-GDPR."] = "Ukázat některé informace ohledně potřebných informací k provozování serveru podle například Obecného nařízení o ochraně osobních údajů EU (GDPR)"; $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"] = "Zablokované 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 Auto Discovered Contact Directory 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 .htconfig.php. See the Config help page 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 .htconfig.php. Pro pomoc při přechodu navštivte stránku Config v sekci nápovědy."; -$a->strings["%s is not reachable on your system. This is a servere configuration issue that prevents the communication.. See the installation page for help."] = "%s není na Vašem systému dosažitelné. Tohle je závažná chyba konfigurace, která brání komunikaci. Pro pomoc navštivte stránku instalace."; +$a->strings["%s is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See the installation page for help."] = "%s 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 stránku instalace."; $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 ://"] = "Nelze zpracovat výchozí url adresu. Musí obsahovat alespoň ://"; $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 the-federation.info 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 the-federation.info."; $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 %1\$s log file.\\r\\n
    Check to see if file %1\$s exist and is readable."] = "Chyba při otevírání záznamu %1\$s.\\r\\n
    Zkontrolujte, jestli soubor %1\$s existuje a může se číst."; $a->strings["Couldn't open %1\$s log file.\\r\\n
    Check to see if file %1\$s is readable."] = "Nelze otevřít záznam %1\$s.\\r\\n
    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 this profile."] = "Jste přihlášen/a pod nesprávnou identitou. Prosím, přihlaste se do tohoto 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 may 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["%s wrote the following post"] = "%s napsal/a následující příspěvek"; @@ -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 account settings. If the user wants to delete their account they can do so at %1\$s/removeme. 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 nastavení účtu. Pokud by chtěl uživatel svůj účet smazat, může tak učinit na stránce %1\$s/removeme. 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řijímat pří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řijímat pří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 may 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í může 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 may 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í může 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í"; From 632dd93145f3d5200d1fbc85c8314f5318baa6c1 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Sat, 6 Oct 2018 10:12:37 +0200 Subject: [PATCH 295/428] DE translation update --- view/lang/de/messages.po | 1445 +++++++++++++++++++------------------- view/lang/de/strings.php | 27 +- 2 files changed, 754 insertions(+), 718 deletions(-) diff --git a/view/lang/de/messages.po b/view/lang/de/messages.po index 1a610dab32..841fe98d15 100644 --- a/view/lang/de/messages.po +++ b/view/lang/de/messages.po @@ -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 \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 "

    What next

    " msgstr "

    Wie geht es weiter?

    " -#: 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 registration page " @@ -1903,83 +1903,83 @@ msgid "" " administrator email. This will allow you to enter the site admin panel." msgstr "Du solltest nun die Seite zur Nutzerregistrierung 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: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 "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 "" -"%s is not reachable on your system. This is a servere " -"configuration issue that prevents the communication.. See the" -" installation page for help." +"%s is not reachable on your system. This is a severe " +"configuration issue that prevents server to server communication. See the installation page for help." msgstr "%s konnte von deinem System nicht aufgerufen werden. Dies deitet auf ein schwerwiegendes Problem deiner Konfiguration hin. Bitte konsultiere die Installations-Dokumentation 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 may still be visible" msgstr "Antworten/Likes auf deine öffentlichen Beiträge könnten 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 " Marital Status:" msgstr " 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 "" "%s wrote the following post" msgstr "%s schrieb den folgenden Beitrag" -#: local/testshare.php:158 src/Content/Text/BBCode.php:991 +#: local/testshare.php:158 src/Content/Text/BBCode.php:992 #, php-format msgid "%2$s %3$s" msgstr "%2$s %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 'Setup the worker'" msgstr "Wenn auf deinem Server keine Kommandozeilenversion von PHP installiert ist, kannst du den Hintergrundprozess nicht einrichten. Hier findest du alternative Möglichkeiten'für das Worker Setup'" -#: 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 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" diff --git a/view/lang/de/strings.php b/view/lang/de/strings.php index 675f995a26..f80bf544bb 100644 --- a/view/lang/de/strings.php +++ b/view/lang/de/strings.php @@ -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 .htconfig.php. See the Config help page 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 .htconfig.php. Wie die Übertragung der Werte aussehen muss kannst du der Konfiguration Hilfeseite entnehmen."; -$a->strings["%s is not reachable on your system. This is a servere configuration issue that prevents the communication.. See the installation page for help."] = "%s konnte von deinem System nicht aufgerufen werden. Dies deitet auf ein schwerwiegendes Problem deiner Konfiguration hin. Bitte konsultiere die Installations-Dokumentation zum Beheben des Problems."; +$a->strings["%s is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See the installation page for help."] = "%s konnte von deinem System nicht aufgerufen werden. Dies deitet auf ein schwerwiegendes Problem deiner Konfiguration hin. Bitte konsultiere die Installations-Dokumentation 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 account settings. If the user wants to delete their account they can do so at %1\$s/removeme. 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 Kontoeinstellungen aus exportieren. Wenn ein Nutzer wünscht das Nutzerkonto zu löschen, so ist dies jederzeit unter %1\$s/removeme 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"; From 510032444f7d8f51a196b0b20792ebcc21a883e0 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 6 Oct 2018 08:51:52 +0000 Subject: [PATCH 296/428] The owner of a "like" should be the author --- src/Model/Item.php | 4 ++-- src/Protocol/Diaspora.php | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index 19ab371d7c..f2d4a89815 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3111,7 +3111,7 @@ 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::createUUID(), @@ -3125,7 +3125,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, diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 551971e504..b5ecfcefcc 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -1969,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); From 17019772a4a3ce7b55fbe7930e9902d86ae39b6f Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Sat, 6 Oct 2018 11:37:15 +0200 Subject: [PATCH 297/428] Fix (short) profile editing showing 'e' for martial and sexual preference --- mod/profiles.php | 4 ++-- view/theme/frio/templates/profile_edit.tpl | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mod/profiles.php b/mod/profiles.php index 76491c553e..7d0c3178cf 100644 --- a/mod/profiles.php +++ b/mod/profiles.php @@ -615,10 +615,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']], diff --git a/view/theme/frio/templates/profile_edit.tpl b/view/theme/frio/templates/profile_edit.tpl index cd4ed1816f..89353e1a6c 100644 --- a/view/theme/frio/templates/profile_edit.tpl +++ b/view/theme/frio/templates/profile_edit.tpl @@ -169,7 +169,7 @@
    - {{$marital}} + {{$marital.selector}}
    @@ -179,7 +179,7 @@
    - {{$sexual}} + {{$sexual.selector}}
    @@ -318,10 +318,10 @@ - + - + From acf31ab64b0d937da455d6363d7810b37a2d7bd9 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 6 Oct 2018 09:38:51 +0000 Subject: [PATCH 298/428] Additional check to ensure that the owner of an activity is always the author --- src/Protocol/DFRN.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 1ab4d8f9e4..4d61f9aee0 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -2349,6 +2349,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; } From 6b374c32a2b05bf65311ac704ef1b6db3ea85834 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 6 Oct 2018 13:16:52 +0000 Subject: [PATCH 299/428] Improved AP distribution / Only process trusted content --- src/Protocol/ActivityPub/Receiver.php | 1 + src/Worker/Notifier.php | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 9ffd9c3bc4..d3b38f9ee3 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -208,6 +208,7 @@ class Receiver if (!$trust_source) { logger('No trust for activity type "' . $activity['type'] . '", so we quit now.', LOGGER_DEBUG); + return; } switch ($activity['type']) { diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index d40d9068fa..b57c81db77 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -20,6 +20,7 @@ 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'; @@ -514,6 +515,12 @@ class Notifier 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']) { @@ -521,6 +528,11 @@ class Notifier $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); From a413ce15aa14480f9c1b98f8f856b883fc6bb5d6 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 6 Oct 2018 13:28:17 +0000 Subject: [PATCH 300/428] "name" must be plaintext --- src/Protocol/ActivityPub/Transmitter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 7d9d6626ce..081ba0b739 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -773,7 +773,7 @@ class Transmitter $data['context'] = self::fetchContextURLForItem($item); if (!empty($item['title'])) { - $data['name'] = BBCode::convert($item['title'], false, 7); + $data['name'] = BBCode::toPlaintext($item['title'], false); } $body = $item['body']; From 389a651005d13677c49fef60c59943eb4a002b8b Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 6 Oct 2018 14:02:23 +0000 Subject: [PATCH 301/428] Transmit the Diaspora GUID with activities (Like, Dislike, ...) --- src/Protocol/ActivityPub/Receiver.php | 4 ++++ src/Protocol/ActivityPub/Transmitter.php | 1 + 2 files changed, 5 insertions(+) diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index d3b38f9ee3..1c237f79dc 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -432,6 +432,10 @@ class Receiver $object_data['updated'] = $activity['updated']; } + if (!empty($activity['diaspora:guid']) && empty($object_data['diaspora:guid'])) { + $object_data['diaspora:guid'] = $activity['diaspora:guid']; + } + if (!empty($activity['inReplyTo']) && empty($object_data['parent-uri'])) { $object_data['parent-uri'] = JsonLD::fetchElement($activity, 'inReplyTo', 'id'); } diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 081ba0b739..9fad787b1b 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -554,6 +554,7 @@ class Transmitter } elseif ($data['type'] == 'Undo') { $data['object'] = self::createActivityFromItem($item_id, true); } else { + $data['diaspora:guid'] = $item['guid']; $data['object'] = $item['thr-parent']; } From 31148e25cf6d800851064813689f8fba6340fb5c Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 6 Oct 2018 16:27:20 +0200 Subject: [PATCH 302/428] Changing Friendica\App\Mode from static methods to public methods - Changing from static methods to public methods - Adding dev-composer-dependency Mockery for static method mocking (f.e. Config, DBA) - Adding ModeTest with Mocking - removing bootstrap from phpunit.xml because of double loading tests\bootstrap.php --- bin/auth_ejabberd.php | 4 +- bin/daemon.php | 2 +- composer.json | 3 +- composer.lock | 203 +++++++++++++++++++- index.php | 14 +- phpunit.xml | 1 - src/App.php | 30 ++- src/App/Mode.php | 58 ++++-- src/Core/Config.php | 10 +- src/Core/Console/ArchiveContact.php | 4 +- src/Core/Console/Cache.php | 2 +- src/Core/Console/Config.php | 4 +- src/Core/Console/GlobalCommunityBlock.php | 2 +- src/Core/Console/GlobalCommunitySilence.php | 2 +- src/Core/Console/Maintenance.php | 4 +- src/Core/Console/NewPassword.php | 2 +- src/Core/Console/PostUpdate.php | 4 +- src/Core/PConfig.php | 14 +- tests/Util/VFSTrait.php | 52 +++++ tests/src/App/ModeTest.php | 139 ++++++++++++++ tests/src/Core/Console/ConsoleTest.php | 50 +---- 21 files changed, 498 insertions(+), 106 deletions(-) create mode 100644 tests/Util/VFSTrait.php create mode 100644 tests/src/App/ModeTest.php diff --git a/bin/auth_ejabberd.php b/bin/auth_ejabberd.php index 55917bf6d9..1f03b94af9 100755 --- a/bin/auth_ejabberd.php +++ b/bin/auth_ejabberd.php @@ -54,7 +54,7 @@ require_once "include/dba.php"; $a = new App(dirname(__DIR__)); -if (App\Mode::isNormal()) { +if ($a->getMode()->isNormal()) { $oAuth = new ExAuth(); $oAuth->readStdin(); -} \ No newline at end of file +} diff --git a/bin/daemon.php b/bin/daemon.php index e2bad90df5..f0f5826d92 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -34,7 +34,7 @@ require_once "include/dba.php"; $a = new App(dirname(__DIR__)); -if (App\Mode::isInstall()) { +if ($a->getMode()->isInstall()) { die("Friendica isn't properly installed yet.\n"); } diff --git a/composer.json b/composer.json index a37010a9ef..5df9a5355b 100644 --- a/composer.json +++ b/composer.json @@ -75,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" diff --git a/composer.lock b/composer.lock index a07d56e692..7973167762 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c2306df3b19ec46d53bb16ac2cffa51a", + "content-hash": "9f0dbeccbae197460a0ce74a940177cd", "packages": [ { "name": "asika/simple-console", @@ -818,6 +818,28 @@ "reference": null, "shasum": "30dc7a7ce872155b23a33bd10ad4c76c0d613f55" }, + "require-dev": { + "npm-asset/babel-core": ">=6.26.0,<7.0.0", + "npm-asset/babel-plugin-external-helpers": ">=6.22.0,<7.0.0", + "npm-asset/babel-preset-env": ">=1.6.1,<2.0.0", + "npm-asset/cpy-cli": ">=1.0.1,<2.0.0", + "npm-asset/cssnano": ">=3.10.0,<4.0.0", + "npm-asset/del-cli": ">=1.1.0,<2.0.0", + "npm-asset/eslint": ">=4.14.0,<5.0.0", + "npm-asset/eslint-config-airbnb-base": ">=12.1.0,<13.0.0", + "npm-asset/eslint-plugin-import": ">=2.8.0,<3.0.0", + "npm-asset/node-qunit-phantomjs": ">=2.0.0,<3.0.0", + "npm-asset/npm-run-all": ">=4.1.2,<5.0.0", + "npm-asset/postcss-cli": ">=4.1.1,<5.0.0", + "npm-asset/postcss-cssnext": ">=3.0.2,<4.0.0", + "npm-asset/postcss-header": ">=1.0.0,<2.0.0", + "npm-asset/postcss-url": ">=7.3.0,<8.0.0", + "npm-asset/rollup": ">=0.53.3,<0.54.0", + "npm-asset/rollup-plugin-babel": ">=3.0.3,<4.0.0", + "npm-asset/rollup-watch": ">=4.3.1,<5.0.0", + "npm-asset/stylefmt": ">=6.0.0,<7.0.0", + "npm-asset/uglify-js": ">=3.3.4,<4.0.0" + }, "type": "npm-asset-library", "extra": { "npm-asset-bugs": { @@ -997,6 +1019,22 @@ "require": { "npm-asset/ev-emitter": ">=1.0.0,<2.0.0" }, + "require-dev": { + "npm-asset/chalk": ">=1.1.1,<2.0.0", + "npm-asset/cheerio": ">=0.19.0,<0.20.0", + "npm-asset/gulp": ">=3.9.0,<4.0.0", + "npm-asset/gulp-jshint": ">=1.11.2,<2.0.0", + "npm-asset/gulp-json-lint": ">=0.1.0,<0.2.0", + "npm-asset/gulp-rename": ">=1.2.2,<2.0.0", + "npm-asset/gulp-replace": ">=0.5.4,<0.6.0", + "npm-asset/gulp-requirejs-optimize": "dev-github:metafizzy/gulp-requirejs-optimize", + "npm-asset/gulp-uglify": ">=1.4.2,<2.0.0", + "npm-asset/gulp-util": ">=3.0.7,<4.0.0", + "npm-asset/highlight.js": ">=8.9.1,<9.0.0", + "npm-asset/marked": ">=0.3.5,<0.4.0", + "npm-asset/minimist": ">=1.2.0,<2.0.0", + "npm-asset/transfob": ">=1.0.0,<2.0.0" + }, "type": "npm-asset-library", "extra": { "npm-asset-bugs": { @@ -1042,6 +1080,14 @@ "reference": null, "shasum": "2736e332aaee73ccf0a14a5f0066391a0a13f4a3" }, + "require-dev": { + "npm-asset/grunt": "~0.4.2", + "npm-asset/grunt-contrib-cssmin": "~0.9.0", + "npm-asset/grunt-contrib-jshint": "~0.6.3", + "npm-asset/grunt-contrib-less": "~0.11.0", + "npm-asset/grunt-contrib-uglify": "~0.4.0", + "npm-asset/grunt-contrib-watch": "~0.6.1" + }, "type": "npm-asset-library", "extra": { "npm-asset-bugs": { @@ -1075,6 +1121,32 @@ "reference": null, "shasum": "2c89d6889b5eac522a7eea32c14521559c6cbf02" }, + "require-dev": { + "npm-asset/commitplease": "2.0.0", + "npm-asset/core-js": "0.9.17", + "npm-asset/grunt": "0.4.5", + "npm-asset/grunt-babel": "5.0.1", + "npm-asset/grunt-cli": "0.1.13", + "npm-asset/grunt-compare-size": "0.4.0", + "npm-asset/grunt-contrib-jshint": "0.11.2", + "npm-asset/grunt-contrib-uglify": "0.9.2", + "npm-asset/grunt-contrib-watch": "0.6.1", + "npm-asset/grunt-git-authors": "2.0.1", + "npm-asset/grunt-jscs": "2.1.0", + "npm-asset/grunt-jsonlint": "1.0.4", + "npm-asset/grunt-npmcopy": "0.1.0", + "npm-asset/gzip-js": "0.3.2", + "npm-asset/jsdom": "5.6.1", + "npm-asset/load-grunt-tasks": "1.0.0", + "npm-asset/qunit-assert-step": "1.0.3", + "npm-asset/qunitjs": "1.17.1", + "npm-asset/requirejs": "2.1.17", + "npm-asset/sinon": "1.10.3", + "npm-asset/sizzle": "2.2.1", + "npm-asset/strip-json-comments": "1.0.3", + "npm-asset/testswarm": "1.1.0", + "npm-asset/win-spawn": "2.0.0" + }, "type": "npm-asset-library", "extra": { "npm-asset-bugs": { @@ -1225,6 +1297,12 @@ "reference": null, "shasum": "06f0335f16e353a695e7206bf50503cb523a6ee5" }, + "require-dev": { + "npm-asset/grunt": "~0.4.1", + "npm-asset/grunt-contrib-connect": "~0.5.0", + "npm-asset/grunt-contrib-jshint": "~0.7.1", + "npm-asset/grunt-contrib-uglify": "~0.2.7" + }, "type": "npm-asset-library", "extra": { "npm-asset-bugs": { @@ -1933,6 +2011,54 @@ ], "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", @@ -1979,6 +2105,71 @@ "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", @@ -2779,7 +2970,7 @@ } ], "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", @@ -2881,7 +3072,7 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", @@ -2949,7 +3140,7 @@ } ], "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" @@ -3001,7 +3192,7 @@ } ], "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "homepage": "https://github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], @@ -3103,7 +3294,7 @@ } ], "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" }, { diff --git a/index.php b/index.php index f34b79867c..19b85b9356 100644 --- a/index.php +++ b/index.php @@ -36,7 +36,7 @@ $a->backend = false; require_once "include/dba.php"; // Missing DB connection: ERROR -if (App\Mode::has(App\Mode::LOCALCONFIGPRESENT) && !App\Mode::has(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,7 +48,7 @@ if ($a->isMaxProcessesReached() || $a->isMaxLoadReached()) { System::httpExit(503, ['title' => 'Error 503 - Service Temporarily Unavailable', 'description' => 'System is currently overloaded. Please try again later.']); } -if (!App\Mode::isInstall()) { +if (!$a->getMode()->isInstall()) { if (Config::get('system', 'force_ssl') && ($a->get_scheme() == "http") && (intval(Config::get('system', 'ssl_policy')) == SSL_POLICY_FULL) && (substr(System::baseUrl(), 0, 8) == "https://") @@ -107,7 +107,7 @@ if (!empty($_SESSION['language']) && $_SESSION['language'] !== $lang) { L10n::loadTranslationTable($lang); } -if (!empty($_GET['zrl']) && App\Mode::isNormal()) { +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 @@ -130,7 +130,7 @@ if (!empty($_GET['zrl']) && App\Mode::isNormal()) { } } -if (!empty($_GET['owt']) && App\Mode::isNormal()) { +if (!empty($_GET['owt']) && $a->getMode()->isNormal()) { $token = $_GET['owt']; $a->query_string = Profile::stripQueryParam($a->query_string, 'owt'); Profile::openWebAuthInit($token); @@ -165,9 +165,9 @@ $_SESSION['last_updated'] = defaults($_SESSION, 'last_updated', []); // in install mode, any url loads install module // but we need "view" module for stylesheet -if (App\Mode::isInstall() && $a->module != 'view') { +if ($a->getMode()->isInstall() && $a->module != 'view') { $a->module = 'install'; -} elseif (!App\Mode::has(App\Mode::MAINTENANCEDISABLED) && $a->module != 'view') { +} elseif (!$a->getMode()->has(App\Mode::MAINTENANCEDISABLED) && $a->module != 'view') { $a->module = 'maintenance'; } else { check_url($a); @@ -320,7 +320,7 @@ if (file_exists($theme_info_file)) { /* initialise content region */ -if (App\Mode::isNormal()) { +if ($a->getMode()->isNormal()) { Addon::callHooks('page_content_top', $a->page['content']); } diff --git a/phpunit.xml b/phpunit.xml index 9ed293b631..0494b4dcb4 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,6 +1,5 @@ diff --git a/src/App.php b/src/App.php index 9a09bcfce0..61d7335f1a 100644 --- a/src/App.php +++ b/src/App.php @@ -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'; @@ -83,6 +84,11 @@ class App public $stylesheets = []; public $footerScripts = []; + /** + * @var App\Mode The Mode of the Application + */ + private $mode; + /** * Register a stylesheet file path to be included in the tag of every page. * Inclusion is done in App->initHead(). @@ -193,6 +199,8 @@ class App $this->callstack['rendering'] = []; $this->callstack['parser'] = []; + $this->mode = new App\Mode($basepath); + $this->reload(); set_time_limit(0); @@ -300,6 +308,22 @@ class App $this->register_template_engine('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; + } + /** * Reloads the whole app instance */ @@ -310,13 +334,13 @@ class App $this->loadDatabase(); - App\Mode::determine($this->basepath); + $this->getMode()->determine($this->basepath); $this->determineUrlPath(); Config::load(); - if (App\Mode::has(App\Mode::DBAVAILABLE)) { + if ($this->getMode()->has(App\Mode::DBAVAILABLE)) { Core\Addon::loadHooks(); $this->loadAddonConfig(); @@ -1402,7 +1426,7 @@ class App */ public function getCurrentTheme() { - if (App\Mode::isInstall()) { + if ($this->getMode()->isInstall()) { return ''; } diff --git a/src/App/Mode.php b/src/App/Mode.php index 189573e378..10f1092a89 100644 --- a/src/App/Mode.php +++ b/src/App/Mode.php @@ -20,9 +20,19 @@ class Mode /*** * @var int the mode of this Application * - * Default is 0 (= not set) */ - private static $mode = 0; + 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 @@ -34,34 +44,38 @@ class Mode * @param string $basepath the Basepath of the Application * */ - public static function determine($basepath) + public function determine($basepath = null) { - self::$mode = 0; + if (!empty($basepath)) { + $this->basepath = $basepath; + } - if (!file_exists($basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php') - && !file_exists($basepath . DIRECTORY_SEPARATOR . '.htconfig.php')) { + $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; } - self::$mode |= Mode::LOCALCONFIGPRESENT; + $this->mode |= Mode::LOCALCONFIGPRESENT; if (!DBA::connected()) { return; } - self::$mode |= Mode::DBAVAILABLE; + $this->mode |= Mode::DBAVAILABLE; if (DBA::fetchFirst("SHOW TABLES LIKE 'config'") === false) { return; } - self::$mode |= Mode::DBCONFIGAVAILABLE; + $this->mode |= Mode::DBCONFIGAVAILABLE; if (Config::get('system', 'maintenance')) { return; } - self::$mode |= Mode::MAINTENANCEDISABLED; + $this->mode |= Mode::MAINTENANCEDISABLED; } /** @@ -71,9 +85,13 @@ class Mode * * @return bool returns true, if the mode is set */ - public static function has($mode) + public function has($mode) { - return self::$mode & $mode; + echo "mode: " . $this->mode . " with " . $mode; + + echo "value: " . ($this->mode & $mode); + + return ($this->mode & $mode) > 0; } @@ -82,10 +100,10 @@ class Mode * * @return bool */ - public static function isInstall() + public function isInstall() { - return !self::has(Mode::LOCALCONFIGPRESENT) || - !self::has(MODE::DBCONFIGAVAILABLE); + return !$this->has(Mode::LOCALCONFIGPRESENT) || + !$this->has(MODE::DBCONFIGAVAILABLE); } /** @@ -93,11 +111,11 @@ class Mode * * @return bool */ - public static function isNormal() + public function isNormal() { - return self::has(Mode::LOCALCONFIGPRESENT) && - self::has(Mode::DBAVAILABLE) && - self::has(Mode::DBCONFIGAVAILABLE) && - self::has(Mode::MAINTENANCEDISABLED); + return $this->has(Mode::LOCALCONFIGPRESENT) && + $this->has(Mode::DBAVAILABLE) && + $this->has(Mode::DBCONFIGAVAILABLE) && + $this->has(Mode::MAINTENANCEDISABLED); } } diff --git a/src/Core/Config.php b/src/Core/Config.php index f2b0d12ab0..a07bbd31c9 100644 --- a/src/Core/Config.php +++ b/src/Core/Config.php @@ -31,7 +31,7 @@ class Config extends BaseObject public static function init() { // Database isn't ready or populated yet - if (!App\Mode::has(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 (!App\Mode::has(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 (!App\Mode::has(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 (!App\Mode::has(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 (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { + if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { return false; } diff --git a/src/Core/Console/ArchiveContact.php b/src/Core/Console/ArchiveContact.php index 8a6bc1f7bf..481037a5f6 100644 --- a/src/Core/Console/ArchiveContact.php +++ b/src/Core/Console/ArchiveContact.php @@ -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 (App\Mode::isInstall()) { + if ($a->getMode()->isInstall()) { throw new RuntimeException('Friendica isn\'t properly installed yet.'); } diff --git a/src/Core/Console/Cache.php b/src/Core/Console/Cache.php index 2d3508894a..af0d771307 100644 --- a/src/Core/Console/Cache.php +++ b/src/Core/Console/Cache.php @@ -65,7 +65,7 @@ HELP; $this->out('Options: ' . var_export($this->options, true)); } - if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { + if ($a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { $this->out('Database isn\'t ready or populated yet, database cache won\'t be available'); } diff --git a/src/Core/Console/Config.php b/src/Core/Console/Config.php index d67f6cbb96..3b92d5a784 100644 --- a/src/Core/Console/Config.php +++ b/src/Core/Console/Config.php @@ -84,7 +84,7 @@ HELP; throw new CommandArgsException('Too many arguments'); } - if (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { + if (!$a->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { $this->out('Database isn\'t ready or populated yet, showing file config only'); } @@ -143,7 +143,7 @@ HELP; if (count($this->args) == 0) { Core\Config::load(); - if (Core\Config::get('system', 'config_adapter') == 'jit' && App\Mode::has(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'); } diff --git a/src/Core/Console/GlobalCommunityBlock.php b/src/Core/Console/GlobalCommunityBlock.php index dbab4ff02c..2a19a9e7f3 100644 --- a/src/Core/Console/GlobalCommunityBlock.php +++ b/src/Core/Console/GlobalCommunityBlock.php @@ -56,7 +56,7 @@ HELP; throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); } - if (App\Mode::isInstall()) { + if ($a->getMode()->isInstall()) { throw new \RuntimeException('Database isn\'t ready or populated yet'); } diff --git a/src/Core/Console/GlobalCommunitySilence.php b/src/Core/Console/GlobalCommunitySilence.php index 0dce00a7b1..3ea6b41554 100644 --- a/src/Core/Console/GlobalCommunitySilence.php +++ b/src/Core/Console/GlobalCommunitySilence.php @@ -65,7 +65,7 @@ HELP; throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); } - if (App\Mode::isInstall()) { + if ($a->getMode()->isInstall()) { throw new RuntimeException('Database isn\'t ready or populated yet'); } diff --git a/src/Core/Console/Maintenance.php b/src/Core/Console/Maintenance.php index d693cb6e89..212edabcc1 100644 --- a/src/Core/Console/Maintenance.php +++ b/src/Core/Console/Maintenance.php @@ -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 (App\Mode::isInstall()) { + if ($a->getMode()->isInstall()) { throw new \RuntimeException('Database isn\'t ready or populated yet'); } diff --git a/src/Core/Console/NewPassword.php b/src/Core/Console/NewPassword.php index 56f3ae7c98..54d10af207 100644 --- a/src/Core/Console/NewPassword.php +++ b/src/Core/Console/NewPassword.php @@ -57,7 +57,7 @@ HELP; throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments'); } - if (App\Mode::isInstall()) { + if ($a->getMode()->isInstall()) { throw new RuntimeException('Database isn\'t ready or populated yet'); } diff --git a/src/Core/Console/PostUpdate.php b/src/Core/Console/PostUpdate.php index a77aae39de..1215591a20 100644 --- a/src/Core/Console/PostUpdate.php +++ b/src/Core/Console/PostUpdate.php @@ -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 (App\Mode::isInstall()) { + if ($a->getMode()->isInstall()) { throw new \RuntimeException('Database isn\'t ready or populated yet'); } diff --git a/src/Core/PConfig.php b/src/Core/PConfig.php index 3c48a568cb..2080f716ce 100644 --- a/src/Core/PConfig.php +++ b/src/Core/PConfig.php @@ -29,12 +29,14 @@ class PConfig extends BaseObject public static function init($uid) { + $a = self::getApp(); + // Database isn't ready or populated yet - if (!App\Mode::has(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 (!App\Mode::has(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 (!App\Mode::has(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 (!App\Mode::has(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 (!App\Mode::has(App\Mode::DBCONFIGAVAILABLE)) { + if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) { return false; } diff --git a/tests/Util/VFSTrait.php b/tests/Util/VFSTrait.php new file mode 100644 index 0000000000..b0e7a3a604 --- /dev/null +++ b/tests/Util/VFSTrait.php @@ -0,0 +1,52 @@ + [], + '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); + } + } +} diff --git a/tests/src/App/ModeTest.php b/tests/src/App/ModeTest.php new file mode 100644 index 0000000000..bac553eb8c --- /dev/null +++ b/tests/src/App/ModeTest.php @@ -0,0 +1,139 @@ +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)); + } +} diff --git a/tests/src/Core/Console/ConsoleTest.php b/tests/src/Core/Console/ConsoleTest.php index 0cc5c63359..40f864e3b9 100644 --- a/tests/src/Core/Console/ConsoleTest.php +++ b/tests/src/Core/Console/ConsoleTest.php @@ -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('app = new App($this->root->url()); BaseObject::setApp($this->app); @@ -67,41 +70,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('at($this->root->getChild('config')) - ->setContent(file_get_contents($file)); - } - } } From a2fb49a2b4cdaca9b938e0a750575ae502c5ec63 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 6 Oct 2018 19:11:00 +0200 Subject: [PATCH 303/428] Removing debugging echo Updating Tests --- phpunit.xml | 1 + src/App/Mode.php | 4 ---- tests/ApiTest.php | 5 ++--- tests/DatabaseTest.php | 11 ++++++++++- tests/bootstrap.php | 10 ---------- 5 files changed, 13 insertions(+), 18 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index 0494b4dcb4..9ed293b631 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,5 +1,6 @@ diff --git a/src/App/Mode.php b/src/App/Mode.php index 10f1092a89..d9f5cdbd4c 100644 --- a/src/App/Mode.php +++ b/src/App/Mode.php @@ -87,10 +87,6 @@ class Mode */ public function has($mode) { - echo "mode: " . $this->mode . " with " . $mode; - - echo "value: " . ($this->mode & $mode); - return ($this->mode & $mode) > 0; } diff --git a/tests/ApiTest.php b/tests/ApiTest.php index 941ed96bf8..cbc6f7e0b4 100644 --- a/tests/ApiTest.php +++ b/tests/ApiTest.php @@ -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 = [ diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php index 9844699b06..52ca3f68d3 100644 --- a/tests/DatabaseTest.php +++ b/tests/DatabaseTest.php @@ -5,6 +5,8 @@ namespace Friendica\Test; +use Friendica\BaseObject; +use Friendica\Core\Config; use Friendica\Database\DBA; use PHPUnit\DbUnit\DataSet\YamlDataSet; use PHPUnit\DbUnit\TestCaseTrait; @@ -16,8 +18,15 @@ use PHPUnit_Extensions_Database_DB_IDatabaseConnection; */ abstract class DatabaseTest extends TestCase { + public function setUp() + { + // Reusable App object + $this->app = BaseObject::getApp(); - use TestCaseTrait; + 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/bootstrap.php b/tests/bootstrap.php index 4bc3e932f0..ada2b1a0ec 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -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); From 192c6c8d4fb1d99981b46acc9d99bb212b754466 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 6 Oct 2018 18:42:26 +0000 Subject: [PATCH 304/428] Preparation for suggestions under AP --- src/Protocol/ActivityPub/Transmitter.php | 30 ++++++++++++++++++++++++ src/Worker/APDelivery.php | 1 + 2 files changed, 31 insertions(+) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 9fad787b1b..cb3e1f30af 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -797,6 +797,36 @@ class Transmitter return $data; } + /** + * 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'], + 'published' => DateTimeFormat::utc($suggestion['created'] . '+00:00', DateTimeFormat::ATOM), + '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 * diff --git a/src/Worker/APDelivery.php b/src/Worker/APDelivery.php index 039cdfbb3b..7b1ad76055 100644 --- a/src/Worker/APDelivery.php +++ b/src/Worker/APDelivery.php @@ -25,6 +25,7 @@ class APDelivery extends BaseObject 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); From f8b74033a4f990e421814ea5bf8b443104e61feb Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 6 Oct 2018 18:44:42 +0000 Subject: [PATCH 305/428] Avoid a notice --- mod/fsuggest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/fsuggest.php b/mod/fsuggest.php index 8fc0f07dee..35710bb338 100644 --- a/mod/fsuggest.php +++ b/mod/fsuggest.php @@ -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", From 3f0f3b6ae60ac514b8ac890db996e40e65795b0b Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 7 Oct 2018 00:27:54 +0200 Subject: [PATCH 306/428] friendica-5847 Console Cache List command doesn't work - Added $prefix to all CacheDriver - Moved hostname magic to CacheDriver - Added test for getAllKeys() --- src/Core/Cache.php | 13 ++--- src/Core/Cache/AbstractCacheDriver.php | 49 ++++++++++++++++++- src/Core/Cache/ArrayCache.php | 4 +- src/Core/Cache/DatabaseCacheDriver.php | 18 +++++-- src/Core/Cache/ICacheDriver.php | 4 +- src/Core/Cache/MemcacheCacheDriver.php | 6 ++- src/Core/Cache/MemcachedCacheDriver.php | 14 +++++- src/Core/Cache/RedisCacheDriver.php | 12 ++++- src/Core/Console/Cache.php | 2 +- tests/src/Core/Cache/ArrayCacheDriverTest.php | 5 -- tests/src/Core/Cache/CacheTest.php | 32 ++++++++++++ .../Core/Cache/DatabaseCacheDriverTest.php | 5 -- .../Core/Cache/MemcacheCacheDriverTest.php | 5 -- .../Core/Cache/MemcachedCacheDriverTest.php | 5 -- tests/src/Core/Cache/RedisCacheDriverTest.php | 5 -- 15 files changed, 131 insertions(+), 48 deletions(-) diff --git a/src/Core/Cache.php b/src/Core/Cache.php index ea7807031f..7b9f6edd2c 100644 --- a/src/Core/Cache.php +++ b/src/Core/Cache.php @@ -51,20 +51,15 @@ class Cache extends \Friendica\BaseObject /** * @brief Returns all the cache keys sorted alphabetically * + * @param string $prefix Prefix of the keys (optional) + * * @return array|null Null if the driver doesn't support this feature */ - public static function getAllKeys() + public static function getAllKeys($prefix = null) { $time = microtime(true); - $return = self::getDriver()->getAllKeys(); - - // Keys are prefixed with the node hostname, let's remove it - array_walk($return, function (&$value) { - $value = preg_replace('/^' . self::getApp()->get_hostname() . ':/', '', $value); - }); - - sort($return); + $return = self::getDriver()->getAllKeys($prefix); self::getApp()->save_timestamp($time, 'cache'); diff --git a/src/Core/Cache/AbstractCacheDriver.php b/src/Core/Cache/AbstractCacheDriver.php index 15b822dc3b..e694b9c314 100644 --- a/src/Core/Cache/AbstractCacheDriver.php +++ b/src/Core/Cache/AbstractCacheDriver.php @@ -17,8 +17,55 @@ 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; } + + /** + * @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()->get_hostname() . ':/', '', $value); + }); + + sort($keys); + + return $keys; + } + } + + /** + * Filters a list for a given prefix + * + * @param array $list the list + * @param string|null $prefix the prefix + * + * @return array the filtered list + */ + protected function filterPrefix($list, $prefix = null) + { + if (empty($prefix)) { + return array_keys($list); + } else { + $result = []; + + foreach (array_keys($list) as $key) { + if (strpos($key, $prefix) === 0) { + array_push($result, $key); + } + } + + return $result; + } + + } } diff --git a/src/Core/Cache/ArrayCache.php b/src/Core/Cache/ArrayCache.php index 47c9c16680..0d314fadb7 100644 --- a/src/Core/Cache/ArrayCache.php +++ b/src/Core/Cache/ArrayCache.php @@ -22,9 +22,9 @@ class ArrayCache extends AbstractCacheDriver implements IMemoryCacheDriver /** * (@inheritdoc) */ - public function getAllKeys() + public function getAllKeys($prefix = null) { - return array_keys($this->cachedData); + return $this->filterPrefix($this->cachedData, $prefix); } /** diff --git a/src/Core/Cache/DatabaseCacheDriver.php b/src/Core/Cache/DatabaseCacheDriver.php index 74dfe3991e..9966457467 100644 --- a/src/Core/Cache/DatabaseCacheDriver.php +++ b/src/Core/Cache/DatabaseCacheDriver.php @@ -16,11 +16,23 @@ class DatabaseCacheDriver extends AbstractCacheDriver implements ICacheDriver /** * (@inheritdoc) */ - public function getAllKeys() + public function getAllKeys($prefix = null) { - $stmt = DBA::select('cache', ['k'], ['`expires` >= ?', DateTimeFormat::utcNow()]); + if (empty($prefix)) { + $where = ['`expires` >= ?', DateTimeFormat::utcNow()]; + } else { + $where = ['`expires` >= ? AND k LIKE CONCAT(?, \'%\')', DateTimeFormat::utcNow(), $prefix]; + } - return DBA::toArray($stmt); + $stmt = DBA::select('cache', ['k'], $where); + + $list = []; + while ($key = DBA::fetch($stmt)) { + array_push($list, $key['k']); + } + DBA::close($stmt); + + return $list; } /** diff --git a/src/Core/Cache/ICacheDriver.php b/src/Core/Cache/ICacheDriver.php index b77aa03c16..0a206559cc 100644 --- a/src/Core/Cache/ICacheDriver.php +++ b/src/Core/Cache/ICacheDriver.php @@ -14,9 +14,11 @@ interface ICacheDriver /** * Lists all cache keys * + * @param string prefix optional a prefix to search + * * @return array|null Null if it isn't supported by the cache driver */ - public function getAllKeys(); + public function getAllKeys($prefix = null); /** * Fetches cached data according to the key diff --git a/src/Core/Cache/MemcacheCacheDriver.php b/src/Core/Cache/MemcacheCacheDriver.php index 207225b1a2..f31e21d14e 100644 --- a/src/Core/Cache/MemcacheCacheDriver.php +++ b/src/Core/Cache/MemcacheCacheDriver.php @@ -43,7 +43,7 @@ class MemcacheCacheDriver extends AbstractCacheDriver implements IMemoryCacheDri /** * (@inheritdoc) */ - public function getAllKeys() + public function getAllKeys($prefix = null) { $list = []; $allSlabs = $this->memcache->getExtendedStats('slabs'); @@ -59,7 +59,9 @@ class MemcacheCacheDriver extends AbstractCacheDriver implements IMemoryCacheDri } } - return $list; + $list = $this->getOriginalKeys($list); + + return $this->filterPrefix($list, $prefix); } /** diff --git a/src/Core/Cache/MemcachedCacheDriver.php b/src/Core/Cache/MemcachedCacheDriver.php index c1d08f3321..82df98f13b 100644 --- a/src/Core/Cache/MemcachedCacheDriver.php +++ b/src/Core/Cache/MemcachedCacheDriver.php @@ -5,6 +5,7 @@ namespace Friendica\Core\Cache; use Friendica\Core\Cache; use Exception; +use Friendica\Network\HTTPException\InternalServerErrorException; use Memcached; /** @@ -40,6 +41,9 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr $this->memcached = new Memcached(); + + $this->memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, false); + array_walk($memcached_hosts, function (&$value) { if (is_string($value)) { $value = array_map('trim', explode(',', $value)); @@ -56,9 +60,15 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr /** * (@inheritdoc) */ - public function getAllKeys() + public function getAllKeys($prefix = null) { - return $this->memcached->getAllKeys(); + // Doesn't work because of https://github.com/php-memcached-dev/php-memcached/issues/367 + // returns everytime an empty array + throw new InternalServerErrorException('getAllKeys for Memcached not supported yet'); + + $list = $this->getOriginalKeys($this->memcached->getAllKeys()); + + return $this->filterPrefix($list, $prefix); } /** diff --git a/src/Core/Cache/RedisCacheDriver.php b/src/Core/Cache/RedisCacheDriver.php index f9d00fde21..fcbfab548a 100644 --- a/src/Core/Cache/RedisCacheDriver.php +++ b/src/Core/Cache/RedisCacheDriver.php @@ -41,9 +41,17 @@ class RedisCacheDriver extends AbstractCacheDriver implements IMemoryCacheDriver /** * (@inheritdoc) */ - public function getAllKeys() + public function getAllKeys($prefix = null) { - return null; + if (empty($prefix)) { + $search = '*'; + } else { + $search = $prefix . '*'; + } + + $list = $this->redis->keys($this->getCacheKey($search)); + + return $this->getOriginalKeys($list); } /** diff --git a/src/Core/Console/Cache.php b/src/Core/Console/Cache.php index 2d3508894a..0dfef43f35 100644 --- a/src/Core/Console/Cache.php +++ b/src/Core/Console/Cache.php @@ -105,7 +105,7 @@ HELP; private function executeList() { $prefix = $this->getArgument(1); - $keys = Core\Cache::getAllKeys(); + $keys = Core\Cache::getAllKeys($prefix); if (empty($prefix)) { $this->out('Listing all cache keys:'); diff --git a/tests/src/Core/Cache/ArrayCacheDriverTest.php b/tests/src/Core/Cache/ArrayCacheDriverTest.php index 0cad6e9c7f..6863d149ff 100644 --- a/tests/src/Core/Cache/ArrayCacheDriverTest.php +++ b/tests/src/Core/Cache/ArrayCacheDriverTest.php @@ -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(); diff --git a/tests/src/Core/Cache/CacheTest.php b/tests/src/Core/Cache/CacheTest.php index 5c56c2072f..86bf5e7f01 100644 --- a/tests/src/Core/Cache/CacheTest.php +++ b/tests/src/Core/Cache/CacheTest.php @@ -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); + } } diff --git a/tests/src/Core/Cache/DatabaseCacheDriverTest.php b/tests/src/Core/Cache/DatabaseCacheDriverTest.php index 5df00fc913..3cc4a72ed1 100644 --- a/tests/src/Core/Cache/DatabaseCacheDriverTest.php +++ b/tests/src/Core/Cache/DatabaseCacheDriverTest.php @@ -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'); diff --git a/tests/src/Core/Cache/MemcacheCacheDriverTest.php b/tests/src/Core/Cache/MemcacheCacheDriverTest.php index 62f7440033..db85723af1 100644 --- a/tests/src/Core/Cache/MemcacheCacheDriverTest.php +++ b/tests/src/Core/Cache/MemcacheCacheDriverTest.php @@ -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'); diff --git a/tests/src/Core/Cache/MemcachedCacheDriverTest.php b/tests/src/Core/Cache/MemcachedCacheDriverTest.php index 5a07814a38..fba5c4a958 100644 --- a/tests/src/Core/Cache/MemcachedCacheDriverTest.php +++ b/tests/src/Core/Cache/MemcachedCacheDriverTest.php @@ -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'); diff --git a/tests/src/Core/Cache/RedisCacheDriverTest.php b/tests/src/Core/Cache/RedisCacheDriverTest.php index 460c1184ba..0ee73945b9 100644 --- a/tests/src/Core/Cache/RedisCacheDriverTest.php +++ b/tests/src/Core/Cache/RedisCacheDriverTest.php @@ -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'); From 1ec5c6b2840cedbe21e089f4ef4404d22a65031e Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 7 Oct 2018 10:35:37 +0200 Subject: [PATCH 307/428] friendica-5847 Console Cache List command doesn't work - filterPrefix => filterArrayKeysByPrefix() - Logging failed Executions of getAllKeys and get from Memcached --- src/Core/Cache/AbstractCacheDriver.php | 15 ++++++++------- src/Core/Cache/ArrayCache.php | 2 +- src/Core/Cache/MemcacheCacheDriver.php | 10 +++++----- src/Core/Cache/MemcachedCacheDriver.php | 22 +++++++++++----------- src/Core/Console/Cache.php | 5 +---- 5 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/Core/Cache/AbstractCacheDriver.php b/src/Core/Cache/AbstractCacheDriver.php index e694b9c314..1cdecf6ceb 100644 --- a/src/Core/Cache/AbstractCacheDriver.php +++ b/src/Core/Cache/AbstractCacheDriver.php @@ -44,21 +44,22 @@ abstract class AbstractCacheDriver extends BaseObject } /** - * Filters a list for a given prefix + * Filters the keys of an array with a given prefix + * Returns the filtered keys as an new array * - * @param array $list the list - * @param string|null $prefix the prefix + * @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 list + * @return array The filtered array with just the keys */ - protected function filterPrefix($list, $prefix = null) + protected function filterArrayKeysByPrefix($array, $prefix = null) { if (empty($prefix)) { - return array_keys($list); + return array_keys($array); } else { $result = []; - foreach (array_keys($list) as $key) { + foreach (array_keys($array) as $key) { if (strpos($key, $prefix) === 0) { array_push($result, $key); } diff --git a/src/Core/Cache/ArrayCache.php b/src/Core/Cache/ArrayCache.php index 0d314fadb7..a99b05788f 100644 --- a/src/Core/Cache/ArrayCache.php +++ b/src/Core/Cache/ArrayCache.php @@ -24,7 +24,7 @@ class ArrayCache extends AbstractCacheDriver implements IMemoryCacheDriver */ public function getAllKeys($prefix = null) { - return $this->filterPrefix($this->cachedData, $prefix); + return $this->filterArrayKeysByPrefix($this->cachedData, $prefix); } /** diff --git a/src/Core/Cache/MemcacheCacheDriver.php b/src/Core/Cache/MemcacheCacheDriver.php index f31e21d14e..fd928c6fcc 100644 --- a/src/Core/Cache/MemcacheCacheDriver.php +++ b/src/Core/Cache/MemcacheCacheDriver.php @@ -45,23 +45,23 @@ class MemcacheCacheDriver extends AbstractCacheDriver implements IMemoryCacheDri */ public function getAllKeys($prefix = null) { - $list = []; + $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 $keys => $arrVal) { + foreach ($cachedump as $key => $arrVal) { if (!is_array($arrVal)) { continue; } - $list = array_merge($list, array_keys($arrVal)); + $keys = array_merge($keys, array_keys($arrVal)); } } } - $list = $this->getOriginalKeys($list); + $keys = $this->getOriginalKeys($keys); - return $this->filterPrefix($list, $prefix); + return $this->filterArrayKeysByPrefix($keys, $prefix); } /** diff --git a/src/Core/Cache/MemcachedCacheDriver.php b/src/Core/Cache/MemcachedCacheDriver.php index 82df98f13b..a6e1bad950 100644 --- a/src/Core/Cache/MemcachedCacheDriver.php +++ b/src/Core/Cache/MemcachedCacheDriver.php @@ -62,13 +62,14 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr */ public function getAllKeys($prefix = null) { - // Doesn't work because of https://github.com/php-memcached-dev/php-memcached/issues/367 - // returns everytime an empty array - throw new InternalServerErrorException('getAllKeys for Memcached not supported yet'); + $keys = $this->getOriginalKeys($this->memcached->getAllKeys()); - $list = $this->getOriginalKeys($this->memcached->getAllKeys()); - - return $this->filterPrefix($list, $prefix); + if ($this->memcached->getResultCode() == Memcached::RES_SUCCESS) { + return $this->filterArrayKeysByPrefix($keys, $prefix); + } else { + logger('Memcached \'getAllKeys\' failed with ' . $this->memcached->getResultMessage(), LOGGER_ALL); + return []; + } } /** @@ -76,17 +77,17 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr */ public function get($key) { - $return = null; $cachekey = $this->getCacheKey($key); // We fetch with the hostname as key to avoid problems with other applications $value = $this->memcached->get($cachekey); if ($this->memcached->getResultCode() === Memcached::RES_SUCCESS) { - $return = $value; + return $value; + } else { + logger('Memcached \'get\' failed with ' . $this->memcached->getResultMessage(), LOGGER_ALL); + return []; } - - return $return; } /** @@ -109,7 +110,6 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr $value ); } - } /** diff --git a/src/Core/Console/Cache.php b/src/Core/Console/Cache.php index 0dfef43f35..459a27e20b 100644 --- a/src/Core/Console/Cache.php +++ b/src/Core/Console/Cache.php @@ -115,10 +115,7 @@ HELP; $count = 0; foreach ($keys as $key) { - if (empty($prefix) || strpos($key, $prefix) === 0) { - $this->out($key); - $count++; - } + $this->out($key); } $this->out($count . ' keys found'); From 8491f8660f3afa67bd02f5702fb10bb35c25db21 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 7 Oct 2018 10:38:45 +0200 Subject: [PATCH 308/428] Bugfixing Memcached --- src/Core/Cache/MemcachedCacheDriver.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Core/Cache/MemcachedCacheDriver.php b/src/Core/Cache/MemcachedCacheDriver.php index a6e1bad950..62c3892860 100644 --- a/src/Core/Cache/MemcachedCacheDriver.php +++ b/src/Core/Cache/MemcachedCacheDriver.php @@ -41,9 +41,6 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr $this->memcached = new Memcached(); - - $this->memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, false); - array_walk($memcached_hosts, function (&$value) { if (is_string($value)) { $value = array_map('trim', explode(',', $value)); @@ -68,7 +65,7 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr return $this->filterArrayKeysByPrefix($keys, $prefix); } else { logger('Memcached \'getAllKeys\' failed with ' . $this->memcached->getResultMessage(), LOGGER_ALL); - return []; + return null; } } @@ -77,17 +74,19 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr */ public function get($key) { + $return = null; $cachekey = $this->getCacheKey($key); // We fetch with the hostname as key to avoid problems with other applications $value = $this->memcached->get($cachekey); if ($this->memcached->getResultCode() === Memcached::RES_SUCCESS) { - return $value; + $return = $value; } else { logger('Memcached \'get\' failed with ' . $this->memcached->getResultMessage(), LOGGER_ALL); - return []; } + + return $return; } /** From 3a74f3364d28297ba957544893d9c721d683dba1 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 7 Oct 2018 13:37:05 +0000 Subject: [PATCH 309/428] Switch to parsing compacted JSON data --- src/Protocol/ActivityPub/Processor.php | 7 +- src/Protocol/ActivityPub/Receiver.php | 241 ++++++++++++++--------- src/Protocol/ActivityPub/Transmitter.php | 4 + src/Util/JsonLD.php | 88 ++++++--- 4 files changed, 226 insertions(+), 114 deletions(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index f62566168b..f117c8c33e 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -52,7 +52,7 @@ class Processor $tag_text = ''; foreach ($tags as $tag) { - if (in_array($tag['type'], ['Mention', 'Hashtag'])) { + if (in_array(defaults($tag, 'type', ''), ['Mention', 'Hashtag'])) { if (!empty($tag_text)) { $tag_text .= ','; } @@ -210,9 +210,8 @@ class Processor $item = self::constructAttachList($activity['attachments'], $item); - $source = JsonLD::fetchElement($activity, 'source', 'content', 'mediaType', 'text/bbcode'); - if (!empty($source)) { - $item['body'] = $source; + if (!empty($activity['source'])) { + $item['body'] = $activity['source']; } $item['protocol'] = Conversation::PARCEL_ACTIVITYPUB; diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 1c237f79dc..48bfc0c8c8 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -36,6 +36,11 @@ use Friendica\Protocol\ActivityPub; */ 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 * @@ -48,7 +53,7 @@ class Receiver } /** - * + * Checks incoming message from the inbox * * @param $body * @param $header @@ -66,14 +71,17 @@ class Receiver $activity = json_decode($body, true); - $actor = JsonLD::fetchElement($activity, 'actor', 'id'); - logger('Message for user ' . $uid . ' is from actor ' . $actor, LOGGER_DEBUG); - 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)) { @@ -100,7 +108,7 @@ class Receiver $trust_source = false; } - self::processActivity($activity, $body, $uid, $trust_source); + self::processActivity($activity, $ldactivity, $body, $uid, $trust_source); } /** @@ -112,16 +120,18 @@ class Receiver * * @return */ - private static function prepareObjectData($activity, $uid, &$trust_source) + private static function prepareObjectData($activity, $ldactivity, $uid, &$trust_source) { - $actor = JsonLD::fetchElement($activity, 'actor', 'id'); + $actor = JsonLD::fetchElement($ldactivity, 'as:actor'); if (empty($actor)) { logger('Empty actor', LOGGER_DEBUG); return []; } + $type = JsonLD::fetchElement($ldactivity, '@type'); + // Fetch all receivers from to, cc, bto and bcc - $receivers = self::getReceivers($activity, $actor); + $receivers = self::getReceivers($ldactivity, $actor); // When it is a delivery to a personal inbox we add that user to the receivers if (!empty($uid)) { @@ -132,34 +142,34 @@ class Receiver logger('Receivers: ' . json_encode($receivers), LOGGER_DEBUG); - $object_id = JsonLD::fetchElement($activity, 'object', 'id'); + $object_id = JsonLD::fetchElement($ldactivity, 'as:object'); if (empty($object_id)) { logger('No object found', LOGGER_DEBUG); return []; } // Fetch the content only on activities where this matters - if (in_array($activity['type'], ['Create', 'Announce'])) { - $object_data = self::fetchObject($object_id, $activity['object'], $trust_source); + if (in_array($type, ['as:Create', 'as:Announce'])) { + $object_data = self::fetchObject($object_id, $activity['object'], $ldactivity['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($activity['type'], ['Like', 'Dislike'])) { + } 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'] = $activity['type']; - $object_data['author'] = $activity['actor']; + $object_data = self::processObject($ldactivity); + $object_data['name'] = $type; + $object_data['author'] = JsonLD::fetchElement($ldactivity, 'as:actor'); $object_data['object'] = $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'] = $activity['id']; + $object_data['id'] = JsonLD::fetchElement($ldactivity, '@id'); $object_data['object'] = $activity['object']; - $object_data['object_type'] = JsonLD::fetchElement($activity, 'object', 'type'); + $object_data['object_type'] = JsonLD::fetchElement($ldactivity, 'as:object', '@type'); } $object_data = self::addActivityFields($object_data, $activity); @@ -181,110 +191,115 @@ class Receiver * @param integer $uid User ID * @param $trust_source */ - public static function processActivity($activity, $body = '', $uid = null, $trust_source = false) + public static function processActivity($activity, $ldactivity = '', $body = '', $uid = null, $trust_source = false) { - if (empty($activity['type'])) { + if (empty($ldactivity)) { + $ldactivity = JsonLD::compact($activity); + } + + $type = JsonLD::fetchElement($ldactivity, '@type'); + if (!$type) { logger('Empty type', LOGGER_DEBUG); return; } - if (empty($activity['object'])) { + if (!JsonLD::fetchElement($ldactivity, 'as:object')) { logger('Empty object', LOGGER_DEBUG); return; } - if (empty($activity['actor'])) { + if (!JsonLD::fetchElement($ldactivity, '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); + $object_data = self::prepareObjectData($activity, $ldactivity, $uid, $trust_source); if (empty($object_data)) { logger('No object data found', LOGGER_DEBUG); return; } if (!$trust_source) { - logger('No trust for activity type "' . $activity['type'] . '", so we quit now.', LOGGER_DEBUG); + logger('No trust for activity type "' . $type . '", so we quit now.', LOGGER_DEBUG); return; } - switch ($activity['type']) { - case 'Create': - case 'Announce': + switch ($type) { + case 'as:Create': + case 'as:Announce': ActivityPub\Processor::createItem($object_data, $body); break; - case 'Like': + case 'as:Like': ActivityPub\Processor::likeItem($object_data, $body); break; - case 'Dislike': + case 'as:Dislike': ActivityPub\Processor::dislikeItem($object_data, $body); break; - case 'Update': - if (in_array($object_data['object_type'], ActivityPub::CONTENT_TYPES)) { + case 'as:Update': + if (in_array($object_data['object_type'], self::CONTENT_TYPES)) { /// @todo - } elseif (in_array($object_data['object_type'], ActivityPub::ACCOUNT_TYPES)) { + } elseif (in_array($object_data['object_type'], self::ACCOUNT_TYPES)) { ActivityPub\Processor::updatePerson($object_data, $body); } break; - case 'Delete': - if ($object_data['object_type'] == 'Tombstone') { + case 'as:Delete': + if ($object_data['object_type'] == 'as:Tombstone') { ActivityPub\Processor::deleteItem($object_data, $body); - } elseif (in_array($object_data['object_type'], ActivityPub::ACCOUNT_TYPES)) { + } elseif (in_array($object_data['object_type'], self::ACCOUNT_TYPES)) { ActivityPub\Processor::deletePerson($object_data, $body); } break; - case 'Follow': + case 'as:Follow': ActivityPub\Processor::followUser($object_data); break; - case 'Accept': - if ($object_data['object_type'] == 'Follow') { + case 'as:Accept': + if ($object_data['object_type'] == 'as:Follow') { ActivityPub\Processor::acceptFollowUser($object_data); } break; - case 'Reject': - if ($object_data['object_type'] == 'Follow') { + case 'as:Reject': + if ($object_data['object_type'] == 'as:Follow') { ActivityPub\Processor::rejectFollowUser($object_data); } break; - case 'Undo': - if ($object_data['object_type'] == 'Follow') { + case 'as:Undo': + if ($object_data['object_type'] == 'as:Follow') { ActivityPub\Processor::undoFollowUser($object_data); - } elseif (in_array($object_data['object_type'], ActivityPub::ACTIVITY_TYPES)) { + } elseif (in_array($object_data['object_type'], self::ACTIVITY_TYPES)) { ActivityPub\Processor::undoActivity($object_data); } break; default: - logger('Unknown activity: ' . $activity['type'], LOGGER_DEBUG); + logger('Unknown activity: ' . $type, LOGGER_DEBUG); break; } } /** - * + * Fetch the receiver list from an activity array * * @param array $activity - * @param $actor + * @param string $actor * - * @return + * @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, 'inReplyTo', 'id'); + $replyto = JsonLD::fetchElement($activity, 'as:inReplyTo'); if (!empty($replyto)) { $parents = Item::select(['uid'], ['uri' => $replyto]); while ($parent = Item::fetch($parents)) { @@ -302,22 +317,18 @@ class Receiver $followers = ''; } - foreach (['to', 'cc', 'bto', 'bcc'] as $element) { - if (empty($activity[$element])) { + foreach (['as:to', 'as:cc', 'as:bto', 'as:bcc'] as $element) { + $receiver_list = JsonLD::fetchElementArray($activity, $element); + if (empty($receiver_list)) { continue; } - // The receiver can be an array or a string - if (is_string($activity[$element])) { - $activity[$element] = [$activity[$element]]; - } - - foreach ($activity[$element] as $receiver) { - if ($receiver == ActivityPub::PUBLIC_COLLECTION) { + foreach ($receiver_list as $receiver) { + if ($receiver == self::PUBLIC_COLLECTION) { $receivers['uid:0'] = 0; } - if (($receiver == ActivityPub::PUBLIC_COLLECTION) && !empty($actor)) { + 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]; @@ -330,7 +341,7 @@ class Receiver DBA::close($contacts); } - if (in_array($receiver, [$followers, ActivityPub::PUBLIC_COLLECTION]) && !empty($actor)) { + 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); @@ -453,9 +464,9 @@ class Receiver * @param $object * @param $trust_source * - * @return + * @return array with object data */ - private static function fetchObject($object_id, $object = [], $trust_source = false) + private static function fetchObject($object_id, $object = [], $ldobject = [], $trust_source = false) { if (!$trust_source || is_string($object)) { $data = ActivityPub::fetchContent($object_id); @@ -463,6 +474,7 @@ class Receiver logger('Empty content for ' . $object_id . ', check if content is available locally.', LOGGER_DEBUG); $data = $object_id; } else { + $ldobject = JsonLD::compact($data); logger('Fetched content for ' . $object_id, LOGGER_DEBUG); } } else { @@ -478,6 +490,7 @@ class Receiver } logger('Using already stored item for url ' . $object_id, LOGGER_DEBUG); $data = ActivityPub\Transmitter::createNote($item); + $ldobject = JsonLD::compact($data); } if (empty($data['type'])) { @@ -486,7 +499,7 @@ class Receiver } if (in_array($data['type'], ActivityPub::CONTENT_TYPES)) { - return self::processObject($data); + return self::processObject($ldobject); } if ($data['type'] == 'Announce') { @@ -500,55 +513,107 @@ class Receiver } /** - * + * Convert tags from JSON-LD format into a simplified format * - * @param $object + * @param array $tags Tags in JSON-LD format * - * @return + * @return array with tags in a simplified format + */ + private static function processTags($tags) + { + $taglist = []; + foreach ($tags as $tag) { + $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 = []; + foreach ($attachments as $attachment) { + $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 (empty($object['id'])) { + if (!JsonLD::fetchElement($object, '@id')) { return false; } $object_data = []; - $object_data['object_type'] = $object['type']; - $object_data['id'] = $object['id']; + $object_data['object_type'] = JsonLD::fetchElement($object, '@type'); + $object_data['id'] = JsonLD::fetchElement($object, '@id'); - if (!empty($object['inReplyTo'])) { - $object_data['reply-to-id'] = JsonLD::fetchElement($object, 'inReplyTo', 'id'); - } else { + $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'] = defaults($object, 'published', null); - $object_data['updated'] = defaults($object, 'updated', $object_data['published']); + $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, 'attributedTo', 'id'); + $actor = JsonLD::fetchElement($object, 'as:attributedTo'); if (empty($actor)) { - $actor = defaults($object, 'actor', null); + $actor = JsonLD::fetchElement($object, 'as:actor'); } - $object_data['diaspora:guid'] = defaults($object, 'diaspora:guid', null); + $object_data['diaspora:guid'] = JsonLD::fetchElement($object, 'diaspora:guid'); + $object_data['diaspora:comment'] = JsonLD::fetchElement($object, 'diaspora:comment'); $object_data['owner'] = $object_data['author'] = $actor; - $object_data['context'] = defaults($object, 'context', null); - $object_data['conversation'] = defaults($object, 'conversation', null); - $object_data['sensitive'] = defaults($object, 'sensitive', null); - $object_data['name'] = defaults($object, 'title', null); - $object_data['name'] = defaults($object, 'name', $object_data['name']); - $object_data['summary'] = defaults($object, 'summary', null); - $object_data['content'] = defaults($object, 'content', null); - $object_data['source'] = defaults($object, 'source', null); - $object_data['location'] = JsonLD::fetchElement($object, 'location', 'name', 'type', 'Place'); - $object_data['attachments'] = defaults($object, 'attachment', null); - $object_data['tags'] = defaults($object, 'tag', null); - $object_data['service'] = JsonLD::fetchElement($object, 'instrument', 'name', 'type', 'Service'); - $object_data['alternate-url'] = JsonLD::fetchElement($object, 'url', 'href'); + $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['attachments'] = self::processAttachments(JsonLD::fetchElementArray($object, 'as:attachment')); + $object_data['tags'] = self::processTags(JsonLD::fetchElementArray($object, 'as:tag')); +// $object_data['service'] = JsonLD::fetchElement($object, 'instrument', 'name', 'type', 'Service'); // todo + $object_data['service'] = null; + $object_data['alternate-url'] = JsonLD::fetchElement($object, 'as:url'); + + // Special treatment for Hubzilla links + if (is_array($object_data['alternate-url'])) { + if (!empty($object['as:url'])) { + $object_data['alternate-url'] = JsonLD::fetchElement($object['as:url'], 'as:href'); + } else { + $object_data['alternate-url'] = null; + } + } + $object_data['receiver'] = self::getReceivers($object, $object_data['owner']); // Common object data: diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index cb3e1f30af..26467e68f8 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -29,6 +29,10 @@ use Friendica\Core\Cache; * * To-Do: * + * Missing object fields: + * - service (App) + * - location + * * Missing object types: * - Event * diff --git a/src/Util/JsonLD.php b/src/Util/JsonLD.php index ddf8d93533..b4c362884c 100644 --- a/src/Util/JsonLD.php +++ b/src/Util/JsonLD.php @@ -82,10 +82,13 @@ class JsonLD { jsonld_set_document_loader('Friendica\Util\JsonLD::documentLoader'); - $context = (object)['as' => 'https://www.w3.org/ns/activitystreams', - 'w3sec' => 'https://w3id.org/security', - 'ostatus' => (object)['@id' => 'http://ostatus.org#', '@type' => '@id'], + $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'], + '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)); @@ -95,6 +98,45 @@ class JsonLD 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]; + } else { + $elements[] = $entry; + } + } + + return $elements; + } + /** * @brief Fetches an element from a JSON array * @@ -106,38 +148,40 @@ class JsonLD * * @return fetched element */ - public static function fetchElement($array, $element, $key, $type = null, $type_value = null) + public static function fetchElement($array, $element, $key = '@id', $type = null, $type_value = null) { if (empty($array)) { - return false; + return null; } - if (empty($array[$element])) { - return false; + if (!isset($array[$element])) { + return null; } - if (is_string($array[$element])) { + if (!is_array($array[$element])) { return $array[$element]; } - if (is_null($type_value)) { - if (!empty($array[$element][$key])) { - return $array[$element][$key]; + if (is_null($type) || is_null($type_value)) { + $element_array = self::fetchElementArray($array, $element, $key); + if (is_null($element_array)) { + return null; } - if (!empty($array[$element][0][$key])) { - return $array[$element][0][$key]; + 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 false; } - if (!empty($array[$element][$key]) && !empty($array[$element][$type]) && ($array[$element][$type] == $type_value)) { - return $array[$element][$key]; - } - - /// @todo Add array search - - return false; + return null; } } From 28456de249fe05a1edd88b9451451a22e18b27b3 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Sun, 7 Oct 2018 16:34:08 +0200 Subject: [PATCH 310/428] Save return_url before login. Add login mask to many sites if not logged in. --- mod/contacts.php | 3 ++- mod/events.php | 3 ++- mod/message.php | 3 ++- mod/notifications.php | 3 ++- mod/profiles.php | 3 ++- mod/settings.php | 3 ++- src/Module/Login.php | 3 +++ 7 files changed, 15 insertions(+), 6 deletions(-) diff --git a/mod/contacts.php b/mod/contacts.php index c33e9b6206..7597fd6432 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -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) { @@ -375,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) { diff --git a/mod/events.php b/mod/events.php index d04aac3761..e5ebf86465 100644 --- a/mod/events.php +++ b/mod/events.php @@ -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'; @@ -193,7 +194,7 @@ function events_content(App $a) { if (!local_user()) { notice(L10n::t('Permission denied.') . EOL); - return; + return Login::form(); } if ($a->argc == 1) { diff --git a/mod/message.php b/mod/message.php index 13ae2f7512..bb3000736a 100644 --- a/mod/message.php +++ b/mod/message.php @@ -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'; @@ -97,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']; diff --git a/mod/notifications.php b/mod/notifications.php index 3934a32357..867c7260da 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -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); diff --git a/mod/profiles.php b/mod/profiles.php index 7d0c3178cf..f41cb72af4 100644 --- a/mod/profiles.php +++ b/mod/profiles.php @@ -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 = ''; diff --git a/mod/settings.php b/mod/settings.php index 78fa446ce0..1e6ce1354e 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -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) { @@ -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'])) { diff --git a/src/Module/Login.php b/src/Module/Login.php index ad5d5ad0b6..f1f728ae90 100644 --- a/src/Module/Login.php +++ b/src/Module/Login.php @@ -47,7 +47,10 @@ class Login extends BaseModule public static function post() { + $return_url = $_SESSION['return_url']; session_unset(); + $_SESSION['return_url'] = $return_url; + // OpenId Login if ( empty($_POST['password']) From 36c31e409150998135d8740bbb2d663eb5892cf3 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 7 Oct 2018 15:34:51 +0000 Subject: [PATCH 311/428] Switching to parsing the JSON-LD --- src/Protocol/ActivityPub/Processor.php | 41 +++++++++------- src/Protocol/ActivityPub/Receiver.php | 65 +++++++++++++++----------- 2 files changed, 60 insertions(+), 46 deletions(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index f117c8c33e..819892cb66 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -138,7 +138,7 @@ class Processor { $item = []; $item['verb'] = ACTIVITY_LIKE; - $item['parent-uri'] = $activity['object']; + $item['parent-uri'] = JsonLD::fetchElement($activity, 'object'); $item['gravity'] = GRAVITY_ACTIVITY; $item['object-type'] = ACTIVITY_OBJ_NOTE; @@ -154,7 +154,7 @@ class Processor public static function deleteItem($activity) { $owner = Contact::getIdForURL($activity['owner']); - $object = JsonLD::fetchElement($activity, 'object', 'id'); + $object = JsonLD::fetchElement($activity, 'object'); logger('Deleting item ' . $object . ' from ' . $owner, LOGGER_DEBUG); Item::delete(['uri' => $object, 'owner-id' => $owner]); } @@ -169,7 +169,7 @@ class Processor { $item = []; $item['verb'] = ACTIVITY_DISLIKE; - $item['parent-uri'] = $activity['object']; + $item['parent-uri'] = JsonLD::fetchElement($activity, 'object'); $item['gravity'] = GRAVITY_ACTIVITY; $item['object-type'] = ACTIVITY_OBJ_NOTE; @@ -261,7 +261,8 @@ class Processor $activity['published'] = $object['published']; $activity['type'] = 'Create'; - ActivityPub\Receiver::processActivity($activity); + $ldactivity = JsonLD::compact($activity); + ActivityPub\Receiver::processActivity($activity, $ldactivity); logger('Activity ' . $url . ' had been fetched and processed.'); } @@ -272,7 +273,7 @@ class Processor */ public static function followUser($activity) { - $actor = JsonLD::fetchElement($activity, 'object', 'id'); + $actor = JsonLD::fetchElement($activity, 'object'); $uid = User::getIdForURL($actor); if (empty($uid)) { return; @@ -312,12 +313,13 @@ class Processor */ public static function updatePerson($activity) { - if (empty($activity['object']['id'])) { + $actor = JsonLD::fetchElement($activity, 'object'); + if ($actor) { return; } - logger('Updating profile for ' . $activity['object']['id'], LOGGER_DEBUG); - APContact::getByURL($activity['object']['id'], true); + logger('Updating profile for ' . $actor, LOGGER_DEBUG); + APContact::getByURL($actor, true); } /** @@ -327,23 +329,26 @@ class Processor */ public static function deletePerson($activity) { - if (empty($activity['object']['id']) || empty($activity['object']['actor'])) { + $id = JsonLD::fetchElement($activity, 'object'); + $actor = JsonLD::fetchElement($activity, 'object', 'as:actor'); + + if (empty($id) || empty($actor)) { logger('Empty object id or actor.', LOGGER_DEBUG); return; } - if ($activity['object']['id'] != $activity['object']['actor']) { + if ($id != $actor) { logger('Object id does not match actor.', LOGGER_DEBUG); return; } - $contacts = DBA::select('contact', ['id'], ['nurl' => normalise_link($activity['object']['id'])]); + $contacts = DBA::select('contact', ['id'], ['nurl' => normalise_link($id)]); while ($contact = DBA::fetch($contacts)) { - Contact::remove($contact["id"]); + Contact::remove($contact['id']); } DBA::close($contacts); - logger('Deleted contact ' . $activity['object']['id'], LOGGER_DEBUG); + logger('Deleted contact ' . $id, LOGGER_DEBUG); } /** @@ -353,7 +358,7 @@ class Processor */ public static function acceptFollowUser($activity) { - $actor = JsonLD::fetchElement($activity, 'object', 'actor'); + $actor = JsonLD::fetchElement($activity, 'object', 'as:actor'); $uid = User::getIdForURL($actor); if (empty($uid)) { return; @@ -386,7 +391,7 @@ class Processor */ public static function rejectFollowUser($activity) { - $actor = JsonLD::fetchElement($activity, 'object', 'actor'); + $actor = JsonLD::fetchElement($activity, 'object', 'as:actor'); $uid = User::getIdForURL($actor); if (empty($uid)) { return; @@ -415,12 +420,12 @@ class Processor */ public static function undoActivity($activity) { - $activity_url = JsonLD::fetchElement($activity, 'object', 'id'); + $activity_url = JsonLD::fetchElement($activity, 'object'); if (empty($activity_url)) { return; } - $actor = JsonLD::fetchElement($activity, 'object', 'actor'); + $actor = JsonLD::fetchElement($activity, 'object', 'as:actor'); if (empty($actor)) { return; } @@ -440,7 +445,7 @@ class Processor */ public static function undoFollowUser($activity) { - $object = JsonLD::fetchElement($activity, 'object', 'object'); + $object = JsonLD::fetchElement($activity, 'object', 'as:object'); $uid = User::getIdForURL($object); if (empty($uid)) { return; diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 48bfc0c8c8..1d807365bb 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -150,7 +150,7 @@ class Receiver // Fetch the content only on activities where this matters if (in_array($type, ['as:Create', 'as:Announce'])) { - $object_data = self::fetchObject($object_id, $activity['object'], $ldactivity['as:object'], $trust_source); + $object_data = self::fetchObject($object_id, $ldactivity['as:object'], $trust_source); if (empty($object_data)) { logger("Object data couldn't be processed", LOGGER_DEBUG); return []; @@ -168,13 +168,13 @@ class Receiver } else { $object_data = []; $object_data['id'] = JsonLD::fetchElement($ldactivity, '@id'); - $object_data['object'] = $activity['object']; + $object_data['object'] = $ldactivity['as:object']; $object_data['object_type'] = JsonLD::fetchElement($ldactivity, 'as:object', '@type'); } $object_data = self::addActivityFields($object_data, $activity); - $object_data['type'] = $activity['type']; + $object_data['type'] = $type; $object_data['owner'] = $actor; $object_data['receiver'] = array_merge(defaults($object_data, 'receiver', []), $receivers); @@ -466,50 +466,49 @@ class Receiver * * @return array with object data */ - private static function fetchObject($object_id, $object = [], $ldobject = [], $trust_source = false) + private static function fetchObject($object_id, $object = [], $trust_source = false) { - if (!$trust_source || is_string($object)) { + if (!$trust_source || empty($object)) { $data = ActivityPub::fetchContent($object_id); - if (empty($data)) { - logger('Empty content for ' . $object_id . ', check if content is available locally.', LOGGER_DEBUG); - $data = $object_id; - } else { - $ldobject = JsonLD::compact($data); + 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); - $data = $object; } - if (is_string($data)) { - $item = Item::selectFirst([], ['uri' => $data]); - if (!DBA::isResult($item)) { - logger('Object with url ' . $data . ' was not found locally.', LOGGER_DEBUG); - return false; - } - logger('Using already stored item for url ' . $object_id, LOGGER_DEBUG); - $data = ActivityPub\Transmitter::createNote($item); - $ldobject = JsonLD::compact($data); - } + $type = JsonLD::fetchElement($object, '@type'); - if (empty($data['type'])) { + if (empty($type)) { logger('Empty type', LOGGER_DEBUG); return false; } - if (in_array($data['type'], ActivityPub::CONTENT_TYPES)) { - return self::processObject($ldobject); + if (in_array($type, self::CONTENT_TYPES)) { + return self::processObject($object); } - if ($data['type'] == 'Announce') { - if (empty($data['object'])) { + if ($type == 'as:Announce') { + $object_id = JsonLD::fetchElement($object, 'object'); + if (empty($object_id)) { return false; } - return self::fetchObject($data['object']); + return self::fetchObject($object_id); } - logger('Unhandled object type: ' . $data['type'], LOGGER_DEBUG); + logger('Unhandled object type: ' . $type, LOGGER_DEBUG); } /** @@ -522,7 +521,12 @@ class Receiver private static function processTags($tags) { $taglist = []; + 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')]; @@ -540,7 +544,12 @@ class Receiver private static function processAttachments($attachments) { $attachlist = []; + 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'), From 616c4a89bd9fde2be3bf398bcd0cc777f617a5fe Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 7 Oct 2018 17:17:06 +0000 Subject: [PATCH 312/428] The new parsing is now active --- src/Module/Inbox.php | 4 +- src/Protocol/ActivityPub.php | 3 +- src/Protocol/ActivityPub/Processor.php | 2 +- src/Protocol/ActivityPub/Receiver.php | 58 +++++++++++++++----------- 4 files changed, 39 insertions(+), 28 deletions(-) diff --git a/src/Module/Inbox.php b/src/Module/Inbox.php index c190be4d1f..3b845074d2 100644 --- a/src/Module/Inbox.php +++ b/src/Module/Inbox.php @@ -26,7 +26,7 @@ class Inbox extends BaseModule } // Enable for test purposes -/* + if (HTTPSignature::getSigner($postdata, $_SERVER)) { $filename = 'signed-activitypub'; } else { @@ -37,7 +37,7 @@ class Inbox extends BaseModule 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)) { diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index e7614afa99..b1680178e3 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -134,7 +134,8 @@ class ActivityPub } foreach ($items as $activity) { - ActivityPub\Receiver::processActivity($activity, '', $uid, true); + $ldactivity = JsonLD::compact($activity); + ActivityPub\Receiver::processActivity($ldactivity, '', $uid, true); } } } diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 819892cb66..b798b1f2b2 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -262,7 +262,7 @@ class Processor $activity['type'] = 'Create'; $ldactivity = JsonLD::compact($activity); - ActivityPub\Receiver::processActivity($activity, $ldactivity); + ActivityPub\Receiver::processActivity($ldactivity); logger('Activity ' . $url . ' had been fetched and processed.'); } diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 1d807365bb..28f0673fab 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -108,7 +108,7 @@ class Receiver $trust_source = false; } - self::processActivity($activity, $ldactivity, $body, $uid, $trust_source); + self::processActivity($ldactivity, $body, $uid, $trust_source); } /** @@ -120,7 +120,7 @@ class Receiver * * @return */ - private static function prepareObjectData($activity, $ldactivity, $uid, &$trust_source) + private static function prepareObjectData($ldactivity, $uid, &$trust_source) { $actor = JsonLD::fetchElement($ldactivity, 'as:actor'); if (empty($actor)) { @@ -150,6 +150,9 @@ class Receiver // 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, $ldactivity['as:object'], $trust_source); if (empty($object_data)) { logger("Object data couldn't be processed", LOGGER_DEBUG); @@ -172,7 +175,7 @@ class Receiver $object_data['object_type'] = JsonLD::fetchElement($ldactivity, 'as:object', '@type'); } - $object_data = self::addActivityFields($object_data, $activity); + $object_data = self::addActivityFields($object_data, $ldactivity); $object_data['type'] = $type; $object_data['owner'] = $actor; @@ -184,19 +187,15 @@ class Receiver } /** - * + * Processes the activity object * - * @param array $activity - * @param $body - * @param integer $uid User ID - * @param $trust_source + * @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, $ldactivity = '', $body = '', $uid = null, $trust_source = false) + public static function processActivity($ldactivity, $body = '', $uid = null, $trust_source = false) { - if (empty($ldactivity)) { - $ldactivity = JsonLD::compact($activity); - } - $type = JsonLD::fetchElement($ldactivity, '@type'); if (!$type) { logger('Empty type', LOGGER_DEBUG); @@ -215,7 +214,7 @@ class Receiver } // $trust_source is called by reference and is set to true if the content was retrieved successfully - $object_data = self::prepareObjectData($activity, $ldactivity, $uid, $trust_source); + $object_data = self::prepareObjectData($ldactivity, $uid, $trust_source); if (empty($object_data)) { logger('No object data found', LOGGER_DEBUG); return; @@ -436,19 +435,19 @@ class Receiver private static function addActivityFields($object_data, $activity) { if (!empty($activity['published']) && empty($object_data['published'])) { - $object_data['published'] = $activity['published']; + $object_data['published'] = JsonLD::fetchElement($activity, 'published', '@value'); } if (!empty($activity['updated']) && empty($object_data['updated'])) { - $object_data['updated'] = $activity['updated']; + $object_data['updated'] = JsonLD::fetchElement($activity, 'updated', '@value'); } if (!empty($activity['diaspora:guid']) && empty($object_data['diaspora:guid'])) { - $object_data['diaspora:guid'] = $activity['diaspora:guid']; + $object_data['diaspora:guid'] = JsonLD::fetchElement($activity, 'diaspora:guid'); } if (!empty($activity['inReplyTo']) && empty($object_data['parent-uri'])) { - $object_data['parent-uri'] = JsonLD::fetchElement($activity, 'inReplyTo', 'id'); + $object_data['parent-uri'] = JsonLD::fetchElement($activity, 'inReplyTo'); } if (!empty($activity['instrument'])) { @@ -458,17 +457,20 @@ class Receiver } /** - * + * Fetches the object data from external ressources if needed * - * @param $object_id - * @param $object - * @param $trust_source + * @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 object data + * @return array with trusted and valid object data */ private static function fetchObject($object_id, $object = [], $trust_source = false) { - if (!$trust_source || empty($object)) { + // 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); @@ -522,6 +524,10 @@ class Receiver { $taglist = []; + if (empty($tags)) { + return []; + } + foreach ($tags as $tag) { if (empty($tag)) { continue; @@ -545,6 +551,10 @@ class Receiver { $attachlist = []; + if (empty($attachments)) { + return []; + } + foreach ($attachments as $attachment) { if (empty($attachment)) { continue; From 1efca1b75db472b743c15f5a3307895af30fd1e7 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 7 Oct 2018 17:35:43 +0000 Subject: [PATCH 313/428] owner is now actor --- src/Protocol/ActivityPub/Processor.php | 24 ++++++++++++------------ src/Protocol/ActivityPub/Receiver.php | 6 +++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index b798b1f2b2..74d4416f1e 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -153,7 +153,7 @@ class Processor */ public static function deleteItem($activity) { - $owner = Contact::getIdForURL($activity['owner']); + $owner = Contact::getIdForURL($activity['actor']); $object = JsonLD::fetchElement($activity, 'object'); logger('Deleting item ' . $object . ' from ' . $owner, LOGGER_DEBUG); Item::delete(['uri' => $object, 'owner-id' => $owner]); @@ -195,7 +195,7 @@ class Processor $item['network'] = Protocol::ACTIVITYPUB; $item['private'] = !in_array(0, $activity['receiver']); $item['author-id'] = Contact::getIdForURL($activity['author'], 0, true); - $item['owner-id'] = Contact::getIdForURL($activity['owner'], 0, true); + $item['owner-id'] = Contact::getIdForURL($activity['actor'], 0, true); $item['uri'] = $activity['id']; $item['created'] = $activity['published']; $item['edited'] = $activity['updated']; @@ -281,18 +281,18 @@ class Processor $owner = User::getOwnerDataById($uid); - $cid = Contact::getIdForURL($activity['owner'], $uid); + $cid = Contact::getIdForURL($activity['actor'], $uid); if (!empty($cid)) { $contact = DBA::selectFirst('contact', [], ['id' => $cid, 'network' => Protocol::NATIVE_SUPPORT]); } else { $contact = false; } - $item = ['author-id' => Contact::getIdForURL($activity['owner']), - 'author-link' => $activity['owner']]; + $item = ['author-id' => Contact::getIdForURL($activity['actor']), + 'author-link' => $activity['actor']]; Contact::addRelationship($owner, $contact, $item); - $cid = Contact::getIdForURL($activity['owner'], $uid); + $cid = Contact::getIdForURL($activity['actor'], $uid); if (empty($cid)) { return; } @@ -366,9 +366,9 @@ class Processor $owner = User::getOwnerDataById($uid); - $cid = Contact::getIdForURL($activity['owner'], $uid); + $cid = Contact::getIdForURL($activity['actor'], $uid); if (empty($cid)) { - logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); + logger('No contact found for ' . $activity['actor'], LOGGER_DEBUG); return; } @@ -399,9 +399,9 @@ class Processor $owner = User::getOwnerDataById($uid); - $cid = Contact::getIdForURL($activity['owner'], $uid); + $cid = Contact::getIdForURL($activity['actor'], $uid); if (empty($cid)) { - logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); + logger('No contact found for ' . $activity['actor'], LOGGER_DEBUG); return; } @@ -453,9 +453,9 @@ class Processor $owner = User::getOwnerDataById($uid); - $cid = Contact::getIdForURL($activity['owner'], $uid); + $cid = Contact::getIdForURL($activity['actor'], $uid); if (empty($cid)) { - logger('No contact found for ' . $activity['owner'], LOGGER_DEBUG); + logger('No contact found for ' . $activity['actor'], LOGGER_DEBUG); return; } diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 28f0673fab..1a261d2bfd 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -178,7 +178,7 @@ class Receiver $object_data = self::addActivityFields($object_data, $ldactivity); $object_data['type'] = $type; - $object_data['owner'] = $actor; + $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); @@ -609,7 +609,7 @@ class Receiver $object_data['diaspora:guid'] = JsonLD::fetchElement($object, 'diaspora:guid'); $object_data['diaspora:comment'] = JsonLD::fetchElement($object, 'diaspora:comment'); - $object_data['owner'] = $object_data['author'] = $actor; + $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'); @@ -633,7 +633,7 @@ class Receiver } } - $object_data['receiver'] = self::getReceivers($object, $object_data['owner']); + $object_data['receiver'] = self::getReceivers($object, $object_data['actor']); // Common object data: From bd6ba98e8d8da4fa3b2075734d1db5a65be2c3f5 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 7 Oct 2018 18:41:45 +0000 Subject: [PATCH 314/428] Some more cleanup --- src/Protocol/ActivityPub/Processor.php | 83 +++++++++++--------------- src/Protocol/ActivityPub/Receiver.php | 40 +++++++------ 2 files changed, 57 insertions(+), 66 deletions(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 74d4416f1e..7d181234fe 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -67,9 +67,9 @@ class Processor } /** - * + * Add attachment data to the item array * - * @param $attachments + * @param array $attachments * @param array $item * * @return item array @@ -101,10 +101,10 @@ class Processor } /** - * + * Prepares data for a message * - * @param array $activity - * @param $body + * @param array $activity Activity array + * @param string $body original source */ public static function createItem($activity, $body) { @@ -129,16 +129,16 @@ class Processor } /** - * + * Prepare the item array for a "like" * - * @param array $activity - * @param $body + * @param array $activity Activity array + * @param string $body original source */ public static function likeItem($activity, $body) { $item = []; $item['verb'] = ACTIVITY_LIKE; - $item['parent-uri'] = JsonLD::fetchElement($activity, 'object'); + $item['parent-uri'] = $activity['object_id']; $item['gravity'] = GRAVITY_ACTIVITY; $item['object-type'] = ACTIVITY_OBJ_NOTE; @@ -149,27 +149,26 @@ class Processor * Delete items * * @param array $activity - * @param $body */ public static function deleteItem($activity) { $owner = Contact::getIdForURL($activity['actor']); - $object = JsonLD::fetchElement($activity, 'object'); - logger('Deleting item ' . $object . ' from ' . $owner, LOGGER_DEBUG); - Item::delete(['uri' => $object, 'owner-id' => $owner]); + + 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 - * @param $body + * @param array $activity Activity array + * @param string $body original source */ public static function dislikeItem($activity, $body) { $item = []; $item['verb'] = ACTIVITY_DISLIKE; - $item['parent-uri'] = JsonLD::fetchElement($activity, 'object'); + $item['parent-uri'] = $activity['object_id']; $item['gravity'] = GRAVITY_ACTIVITY; $item['object-type'] = ACTIVITY_OBJ_NOTE; @@ -177,11 +176,11 @@ class Processor } /** - * + * Creates an item post * - * @param array $activity - * @param array $item - * @param $body + * @param array $activity Activity data + * @param array $item item array + * @param string $body original source */ private static function postItem($activity, $item, $body) { @@ -233,7 +232,7 @@ class Processor } /** - * + * Fetches missing posts * * @param $url * @param $child @@ -273,8 +272,7 @@ class Processor */ public static function followUser($activity) { - $actor = JsonLD::fetchElement($activity, 'object'); - $uid = User::getIdForURL($actor); + $uid = User::getIdForURL($activity['object_actor']); if (empty($uid)) { return; } @@ -313,13 +311,12 @@ class Processor */ public static function updatePerson($activity) { - $actor = JsonLD::fetchElement($activity, 'object'); - if ($actor) { + if (empty($activity['object_id'])) { return; } - logger('Updating profile for ' . $actor, LOGGER_DEBUG); - APContact::getByURL($actor, true); + logger('Updating profile for ' . $activity['object_id'], LOGGER_DEBUG); + APContact::getByURL($activity['object_id'], true); } /** @@ -329,26 +326,23 @@ class Processor */ public static function deletePerson($activity) { - $id = JsonLD::fetchElement($activity, 'object'); - $actor = JsonLD::fetchElement($activity, 'object', 'as:actor'); - - if (empty($id) || empty($actor)) { + if (empty($activity['object_id']) || empty($activity['object_actor'])) { logger('Empty object id or actor.', LOGGER_DEBUG); return; } - if ($id != $actor) { + if ($activity['object_id'] != $activity['object_actor']) { logger('Object id does not match actor.', LOGGER_DEBUG); return; } - $contacts = DBA::select('contact', ['id'], ['nurl' => normalise_link($id)]); + $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 ' . $id, LOGGER_DEBUG); + logger('Deleted contact ' . $activity['object_id'], LOGGER_DEBUG); } /** @@ -358,8 +352,7 @@ class Processor */ public static function acceptFollowUser($activity) { - $actor = JsonLD::fetchElement($activity, 'object', 'as:actor'); - $uid = User::getIdForURL($actor); + $uid = User::getIdForURL($activity['object_actor']); if (empty($uid)) { return; } @@ -391,8 +384,7 @@ class Processor */ public static function rejectFollowUser($activity) { - $actor = JsonLD::fetchElement($activity, 'object', 'as:actor'); - $uid = User::getIdForURL($actor); + $uid = User::getIdForURL($activity['object_actor']); if (empty($uid)) { return; } @@ -420,22 +412,20 @@ class Processor */ public static function undoActivity($activity) { - $activity_url = JsonLD::fetchElement($activity, 'object'); - if (empty($activity_url)) { + if (empty($activity['object_id'])) { return; } - $actor = JsonLD::fetchElement($activity, 'object', 'as:actor'); - if (empty($actor)) { + if (empty($activity['object_actor'])) { return; } - $author_id = Contact::getIdForURL($actor); + $author_id = Contact::getIdForURL($activity['object_actor']); if (empty($author_id)) { return; } - Item::delete(['uri' => $activity_url, 'author-id' => $author_id, 'gravity' => GRAVITY_ACTIVITY]); + Item::delete(['uri' => $activity['object_id'], 'author-id' => $author_id, 'gravity' => GRAVITY_ACTIVITY]); } /** @@ -445,8 +435,7 @@ class Processor */ public static function undoFollowUser($activity) { - $object = JsonLD::fetchElement($activity, 'object', 'as:object'); - $uid = User::getIdForURL($object); + $uid = User::getIdForURL($activity['object_object']); if (empty($uid)) { return; } diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 1a261d2bfd..ba6cd52ba3 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -112,26 +112,26 @@ class Receiver } /** - * + * Prepare the object array * * @param array $activity * @param integer $uid User ID * @param $trust_source * - * @return + * @return array with object data */ - private static function prepareObjectData($ldactivity, $uid, &$trust_source) + private static function prepareObjectData($activity, $uid, &$trust_source) { - $actor = JsonLD::fetchElement($ldactivity, 'as:actor'); + $actor = JsonLD::fetchElement($activity, 'as:actor'); if (empty($actor)) { logger('Empty actor', LOGGER_DEBUG); return []; } - $type = JsonLD::fetchElement($ldactivity, '@type'); + $type = JsonLD::fetchElement($activity, '@type'); // Fetch all receivers from to, cc, bto and bcc - $receivers = self::getReceivers($ldactivity, $actor); + $receivers = self::getReceivers($activity, $actor); // When it is a delivery to a personal inbox we add that user to the receivers if (!empty($uid)) { @@ -142,7 +142,7 @@ class Receiver logger('Receivers: ' . json_encode($receivers), LOGGER_DEBUG); - $object_id = JsonLD::fetchElement($ldactivity, 'as:object'); + $object_id = JsonLD::fetchElement($activity, 'as:object'); if (empty($object_id)) { logger('No object found', LOGGER_DEBUG); return []; @@ -153,7 +153,7 @@ class Receiver if ($type == 'as:Announce') { $trust_source = false; } - $object_data = self::fetchObject($object_id, $ldactivity['as:object'], $trust_source); + $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 []; @@ -163,19 +163,21 @@ class Receiver } 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($ldactivity); + $object_data = self::processObject($activity); $object_data['name'] = $type; - $object_data['author'] = JsonLD::fetchElement($ldactivity, 'as:actor'); + $object_data['author'] = JsonLD::fetchElement($activity, 'as:actor'); $object_data['object'] = $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($ldactivity, '@id'); - $object_data['object'] = $ldactivity['as:object']; - $object_data['object_type'] = JsonLD::fetchElement($ldactivity, 'as:object', '@type'); + $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, $ldactivity); + $object_data = self::addActivityFields($object_data, $activity); $object_data['type'] = $type; $object_data['actor'] = $actor; @@ -194,27 +196,27 @@ class Receiver * @param integer $uid User ID * @param boolean $trust_source Do we trust the source? */ - public static function processActivity($ldactivity, $body = '', $uid = null, $trust_source = false) + public static function processActivity($activity, $body = '', $uid = null, $trust_source = false) { - $type = JsonLD::fetchElement($ldactivity, '@type'); + $type = JsonLD::fetchElement($activity, '@type'); if (!$type) { logger('Empty type', LOGGER_DEBUG); return; } - if (!JsonLD::fetchElement($ldactivity, 'as:object')) { + if (!JsonLD::fetchElement($activity, 'as:object')) { logger('Empty object', LOGGER_DEBUG); return; } - if (!JsonLD::fetchElement($ldactivity, 'as:actor')) { + 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($ldactivity, $uid, $trust_source); + $object_data = self::prepareObjectData($activity, $uid, $trust_source); if (empty($object_data)) { logger('No object data found', LOGGER_DEBUG); return; From 93866b477a2ea43ed12b72cf35bb3241e4c133b3 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 7 Oct 2018 19:42:04 +0000 Subject: [PATCH 315/428] Several fixes --- src/Module/Inbox.php | 4 ++-- src/Protocol/ActivityPub.php | 2 -- src/Protocol/ActivityPub/Processor.php | 6 +++--- src/Protocol/ActivityPub/Receiver.php | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Module/Inbox.php b/src/Module/Inbox.php index 3b845074d2..c190be4d1f 100644 --- a/src/Module/Inbox.php +++ b/src/Module/Inbox.php @@ -26,7 +26,7 @@ class Inbox extends BaseModule } // Enable for test purposes - +/* if (HTTPSignature::getSigner($postdata, $_SERVER)) { $filename = 'signed-activitypub'; } else { @@ -37,7 +37,7 @@ class Inbox extends BaseModule 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)) { diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index b1680178e3..b4668e9154 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -39,8 +39,6 @@ class ActivityPub 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', 'sensitive' => 'as:sensitive', 'Hashtag' => 'as:Hashtag']]; const ACCOUNT_TYPES = ['Person', 'Organization', 'Service', 'Group', 'Application']; - const CONTENT_TYPES = ['Note', 'Article', 'Video', 'Image']; - const ACTIVITY_TYPES = ['Like', 'Dislike', 'Accept', 'Reject', 'TentativeAccept']; /** * Checks if the web request is done for the AP protocol * diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 7d181234fe..32cfcc6cb0 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -272,7 +272,7 @@ class Processor */ public static function followUser($activity) { - $uid = User::getIdForURL($activity['object_actor']); + $uid = User::getIdForURL($activity['object_id']); if (empty($uid)) { return; } @@ -326,12 +326,12 @@ class Processor */ public static function deletePerson($activity) { - if (empty($activity['object_id']) || empty($activity['object_actor'])) { + if (empty($activity['object_id']) || empty($activity['actor'])) { logger('Empty object id or actor.', LOGGER_DEBUG); return; } - if ($activity['object_id'] != $activity['object_actor']) { + if ($activity['object_id'] != $activity['actor']) { logger('Object id does not match actor.', LOGGER_DEBUG); return; } diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index ba6cd52ba3..ac66aeb6ec 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -166,7 +166,7 @@ class Receiver $object_data = self::processObject($activity); $object_data['name'] = $type; $object_data['author'] = JsonLD::fetchElement($activity, 'as:actor'); - $object_data['object'] = $object_id; + $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 = []; From 7da6da6666973efce1553237846aca06d497866d Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 7 Oct 2018 22:14:05 +0200 Subject: [PATCH 316/428] Bugfixings for getAllKeys() --- src/Core/Cache.php | 2 +- src/Core/Cache/DatabaseCacheDriver.php | 8 ++++---- src/Core/Cache/ICacheDriver.php | 2 +- src/Core/Cache/MemcachedCacheDriver.php | 2 +- src/Core/Console/Cache.php | 1 + 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Core/Cache.php b/src/Core/Cache.php index 7b9f6edd2c..b239af7d60 100644 --- a/src/Core/Cache.php +++ b/src/Core/Cache.php @@ -53,7 +53,7 @@ class Cache extends \Friendica\BaseObject * * @param string $prefix Prefix of the keys (optional) * - * @return array|null Null if the driver doesn't support this feature + * @return array Empty if the driver doesn't support this feature */ public static function getAllKeys($prefix = null) { diff --git a/src/Core/Cache/DatabaseCacheDriver.php b/src/Core/Cache/DatabaseCacheDriver.php index 9966457467..d90c6e4f18 100644 --- a/src/Core/Cache/DatabaseCacheDriver.php +++ b/src/Core/Cache/DatabaseCacheDriver.php @@ -21,18 +21,18 @@ class DatabaseCacheDriver extends AbstractCacheDriver implements ICacheDriver if (empty($prefix)) { $where = ['`expires` >= ?', DateTimeFormat::utcNow()]; } else { - $where = ['`expires` >= ? AND k LIKE CONCAT(?, \'%\')', DateTimeFormat::utcNow(), $prefix]; + $where = ['`expires` >= ? AND `k` LIKE CONCAT(?, \'%\')', DateTimeFormat::utcNow(), $prefix]; } $stmt = DBA::select('cache', ['k'], $where); - $list = []; + $keys = []; while ($key = DBA::fetch($stmt)) { - array_push($list, $key['k']); + array_push($keys, $key['k']); } DBA::close($stmt); - return $list; + return $keys; } /** diff --git a/src/Core/Cache/ICacheDriver.php b/src/Core/Cache/ICacheDriver.php index 0a206559cc..2c04c59925 100644 --- a/src/Core/Cache/ICacheDriver.php +++ b/src/Core/Cache/ICacheDriver.php @@ -16,7 +16,7 @@ interface ICacheDriver * * @param string prefix optional a prefix to search * - * @return array|null Null if it isn't supported by the cache driver + * @return array Empty if it isn't supported by the cache driver */ public function getAllKeys($prefix = null); diff --git a/src/Core/Cache/MemcachedCacheDriver.php b/src/Core/Cache/MemcachedCacheDriver.php index 62c3892860..1a6b2a9aef 100644 --- a/src/Core/Cache/MemcachedCacheDriver.php +++ b/src/Core/Cache/MemcachedCacheDriver.php @@ -65,7 +65,7 @@ class MemcachedCacheDriver extends AbstractCacheDriver implements IMemoryCacheDr return $this->filterArrayKeysByPrefix($keys, $prefix); } else { logger('Memcached \'getAllKeys\' failed with ' . $this->memcached->getResultMessage(), LOGGER_ALL); - return null; + return []; } } diff --git a/src/Core/Console/Cache.php b/src/Core/Console/Cache.php index 459a27e20b..1d93c3c011 100644 --- a/src/Core/Console/Cache.php +++ b/src/Core/Console/Cache.php @@ -116,6 +116,7 @@ HELP; $count = 0; foreach ($keys as $key) { $this->out($key); + $count++; } $this->out($count . ' keys found'); From 46f77f348628b5396e286617f22a43e90086a34b Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 7 Oct 2018 20:36:15 +0000 Subject: [PATCH 317/428] Detect the object type --- database.sql | 30 +++++++++++++++-- src/Protocol/ActivityPub/Receiver.php | 47 +++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/database.sql b/database.sql index 7188558042..a797c8df36 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2018.12-dev (The Tazmans Flax-lily) --- DB_UPDATE_VERSION 1283 +-- DB_UPDATE_VERSION 1284 -- ------------------------------------------ @@ -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 -- @@ -212,7 +238,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`), diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index ac66aeb6ec..1dac0bb827 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -30,9 +30,6 @@ use Friendica\Protocol\ActivityPub; * - Remove * - Undo Block * - Undo Accept (Problem: This could invert a contact accept or an event accept) - * - * General: - * - Possibly using the LD-JSON parser */ class Receiver { @@ -111,6 +108,44 @@ class Receiver 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 * @@ -148,6 +183,8 @@ class Receiver 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') { @@ -179,6 +216,10 @@ class Receiver $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); From 30ad6d60fd65ff2520baa7b0e4d18b77cf44096c Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 7 Oct 2018 20:51:39 +0000 Subject: [PATCH 318/428] Duplicated line removed --- src/Util/JsonLD.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Util/JsonLD.php b/src/Util/JsonLD.php index b4c362884c..a581892939 100644 --- a/src/Util/JsonLD.php +++ b/src/Util/JsonLD.php @@ -88,7 +88,6 @@ class JsonLD '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'], - '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)); From 4047952703b4bb41d934e6e4cf758948dc5c84af Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 8 Oct 2018 03:28:49 +0000 Subject: [PATCH 319/428] AP: Avoid an empty avatar field --- src/Protocol/ActivityPub/Transmitter.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 26467e68f8..476c63a58f 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -209,12 +209,17 @@ class Transmitter return []; } - $fields = ['name', 'url', 'location', 'about', 'avatar']; + $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']; From b5d73f840c30e99de07c227450a240a38f1052ab Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 9 Oct 2018 05:04:24 +0000 Subject: [PATCH 320/428] AP fixes: LD-signature, wrong owner for completed thres, account removal --- composer.lock | 10 +++++----- src/Protocol/ActivityPub/Processor.php | 15 ++++++++++++++- src/Protocol/ActivityPub/Receiver.php | 5 +++++ src/Worker/Notifier.php | 4 ++-- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/composer.lock b/composer.lock index 7973167762..9230bb4db9 100644 --- a/composer.lock +++ b/composer.lock @@ -332,11 +332,11 @@ }, { "name": "friendica/json-ld", - "version": "1.0.0", + "version": "1.1.1", "source": { "type": "git", "url": "https://git.friendi.ca/friendica/php-json-ld", - "reference": "a9ac64daf01cfd97e80c36a5104247d37c0ae5ef" + "reference": "ca3916d10d2ad9073b3b1eae383978dbe828e1e1" }, "require": { "ext-json": "*", @@ -355,11 +355,11 @@ { "name": "Digital Bazaar, Inc.", "email": "support@digitalbazaar.com", - "url": "http://digitalbazaar.com/" + "homepage": "http://digitalbazaar.com/" }, { "name": "Friendica Team", - "url": "https://friendi.ca/" + "homepage": "https://friendi.ca/" } ], "description": "A JSON-LD Processor and API implementation in PHP.", @@ -372,7 +372,7 @@ "Semantic Web", "jsonld" ], - "time": "2018-09-28T00:01:12+00:00" + "time": "2018-10-08T20:41:00+00:00" }, { "name": "fxp/composer-asset-plugin", diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 32cfcc6cb0..a85123817a 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -18,6 +18,9 @@ use Friendica\Protocol\ActivityPub; /** * ActivityPub Protocol class + * + * To-Do: + * - Store Diaspora signature */ class Processor { @@ -194,7 +197,14 @@ class Processor $item['network'] = Protocol::ACTIVITYPUB; $item['private'] = !in_array(0, $activity['receiver']); $item['author-id'] = Contact::getIdForURL($activity['author'], 0, true); - $item['owner-id'] = Contact::getIdForURL($activity['actor'], 0, true); + + if (empty($activity['thread-completion'])) { + $item['owner-id'] = Contact::getIdForURL($activity['actor'], 0, true); + } else { + logger('Ignoring actor because of thread completion.', LOGGER_DEBUG); + $item['owner-id'] = $item['author-id']; + } + $item['uri'] = $activity['id']; $item['created'] = $activity['published']; $item['edited'] = $activity['updated']; @@ -261,6 +271,9 @@ class Processor $activity['type'] = 'Create'; $ldactivity = JsonLD::compact($activity); + + $ldactivity['thread-completion'] = true; + ActivityPub\Receiver::processActivity($ldactivity); logger('Activity ' . $url . ' had been fetched and processed.'); } diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 1dac0bb827..f371eede7f 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -268,6 +268,11 @@ class Receiver return; } + // 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': diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index b57c81db77..6bfd2bc3b3 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -103,9 +103,9 @@ class Notifier $inboxes = ActivityPub\Transmitter::fetchTargetInboxesforUser(0); foreach ($inboxes as $inbox) { - logger('Account removal for user ' . $uid . ' to ' . $inbox .' via ActivityPub', LOGGER_DEBUG); + 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, $uid); + 'APDelivery', Delivery::REMOVAL, '', $inbox, $item_id); } return; From 05d27e48aa24d6174abe4d78a1710b0cf2fae7c4 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Tue, 9 Oct 2018 16:47:28 +0200 Subject: [PATCH 321/428] word-wrap for comments in frio style.css --- view/theme/frio/css/style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index c563dd121a..867c8a22ea 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -1525,6 +1525,7 @@ section #jotOpen { } .panel .panel-body .wall-item-content { color: #555; + word-wrap: break-word; } .tread-wrapper .media { overflow: visible; From c0fc3c9845c66d9359c89a6459d7974ab3e40c10 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Tue, 9 Oct 2018 17:12:28 +0200 Subject: [PATCH 322/428] frio set working css property + adding fix for vier --- view/theme/frio/css/style.css | 2 +- view/theme/vier/style.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 867c8a22ea..cd2337a7ab 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -1525,7 +1525,7 @@ section #jotOpen { } .panel .panel-body .wall-item-content { color: #555; - word-wrap: break-word; + word-break: break-all; } .tread-wrapper .media { overflow: visible; diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css index 6c4f2b20f3..10a67cd84c 100644 --- a/view/theme/vier/style.css +++ b/view/theme/vier/style.css @@ -1467,7 +1467,7 @@ section.minimal { /* font-size: 14px; */ max-width: 660px; word-wrap: break-word; - word-break: break-word; + word-break: break-all; /* line-height: 1.36; */ padding-bottom: 6px; } From d8780b1640e47fce4f94b07645ff0cbf174bb598 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Tue, 9 Oct 2018 20:10:34 +0200 Subject: [PATCH 323/428] Replace goaway location SESSION var return_url with page as string value --- include/items.php | 8 ++++---- mod/events.php | 2 +- mod/filerm.php | 4 +--- mod/ostatus_subscribe.php | 2 +- mod/repair_ostatus.php | 2 +- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/include/items.php b/include/items.php index 9fd557a778..8b666f1ca2 100644 --- a/include/items.php +++ b/include/items.php @@ -354,7 +354,7 @@ function drop_item($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('/item/drop/' . $id); } // delete the item Item::deleteForUser(['id' => $item['id']], local_user()); - goaway(System::baseUrl() . '/' . $_SESSION['return_url']); + goaway('/item/drop/' . $id); //NOTREACHED } else { notice(L10n::t('Permission denied.') . EOL); - goaway(System::baseUrl() . '/' . $_SESSION['return_url']); + goaway('/item/drop/' . $id); //NOTREACHED } } diff --git a/mod/events.php b/mod/events.php index e5ebf86465..d6ad97eac6 100644 --- a/mod/events.php +++ b/mod/events.php @@ -187,7 +187,7 @@ function events_post(App $a) Worker::add(PRIORITY_HIGH, "Notifier", "event", $item_id); } - goaway($_SESSION['return_url']); + goaway('/events'); } function events_content(App $a) diff --git a/mod/filerm.php b/mod/filerm.php index bd46a8bfea..55b218e151 100644 --- a/mod/filerm.php +++ b/mod/filerm.php @@ -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(); } diff --git a/mod/ostatus_subscribe.php b/mod/ostatus_subscribe.php index 987f31699e..ffaa6791f3 100644 --- a/mod/ostatus_subscribe.php +++ b/mod/ostatus_subscribe.php @@ -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 } diff --git a/mod/repair_ostatus.php b/mod/repair_ostatus.php index 3acaa687a7..4499220817 100644 --- a/mod/repair_ostatus.php +++ b/mod/repair_ostatus.php @@ -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 } From d18421f7608e855bb0af5e81ed1b85d0a0553619 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Tue, 9 Oct 2018 20:40:25 +0200 Subject: [PATCH 324/428] Return to item if not owned by user or canceld --- include/items.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/items.php b/include/items.php index 8b666f1ca2..cfd792e2da 100644 --- a/include/items.php +++ b/include/items.php @@ -349,7 +349,7 @@ 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)) { @@ -401,7 +401,7 @@ function drop_item($id) } // Now check how the user responded to the confirmation query if (!empty($_REQUEST['canceled'])) { - goaway('/item/drop/' . $id); + goaway('/display/' . $item['guid']); } // delete the item @@ -411,7 +411,7 @@ function drop_item($id) //NOTREACHED } else { notice(L10n::t('Permission denied.') . EOL); - goaway('/item/drop/' . $id); + goaway('/display/' . $item['guid']); //NOTREACHED } } From 29033bdf05f1d4db09f319659ca533894eab4c7f Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Tue, 9 Oct 2018 20:44:30 +0200 Subject: [PATCH 325/428] goaway to network if deleted item + remove goaway for filerm --- include/items.php | 2 +- mod/filerm.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/items.php b/include/items.php index cfd792e2da..e8e2a5da0d 100644 --- a/include/items.php +++ b/include/items.php @@ -407,7 +407,7 @@ function drop_item($id) // delete the item Item::deleteForUser(['id' => $item['id']], local_user()); - goaway('/item/drop/' . $id); + goaway('/network'); //NOTREACHED } else { notice(L10n::t('Permission denied.') . EOL); diff --git a/mod/filerm.php b/mod/filerm.php index 55b218e151..7fb978ae69 100644 --- a/mod/filerm.php +++ b/mod/filerm.php @@ -25,7 +25,7 @@ function filerm_content(App $a) { file_tag_unsave_file(local_user(),$item_id,$term, $category); } - goaway('/network'); + //goaway('/network'); killme(); } From 903290a764a4b4a56053aad7384842b211446828 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 9 Oct 2018 15:09:51 -0400 Subject: [PATCH 326/428] Revert "Word Wrap for long words in comments" --- view/theme/frio/css/style.css | 1 - view/theme/vier/style.css | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index cd2337a7ab..c563dd121a 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -1525,7 +1525,6 @@ section #jotOpen { } .panel .panel-body .wall-item-content { color: #555; - word-break: break-all; } .tread-wrapper .media { overflow: visible; diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css index 10a67cd84c..6c4f2b20f3 100644 --- a/view/theme/vier/style.css +++ b/view/theme/vier/style.css @@ -1467,7 +1467,7 @@ section.minimal { /* font-size: 14px; */ max-width: 660px; word-wrap: break-word; - word-break: break-all; + word-break: break-word; /* line-height: 1.36; */ padding-bottom: 6px; } From 2db2b79bfabf727c23876ae027e35ff517c13638 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Tue, 9 Oct 2018 21:38:17 +0200 Subject: [PATCH 327/428] Give Login Form previous URL to return to. SESSION var is empty if invalid page. empty args is catched by function --- src/Module/Login.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Module/Login.php b/src/Module/Login.php index f1f728ae90..25ddd13502 100644 --- a/src/Module/Login.php +++ b/src/Module/Login.php @@ -42,7 +42,7 @@ class Login extends BaseModule goaway(self::getApp()->get_baseurl()); } - 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() From c0f26ace2ecb5dffcc232ed9015eb7ef20ccf63a Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 9 Oct 2018 19:58:15 +0000 Subject: [PATCH 328/428] AP: Switchting existing contacts to AP when receiving activities --- src/Protocol/ActivityPub/Processor.php | 28 +++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index a85123817a..36b283e8d5 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -294,6 +294,7 @@ class Processor $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; @@ -308,11 +309,6 @@ class Processor return; } - $contact = DBA::selectFirst('contact', ['network'], ['id' => $cid]); - if ($contact['network'] != Protocol::ACTIVITYPUB) { - Contact::updateFromProbe($cid, Protocol::ACTIVITYPUB); - } - DBA::update('contact', ['hub-verify' => $activity['id']], ['id' => $cid]); logger('Follow user ' . $uid . ' from contact ' . $cid . ' with id ' . $activity['id']); } @@ -378,6 +374,8 @@ class Processor return; } + self::switchContact($cid); + $fields = ['pending' => false]; $contact = DBA::selectFirst('contact', ['rel'], ['id' => $cid]); @@ -410,6 +408,8 @@ class Processor 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); @@ -461,6 +461,8 @@ class Processor return; } + self::switchContact($cid); + $contact = DBA::selectFirst('contact', [], ['id' => $cid]); if (!DBA::isResult($contact)) { return; @@ -469,4 +471,20 @@ class Processor 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); + } } From 0994aaf8753ce898fcf4967a25fb990126d586ed Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 9 Oct 2018 20:00:57 +0000 Subject: [PATCH 329/428] AP: Avoid a misleading log entry / unneeded field removed --- src/Protocol/ActivityPub/Processor.php | 3 +++ src/Protocol/ActivityPub/Transmitter.php | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index a85123817a..05e59fd3c1 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -196,12 +196,15 @@ class Processor $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']; } diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 476c63a58f..96c069e589 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -778,7 +778,6 @@ class Transmitter $data['url'] = $item['plink']; $data['attributedTo'] = $item['author-link']; - $data['actor'] = $item['author-link']; $data['sensitive'] = self::isSensitive($item['id']); $data['context'] = self::fetchContextURLForItem($item); From 5a02e39a65f8f685440228cc1d36738cbe15f32b Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Tue, 9 Oct 2018 19:58:58 +0200 Subject: [PATCH 330/428] Rename App Methods - renamed a lot of App methods to CamelCase - replaced direct public variables with get-/set-Methods --- bin/worker.php | 2 +- boot.php | 24 +- include/api.php | 2 +- include/enotify.php | 2 +- include/items.php | 2 +- include/text.php | 14 +- index.php | 10 +- mod/admin.php | 28 +-- mod/allfriends.php | 2 +- mod/common.php | 2 +- mod/community.php | 2 +- mod/contacts.php | 2 +- mod/dfrn_request.php | 8 +- mod/directory.php | 4 +- mod/dirfind.php | 4 +- mod/display.php | 2 +- mod/hcard.php | 2 +- mod/home.php | 4 +- mod/hostxrd.php | 2 +- mod/match.php | 4 +- mod/message.php | 2 +- mod/network.php | 10 +- mod/nodeinfo.php | 2 +- mod/notes.php | 2 +- mod/notifications.php | 2 +- mod/notify.php | 2 +- mod/openid.php | 2 +- mod/opensearch.php | 2 +- mod/photo.php | 2 +- mod/photos.php | 10 +- mod/ping.php | 2 +- mod/profile.php | 4 +- mod/profiles.php | 2 +- mod/pubsubhubbub.php | 2 +- mod/redir.php | 2 +- mod/register.php | 4 +- mod/settings.php | 6 +- mod/videos.php | 4 +- mod/viewcontacts.php | 2 +- mod/xrd.php | 6 +- src/App.php | 253 ++++++++++++--------- src/Content/Nav.php | 2 +- src/Content/Text/BBCode.php | 10 +- src/Content/Text/Markdown.php | 2 +- src/Core/Addon.php | 6 +- src/Core/Cache.php | 8 +- src/Core/Cache/AbstractCacheDriver.php | 4 +- src/Core/Console/AutomaticInstallation.php | 4 +- src/Core/Console/DocBloxErrorChecker.php | 2 +- src/Core/Install.php | 2 +- src/Core/NotificationsManager.php | 2 +- src/Core/System.php | 6 +- src/Core/Theme.php | 2 +- src/Core/Worker.php | 4 +- src/Database/DBA.php | 8 +- src/Database/DBStructure.php | 2 +- src/Model/Contact.php | 4 +- src/Model/Item.php | 6 +- src/Model/Photo.php | 2 +- src/Model/Profile.php | 4 +- src/Model/User.php | 2 +- src/Module/Login.php | 18 +- src/Module/Logout.php | 2 +- src/Module/Magic.php | 4 +- src/Module/Proxy.php | 4 +- src/Network/Curl.php | 92 ++++++++ src/Network/Probe.php | 2 +- src/Object/Image.php | 10 +- src/Object/Post.php | 8 +- src/Protocol/DFRN.php | 12 +- src/Protocol/Diaspora.php | 4 +- src/Protocol/Feed.php | 2 +- src/Protocol/OStatus.php | 2 +- src/Protocol/PortableContact.php | 4 +- src/Protocol/Salmon.php | 8 +- src/Render/FriendicaSmarty.php | 4 +- src/Util/ExAuth.php | 4 +- src/Util/HTTPSignature.php | 2 +- src/Util/Network.php | 59 +++-- src/Util/Proxy.php | 2 +- src/Worker/Cron.php | 2 +- src/Worker/CronJobs.php | 6 +- src/Worker/Delivery.php | 4 +- src/Worker/Notifier.php | 2 +- src/Worker/OnePoll.php | 4 +- src/Worker/PubSubPublish.php | 2 +- tests/ApiTest.php | 5 +- tests/DatabaseTest.php | 8 +- tests/src/Core/Cache/MemoryCacheTest.php | 2 +- view/theme/duepuntozero/theme.php | 2 +- view/theme/frio/php/default.php | 2 +- view/theme/frio/theme.php | 4 +- view/theme/smoothly/theme.php | 2 +- view/theme/vier/theme.php | 4 +- 94 files changed, 481 insertions(+), 338 deletions(-) create mode 100644 src/Network/Curl.php diff --git a/bin/worker.php b/bin/worker.php index ceab479cea..cb09a4929d 100755 --- a/bin/worker.php +++ b/bin/worker.php @@ -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(); diff --git a/boot.php b/boot.php index b1d5b593fd..64741b1762 100644 --- a/boot.php +++ b/boot.php @@ -556,7 +556,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()); } @@ -975,27 +975,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; @@ -1077,8 +1077,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(); @@ -1089,7 +1089,7 @@ function get_itemcachepath() mkdir($itemcache); } - if (App::directory_usable($itemcache)) { + if (App::isDirectoryUsable($itemcache)) { Config::set("system", "itemcache", $itemcache); return $itemcache; } @@ -1105,7 +1105,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; } @@ -1120,7 +1120,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; diff --git a/include/api.php b/include/api.php index cab0290de3..01cb93a3b8 100644 --- a/include/api.php +++ b/include/api.php @@ -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'; diff --git a/include/enotify.php b/include/enotify.php index 70abce5845..b184a6935e 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -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, ':')); } diff --git a/include/items.php b/include/items.php index e8e2a5da0d..236e63dd25 100644 --- a/include/items.php +++ b/include/items.php @@ -318,7 +318,7 @@ function subscribe_to_hub($url, array $importer, array $contact, $hubmode = 'sub Network::post($url, $params); - logger('subscribe_to_hub: returns: ' . $a->get_curl_code(), LOGGER_DEBUG); + logger('subscribe_to_hub: returns: ' . Network::getCurl()->getCode(), LOGGER_DEBUG); return; diff --git a/include/text.php b/include/text.php index 7013c2c91b..5a18529d93 100644 --- a/include/text.php +++ b/include/text.php @@ -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"); } @@ -1414,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'); } diff --git a/index.php b/index.php index 19b85b9356..7ec3485d84 100644 --- 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; @@ -49,7 +47,7 @@ if ($a->isMaxProcessesReached() || $a->isMaxLoadReached()) { } if (!$a->getMode()->isInstall()) { - if (Config::get('system', 'force_ssl') && ($a->get_scheme() == "http") + 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 +76,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(); diff --git a/mod/admin.php b/mod/admin.php index 77ac7eddf8..f186f127ad 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -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 .htconfig.php. See the Config help page 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 .htconfig.php. See the Config help page 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('%s is not reachable on your system. This is a severe configuration issue that prevents server to server communication. See the installation page 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); @@ -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 */ diff --git a/mod/allfriends.php b/mod/allfriends.php index 7623a9cd06..b41d0c891b 100644 --- a/mod/allfriends.php +++ b/mod/allfriends.php @@ -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)) { diff --git a/mod/common.php b/mod/common.php index afe78ce460..d694527b86 100644 --- a/mod/common.php +++ b/mod/common.php @@ -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; diff --git a/mod/community.php b/mod/community.php index 9c9fb43900..d1432b7bbb 100644 --- a/mod/community.php +++ b/mod/community.php @@ -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); diff --git a/mod/contacts.php b/mod/contacts.php index 7597fd6432..4e149ab74f 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -793,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']; } diff --git a/mod/dfrn_request.php b/mod/dfrn_request.php index 25fe69066f..4971cb8609 100644 --- a/mod/dfrn_request.php +++ b/mod/dfrn_request.php @@ -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); diff --git a/mod/directory.php b/mod/directory.php index 411024dc1a..202132e366 100644 --- a/mod/directory.php +++ b/mod/directory.php @@ -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 "; diff --git a/mod/dirfind.php b/mod/dirfind.php index 4223bb6ecd..5fe9ae13af 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -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)) { diff --git a/mod/display.php b/mod/display.php index fe8e960f9e..a03b918372 100644 --- a/mod/display.php +++ b/mod/display.php @@ -365,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; diff --git a/mod/hcard.php b/mod/hcard.php index 0c046da540..11e5475f43 100644 --- a/mod/hcard.php +++ b/mod/hcard.php @@ -50,7 +50,7 @@ function hcard_init(App $a) $a->page['htmlhead'] .= '' . "\r\n" ; $a->page['htmlhead'] .= '' . "\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'] .= '' . "\r\n"; header('Link: <' . System::baseUrl() . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false); diff --git a/mod/home.php b/mod/home.php index d28bf3cb43..33d736a4e1 100644 --- a/mod/home.php +++ b/mod/home.php @@ -38,8 +38,8 @@ function home_content(App $a) { $customhome = false; $defaultheader = '

    ' . (Config::get('config', 'sitename') ? L10n::t('Welcome to %s', Config::get('config', 'sitename')) : '') . '

    '; - $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)) { diff --git a/mod/hostxrd.php b/mod/hostxrd.php index 16f132fe09..30343381c3 100644 --- a/mod/hostxrd.php +++ b/mod/hostxrd.php @@ -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'))] diff --git a/mod/match.php b/mod/match.php index caa4c944ca..bb1e4542ae 100644 --- a/mod/match.php +++ b/mod/match.php @@ -67,8 +67,8 @@ function match_content(App $a) $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)) { diff --git a/mod/message.php b/mod/message.php index bb3000736a..f9c5c29ec7 100644 --- a/mod/message.php +++ b/mod/message.php @@ -279,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']); diff --git a/mod/network.php b/mod/network.php index 58e147d1f7..fb0093849e 100644 --- a/mod/network.php +++ b/mod/network.php @@ -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; diff --git a/mod/nodeinfo.php b/mod/nodeinfo.php index 072986cc5e..ed0166838f 100644 --- a/mod/nodeinfo.php +++ b/mod/nodeinfo.php @@ -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); diff --git a/mod/notes.php b/mod/notes.php index 01f283870e..da8352966e 100644 --- a/mod/notes.php +++ b/mod/notes.php @@ -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']]]; diff --git a/mod/notifications.php b/mod/notifications.php index 867c7260da..1885f96447 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -120,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']; diff --git a/mod/notify.php b/mod/notify.php index 458d0140a6..a277e59813 100644 --- a/mod/notify.php +++ b/mod/notify.php @@ -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"]); diff --git a/mod/openid.php b/mod/openid.php index 41d45c1f60..63b29684b3 100644 --- a/mod/openid.php +++ b/mod/openid.php @@ -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()) { diff --git a/mod/opensearch.php b/mod/opensearch.php index 8a427908bc..5410024100 100644 --- a/mod/opensearch.php +++ b/mod/opensearch.php @@ -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; diff --git a/mod/photo.php b/mod/photo.php index 6d456b349e..b1dd9a5c3a 100644 --- a/mod/photo.php +++ b/mod/photo.php @@ -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"); diff --git a/mod/photos.php b/mod/photos.php index 568d6eb537..259209ed40 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -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`, diff --git a/mod/ping.php b/mod/ping.php index 968751a7da..ff0139f28f 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -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']); } diff --git a/mod/profile.php b/mod/profile.php index 5b306b20fb..c57f403930 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -91,7 +91,7 @@ function profile_init(App $a) $a->page['htmlhead'] .= '' . "\r\n"; $a->page['htmlhead'] .= '' . "\r\n"; $a->page['htmlhead'] .= '' . "\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'] .= '' . "\r\n"; header('Link: <' . System::baseUrl() . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false); @@ -307,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'])); diff --git a/mod/profiles.php b/mod/profiles.php index f41cb72af4..3e6bd1cb0d 100644 --- a/mod/profiles.php +++ b/mod/profiles.php @@ -667,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'], diff --git a/mod/pubsubhubbub.php b/mod/pubsubhubbub.php index 8f9478d8aa..5697be8305 100644 --- a/mod/pubsubhubbub.php +++ b/mod/pubsubhubbub.php @@ -105,7 +105,7 @@ function pubsubhubbub_init(App $a) { // Social/StatusNet doesn't honour it (yet) $body = Network::fetchUrl($hub_callback . "?" . $params); - $ret = $a->get_curl_code(); + $ret = Network::getCurl()->getCode(); // give up if the HTTP return code wasn't a success (2xx) if ($ret < 200 || $ret > 299) { diff --git a/mod/redir.php b/mod/redir.php index 3acf960dab..b9a24210b6 100644 --- a/mod/redir.php +++ b/mod/redir.php @@ -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 diff --git a/mod/register.php b/mod/register.php index b851faf2d6..454062d89b 100644 --- a/mod/register.php +++ b/mod/register.php @@ -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 \'nickname@%s\'.', $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 \'nickname@%s\'.', $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'), diff --git a/mod/settings.php b/mod/settings.php index 1e6ce1354e..3a6c8c3fab 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -547,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 { @@ -1136,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 '%s' or '%s'.", $nickname . '@' . $a->get_hostname() . $a->get_path(), System::baseUrl() . '/profile/' . $nickname), - '$basepath' => $a->get_hostname() + '$desc' => L10n::t("Your Identity Address is '%s' or '%s'.", $nickname . '@' . $a->getHostName() . $a->getURLpath(), System::baseUrl() . '/profile/' . $nickname), + '$basepath' => $a->getHostName() ]); $stpl = get_markup_template('settings/settings.tpl'); diff --git a/mod/videos.php b/mod/videos.php index a0c9d0d16e..e52c78cab1 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -341,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`, diff --git a/mod/viewcontacts.php b/mod/viewcontacts.php index 9446470e1b..563c13c6d4 100644 --- a/mod/viewcontacts.php +++ b/mod/viewcontacts.php @@ -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` diff --git a/mod/xrd.php b/mod/xrd.php index 6a5fdbbdb9..801fa9d91b 100644 --- a/mod/xrd.php +++ b/mod/xrd.php @@ -55,9 +55,9 @@ function xrd_init(App $a) $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') { diff --git a/src/App.php b/src/App.php index 61d7335f1a..293d9d3a56 100644 --- a/src/App.php +++ b/src/App.php @@ -54,8 +54,6 @@ class App public $argc; public $module; public $strings; - public $basepath; - public $urlpath; public $hooks = []; public $timezone; public $interactive = true; @@ -65,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 @@ -89,6 +85,31 @@ class App */ private $mode; + /** + * @var string The App basepath + */ + 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; + /** * Register a stylesheet file path to be included in the tag of every page. * Inclusion is done in App->initHead(). @@ -100,7 +121,7 @@ class App */ public function registerStylesheet($path) { - $url = str_replace($this->get_basepath() . DIRECTORY_SEPARATOR, '', $path); + $url = str_replace($this->getBasePath() . DIRECTORY_SEPARATOR, '', $path); $this->stylesheets[] = trim($url, '/'); } @@ -116,7 +137,7 @@ class App */ public function registerFooterScript($path) { - $url = str_replace($this->get_basepath() . DIRECTORY_SEPARATOR, '', $path); + $url = str_replace($this->getBasePath() . DIRECTORY_SEPARATOR, '', $path); $this->footerScripts[] = trim($url, '/'); } @@ -157,26 +178,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 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)) { + if (!static::isDirectoryUsable($basepath, false)) { throw new Exception('Basepath ' . $basepath . ' isn\'t usable.'); } BaseObject::setApp($this); $this->basepath = rtrim($basepath, DIRECTORY_SEPARATOR); + $this->checkBackend($backend); + $this->checkFriendicaApp(); $this->performance['start'] = microtime(true); $this->performance['database'] = 0; @@ -230,9 +251,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); @@ -301,11 +322,8 @@ 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)'; - // Register template engines - $this->register_template_engine('Friendica\Render\FriendicaSmartyEngine'); + $this->registerTemplateEngine('Friendica\Render\FriendicaSmartyEngine'); } /** @@ -334,9 +352,9 @@ class App $this->loadDatabase(); - $this->getMode()->determine($this->basepath); + $this->getMode()->determine($this->getBasePath()); - $this->determineUrlPath(); + $this->determineURLPath(); Config::load(); @@ -372,20 +390,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); @@ -413,8 +431,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); } } @@ -473,8 +491,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); } } @@ -502,7 +520,7 @@ 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'); @@ -562,7 +580,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'); + $this->saveTimestamp($stamp1, 'network'); } /** @@ -573,7 +591,7 @@ class App * * @return string */ - public function get_basepath() + public function getBasePath() { $basepath = $this->basepath; @@ -589,7 +607,7 @@ class App $basepath = $_SERVER['PWD']; } - return self::realpath($basepath); + return self::getRealPath($basepath); } /** @@ -602,7 +620,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); @@ -613,7 +631,7 @@ class App } } - public function get_scheme() + public function getScheme() { return $this->scheme; } @@ -632,7 +650,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; @@ -655,7 +673,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() : '' ); } /** @@ -665,7 +683,7 @@ class App * * @param string $url */ - public function set_baseurl($url) + public function setBaseURL($url) { $parsed = @parse_url($url); $hostname = ''; @@ -686,8 +704,8 @@ class App $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') != '') { @@ -700,7 +718,7 @@ class App } } - public function get_hostname() + public function getHostName() { if (Config::get('config', 'hostname') != '') { $this->hostname = Config::get('config', 'hostname'); @@ -709,23 +727,23 @@ class App return $this->hostname; } - public function get_path() + public function getURLpath() { 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']; @@ -791,7 +809,7 @@ class App * 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?'), @@ -847,41 +865,11 @@ class App $tpl = get_markup_template('footer.tpl'); $this->page['footer'] = replace_macros($tpl, [ - '$baseurl' => $this->get_baseurl(), + '$baseurl' => $this->getBaseURL(), '$footerScripts' => $this->footerScripts, ]) . $this->page['footer']; } - 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; - } - - public function get_curl_content_type() - { - return $this->curl_content_type; - } - - public function set_curl_headers($headers) - { - $this->curl_headers = $headers; - } - - public function get_curl_headers() - { - return $this->curl_headers; - } - /** * @brief Removes the base url from an url. This avoids some mixed content problems. * @@ -889,11 +877,11 @@ class App * * @return string The cleaned url */ - public function remove_baseurl($orig_url) + public function removeBaseURL($orig_url) { // Remove the hostname from the url if it is an internal link $nurl = normalise_link($orig_url); - $base = normalise_link($this->get_baseurl()); + $base = normalise_link($this->getBaseURL()); $url = str_replace($base . '/', '', $nurl); // if it is an external link return the orignal value @@ -909,7 +897,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')) { @@ -929,7 +917,7 @@ class App * * @return object Template Engine instance */ - public function template_engine() + public function getTemplateEngine() { $template_engine = 'smarty3'; if (x($this->theme, 'template_engine')) { @@ -956,33 +944,40 @@ class App * * @return string */ - public function get_template_engine() + public function getActiveTemplateEngine() { return $this->theme['template_engine']; } - public function set_template_engine($engine = 'smarty3') + public function setActiveTemplateEngine($engine = 'smarty3') { $this->theme['template_engine'] = $engine; } - public function get_template_ldelim($engine = 'smarty3') + public function getTemplateLdelim($engine = 'smarty3') { return $this->ldelim[$engine]; } - public function get_template_rdelim($engine = 'smarty3') + public function getTemplateRdelim($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 @@ -1002,19 +997,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; } /** @@ -1023,10 +1040,8 @@ 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? */ - public function is_backend() - { + private function checkBackend($backend) { static $backends = [ '_well_known', 'api', @@ -1050,7 +1065,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) || $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; } /** @@ -1098,7 +1123,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) { @@ -1144,7 +1169,7 @@ class App */ public function isMaxLoadReached() { - if ($this->is_backend()) { + if ($this->isBackend()) { $process = 'backend'; $maxsysload = intval(Config::get('system', 'maxloadavg')); if ($maxsysload < 1) { @@ -1193,14 +1218,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); @@ -1216,7 +1241,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 ''; @@ -1231,7 +1256,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); @@ -1239,22 +1264,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; } @@ -1265,6 +1290,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) { @@ -1347,6 +1374,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) { @@ -1408,7 +1437,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, ':')); } @@ -1422,7 +1451,7 @@ class App /** * Returns the current theme name. * - * @return string + * @return string the name of the current theme */ public function getCurrentTheme() { @@ -1435,7 +1464,7 @@ class App /// https://github.com/friendica/friendica/issues/5092) $this->computeCurrentTheme(); - return $this->current_theme; + return $this->currentTheme; } /** @@ -1451,7 +1480,7 @@ class App } // Sane default - $this->current_theme = $system_theme; + $this->currentTheme = $system_theme; $allowed_themes = explode(',', Config::get('system', 'allowed_themes', $system_theme)); @@ -1490,7 +1519,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; } } diff --git a/src/Content/Nav.php b/src/Content/Nav.php index 99decc92bb..7a1a149a2f 100644 --- a/src/Content/Nav.php +++ b/src/Content/Nav.php @@ -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 { diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index c3453bcf72..66f4190b28 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -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/") { @@ -1946,7 +1946,7 @@ class BBCode extends BaseObject // unmask the special chars back to HTML $text = str_replace(['&\_lt\_;', '&\_gt\_;', '&\_amp\_;'], ['<', '>', '&'], $text); - $a->save_timestamp($stamp1, "parser"); + $a->saveTimestamp($stamp1, "parser"); // Libertree has a problem with escaped hashtags. $text = str_replace(['\#'], ['#'], $text); diff --git a/src/Content/Text/Markdown.php b/src/Content/Text/Markdown.php index 0687b5377b..2289bee869 100644 --- a/src/Content/Text/Markdown.php +++ b/src/Content/Text/Markdown.php @@ -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; } diff --git a/src/Core/Addon.php b/src/Core/Addon.php index d5a7a6f1b4..d2f89ce279 100644 --- a/src/Core/Addon.php +++ b/src/Core/Addon.php @@ -197,7 +197,7 @@ class Addon extends BaseObject */ public static function registerHook($hook, $file, $function, $priority = 0) { - $file = str_replace(self::getApp()->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); @@ -220,7 +220,7 @@ class Addon extends BaseObject */ public static function unregisterHook($hook, $file, $function) { - $relative_file = str_replace(self::getApp()->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]; @@ -368,7 +368,7 @@ class Addon extends BaseObject $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); diff --git a/src/Core/Cache.php b/src/Core/Cache.php index b239af7d60..0fb328aaee 100644 --- a/src/Core/Cache.php +++ b/src/Core/Cache.php @@ -61,7 +61,7 @@ class Cache extends \Friendica\BaseObject $return = self::getDriver()->getAllKeys($prefix); - self::getApp()->save_timestamp($time, 'cache'); + self::getApp()->saveTimestamp($time, 'cache'); return $return; } @@ -79,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; } @@ -101,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; } @@ -119,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; } diff --git a/src/Core/Cache/AbstractCacheDriver.php b/src/Core/Cache/AbstractCacheDriver.php index 1cdecf6ceb..c2628551ef 100644 --- a/src/Core/Cache/AbstractCacheDriver.php +++ b/src/Core/Cache/AbstractCacheDriver.php @@ -20,7 +20,7 @@ abstract class AbstractCacheDriver extends BaseObject 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; } /** @@ -34,7 +34,7 @@ abstract class AbstractCacheDriver extends BaseObject } else { // Keys are prefixed with the node hostname, let's remove it array_walk($keys, function (&$value) { - $value = preg_replace('/^' . self::getApp()->get_hostname() . ':/', '', $value); + $value = preg_replace('/^' . self::getApp()->getHostName() . ':/', '', $value); }); sort($keys); diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index 9b6945ecd4..9cdb8a0ae2 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -84,8 +84,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"); } } diff --git a/src/Core/Console/DocBloxErrorChecker.php b/src/Core/Console/DocBloxErrorChecker.php index b29f8e2baa..421f913bb8 100644 --- a/src/Core/Console/DocBloxErrorChecker.php +++ b/src/Core/Console/DocBloxErrorChecker.php @@ -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 = []; diff --git a/src/Core/Install.php b/src/Core/Install.php index ba3a97ea6c..ba767f3f9b 100644 --- a/src/Core/Install.php +++ b/src/Core/Install.php @@ -86,7 +86,7 @@ class Install extends BaseObject $app = self::getApp(); - $result = file_put_contents($app->basepath . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php', $txt); + $result = file_put_contents($app->getBasePath() . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'local.ini.php', $txt); if (!$result) { $app->data['txt'] = $txt; } diff --git a/src/Core/NotificationsManager.php b/src/Core/NotificationsManager.php index f8c4ee3f86..4f5ccb95a0 100644 --- a/src/Core/NotificationsManager.php +++ b/src/Core/NotificationsManager.php @@ -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', diff --git a/src/Core/System.php b/src/Core/System.php index b41f520d77..cbffcdbef1 100644 --- a/src/Core/System.php +++ b/src/Core/System.php @@ -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); } /** @@ -185,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)) { diff --git a/src/Core/Theme.php b/src/Core/Theme.php index c64ed08d3b..7e5b89d2f9 100644 --- a/src/Core/Theme.php +++ b/src/Core/Theme.php @@ -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); diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 3400f00ae1..870a5dfb24 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -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; diff --git a/src/Database/DBA.php b/src/Database/DBA.php index ab856ef9d0..c33fa2152f 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -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; } diff --git a/src/Database/DBStructure.php b/src/Database/DBStructure.php index d6cd66aafa..0472d753dd 100644 --- a/src/Database/DBStructure.php +++ b/src/Database/DBStructure.php @@ -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/Contact.php b/src/Model/Contact.php index fa6966a0ef..ab427efab9 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1632,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"); diff --git a/src/Model/Item.php b/src/Model/Item.php index f2d4a89815..c0c67352e4 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1166,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 = ''; @@ -2361,7 +2361,7 @@ class Item extends BaseObject $guid = System::createUUID(); } - return self::getApp()->get_baseurl() . '/objects/' . $guid; + return self::getApp()->getBaseURL() . '/objects/' . $guid; } /** @@ -2644,7 +2644,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; } diff --git a/src/Model/Photo.php b/src/Model/Photo.php index 555df80e63..e64158e175 100644 --- a/src/Model/Photo.php +++ b/src/Model/Photo.php @@ -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(); diff --git a/src/Model/Profile.php b/src/Model/Profile.php index cb2754cc80..a1274c1ae4 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -162,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)) { @@ -1116,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); } diff --git a/src/Model/User.php b/src/Model/User.php index 7432b75774..b8b694de87 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -414,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']; diff --git a/src/Module/Login.php b/src/Module/Login.php index 25ddd13502..15505a38be 100644 --- a/src/Module/Login.php +++ b/src/Module/Login.php @@ -39,7 +39,7 @@ class Login extends BaseModule } if (local_user()) { - goaway(self::getApp()->get_baseurl()); + goaway(self::getApp()->getBaseURL()); } return self::form($_SESSION['return_url'], intval(Config::get('config', 'register_policy')) !== REGISTER_CLOSED); @@ -86,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.') . '

    ' . L10n::t('The error message was:') . ' ' . $e->getMessage()); @@ -191,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 @@ -228,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', [], @@ -242,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 @@ -297,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) ] ); @@ -308,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'), diff --git a/src/Module/Logout.php b/src/Module/Logout.php index bfa917a393..cbfd245f30 100644 --- a/src/Module/Logout.php +++ b/src/Module/Logout.php @@ -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()); } } diff --git a/src/Module/Magic.php b/src/Module/Magic.php index 0b4126e0e9..5bf176b251 100644 --- a/src/Module/Magic.php +++ b/src/Module/Magic.php @@ -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; @@ -78,7 +78,7 @@ class Magic extends BaseModule $headers = HTTPSignature::createSig( $headers, $user['prvkey'], - 'acct:' . $user['nickname'] . '@' . $a->get_hostname() . ($a->urlpath ? '/' . $a->urlpath : '') + 'acct:' . $user['nickname'] . '@' . $a->getHostName() . ($a->getURLpath() ? '/' . $a->getURLpath() : '') ); // Try to get an authentication token from the other instance. diff --git a/src/Module/Proxy.php b/src/Module/Proxy.php index 0de45b3325..14e842562f 100644 --- a/src/Module/Proxy.php +++ b/src/Module/Proxy.php @@ -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)) { @@ -196,7 +196,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(Network::getCurl()->getCode(), 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/Curl.php b/src/Network/Curl.php new file mode 100644 index 0000000000..bc04f6b4e4 --- /dev/null +++ b/src/Network/Curl.php @@ -0,0 +1,92 @@ +code = $code; + $this->contentType = $contentType; + $this->headers = $headers; + } + + /** + * Sets the Curl Code + * + * @param string $code The Curl Code + */ + public function setCode($code) + { + $this->code = $code; + } + + /** + * Gets the Curl Code + * + * @return string The Curl Code + */ + public function getCode() + { + return $this->code; + } + + /** + * Sets the Curl Content Type + * + * @param string $content_type The Curl Content Type + */ + public function setContentType($content_type) + { + $this->contentType = $content_type; + } + + /** + * Returns the Curl Content Type + * + * @return string the Curl Content Type + */ + public function getContentType() + { + return $this->contentType; + } + + /** + * Sets the Curl headers + * + * @param string $headers the Curl headers + */ + public function setHeaders($headers) + { + $this->headers = $headers; + } + + /** + * Returns the Curl headers + * + * @return string the Curl headers + */ + public function getHeaders() + { + return $this->headers; + } +} diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 2c84ddb85a..5a03a71f7b 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -74,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); diff --git a/src/Object/Image.php b/src/Object/Image.php index 620929df51..166e150bf5 100644 --- a/src/Object/Image.php +++ b/src/Object/Image.php @@ -655,7 +655,7 @@ class Image $stamp1 = microtime(true); file_put_contents($path, $string); - $a->save_timestamp($stamp1, "file"); + $a->saveTimestamp($stamp1, "file"); } /** @@ -730,7 +730,7 @@ class Image if ($fromcurl) { $a = get_app(); $headers=[]; - $h = explode("\n", $a->get_curl_headers()); + $h = explode("\n", Network::getCurl()->getHeaders()); foreach ($h as $l) { $data = array_map("trim", explode(":", trim($l), 2)); if (count($data) > 1) { @@ -799,7 +799,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 +907,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 +921,7 @@ class Image $stamp1 = microtime(true); file_put_contents($tempfile, $imagedata); - $a->save_timestamp($stamp1, "file"); + $a->saveTimestamp($stamp1, "file"); $data = getimagesize($tempfile); diff --git a/src/Object/Post.php b/src/Object/Post.php index 35805e1fdd..48ffe65b74 100644 --- a/src/Object/Post.php +++ b/src/Object/Post.php @@ -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 : '', @@ -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/DFRN.php b/src/Protocol/DFRN.php index 4d61f9aee0..ff468fb2c1 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -1220,7 +1220,7 @@ class DFRN $xml = $ret['body']; - $curl_stat = $a->get_curl_code(); + $curl_stat = Network::getCurl()->getCode(); if (empty($curl_stat)) { Contact::markForArchival($contact); return -3; // timed out @@ -1372,13 +1372,13 @@ class DFRN logger('dfrn_deliver: ' . "RECEIVED: " . $xml, LOGGER_DATA); - $curl_stat = $a->get_curl_code(); + $curl_stat = Network::getCurl()->getCode(); 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(Network::getCurl()->getHeaders(), 'retry-after')) { Contact::markForArchival($contact); return -10; } @@ -1469,14 +1469,14 @@ class DFRN $xml = Network::post($dest_url, $envelope, ["Content-Type: ".$content_type]); - $curl_stat = $a->get_curl_code(); + $curl_stat = Network::getCurl()->getCode(); 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(Network::getCurl()->getHeaders(), 'retry-after'))) { Contact::markForArchival($contact); return -10; } @@ -2496,7 +2496,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']); diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index b5ecfcefcc..ebdc84ce7f 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -3080,7 +3080,7 @@ class Diaspora $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(); + $return_code = Network::getCurl()->getCode(); } else { logger("test_mode"); return 200; @@ -3089,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(Network::getCurl()->getHeaders(), "retry-after")))) { if (!$no_queue && !empty($contact['contact-type']) && ($contact['contact-type'] != Contact::ACCOUNT_TYPE_RELAY)) { logger("queue message"); // queue message for redelivery diff --git a/src/Protocol/Feed.php b/src/Protocol/Feed.php index 0709a9550e..39b272a422 100644 --- a/src/Protocol/Feed.php +++ b/src/Protocol/Feed.php @@ -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']); diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index d56bacc675..b9090d0e44 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -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']; diff --git a/src/Protocol/PortableContact.php b/src/Protocol/PortableContact.php index 280dbe72c2..a5932e158b 100644 --- a/src/Protocol/PortableContact.php +++ b/src/Protocol/PortableContact.php @@ -90,9 +90,9 @@ class PortableContact logger('load: returns ' . $s, LOGGER_DATA); - logger('load: return code: ' . $a->get_curl_code(), LOGGER_DEBUG); + logger('load: return code: ' . Network::getCurl()->getCode(), LOGGER_DEBUG); - if (($a->get_curl_code() > 299) || (! $s)) { + if ((Network::getCurl()->getCode() > 299) || (! $s)) { return; } diff --git a/src/Protocol/Salmon.php b/src/Protocol/Salmon.php index f30488ce14..b71be6e2fa 100644 --- a/src/Protocol/Salmon.php +++ b/src/Protocol/Salmon.php @@ -139,7 +139,7 @@ class Salmon ]); $a = get_app(); - $return_code = $a->get_curl_code(); + $return_code = Network::getCurl()->getCode(); // check for success, e.g. 2xx @@ -163,7 +163,7 @@ class Salmon 'Content-type: application/magic-envelope+xml', 'Content-length: ' . strlen($salmon) ]); - $return_code = $a->get_curl_code(); + $return_code = Network::getCurl()->getCode(); } if ($return_code > 299) { @@ -185,7 +185,7 @@ class Salmon Network::post($url, $salmon, [ 'Content-type: application/magic-envelope+xml', 'Content-length: ' . strlen($salmon)]); - $return_code = $a->get_curl_code(); + $return_code = Network::getCurl()->getCode(); } logger('slapper for '.$url.' returned ' . $return_code); @@ -194,7 +194,7 @@ class Salmon return -1; } - if (($return_code == 503) && (stristr($a->get_curl_headers(), 'retry-after'))) { + if (($return_code == 503) && (stristr(Network::getCurl()->getHeaders(), 'retry-after'))) { return -1; } diff --git a/src/Render/FriendicaSmarty.php b/src/Render/FriendicaSmarty.php index f4c6a8ed27..559d501ca9 100644 --- a/src/Render/FriendicaSmarty.php +++ b/src/Render/FriendicaSmarty.php @@ -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->getTemplateLdelim('smarty3'); + $this->right_delimiter = $a->getTemplateRdelim('smarty3'); // Don't report errors so verbosely $this->error_reporting = E_ALL & ~E_NOTICE; diff --git a/src/Util/ExAuth.php b/src/Util/ExAuth.php index 92f3f56f85..de5d52d895 100644 --- a/src/Util/ExAuth.php +++ b/src/Util/ExAuth.php @@ -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 { @@ -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]); diff --git a/src/Util/HTTPSignature.php b/src/Util/HTTPSignature.php index 234d896078..494d6e0e65 100644 --- a/src/Util/HTTPSignature.php +++ b/src/Util/HTTPSignature.php @@ -303,7 +303,7 @@ class HTTPSignature $headers[] = 'Content-Type: application/activity+json'; Network::post($target, $content, $headers); - $return_code = BaseObject::getApp()->get_curl_code(); + $return_code = BaseObject::getApp()->getCurlCode(); logger('Transmit to ' . $target . ' returned ' . $return_code); } diff --git a/src/Util/Network.php b/src/Util/Network.php index 0de9661859..ec8b8c9b09 100644 --- a/src/Util/Network.php +++ b/src/Util/Network.php @@ -9,6 +9,8 @@ use Friendica\Core\Addon; use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Core\Config; +use Friendica\Network\Curl; +use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Network\Probe; use Friendica\Object\Image; use Friendica\Util\XML; @@ -17,6 +19,25 @@ use DomXPath; class Network { + /** + * @var Curl The latest Curl output + */ + private static $curl; + + /** + * Returns the latest Curl output + * + * @return Curl The latest Curl output + */ + public static function getCurl() + { + if (empty(self::$curl)) { + self::$curl = new Curl(); + } + + return self::$curl; + } + /** * Curl wrapper * @@ -35,7 +56,7 @@ 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); @@ -59,7 +80,7 @@ class Network * * @return array 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, @@ -145,7 +166,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 +224,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. @@ -242,9 +261,7 @@ class Network $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); + self::$curl = new Curl($http_code, (isset($curl_info['content_type']) ? $curl_info['content_type'] : ''), $header); if ($http_code == 301 || $http_code == 302 || $http_code == 303 || $http_code == 307) { $new_location_info = @parse_url($curl_info['redirect_url']); @@ -277,8 +294,10 @@ class Network } } - $a->set_curl_code($http_code); - $a->set_curl_content_type($curl_info['content_type']); + self::$curl->setCode($http_code); + if (isset($curl_info['content_type'])) { + self::$curl->setContentType($curl_info['content_type']); + } $rc = intval($http_code); $ret['return_code'] = $rc; @@ -301,7 +320,7 @@ class Network @curl_close($ch); - $a->save_timestamp($stamp1, 'network'); + $a->saveTimestamp($stamp1, 'network'); return($ret); } @@ -339,7 +358,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,7 +403,7 @@ class Network } } - $a->set_curl_code(0); + self::getCurl()->setCode(0); // don't let curl abort the entire application // if it throws any errors. @@ -427,15 +446,15 @@ class Network } } - $a->set_curl_code($http_code); + self::getCurl()->setCode($http_code); $body = substr($s, strlen($header)); - $a->set_curl_headers($header); + self::getCurl()->setHeaders($header); curl_close($ch); - $a->save_timestamp($stamp1, 'network'); + $a->saveTimestamp($stamp1, 'network'); logger('post_url: end ' . $url, LOGGER_DATA); @@ -729,14 +748,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 +792,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; diff --git a/src/Util/Proxy.php b/src/Util/Proxy.php index 3473e8d167..0bb7537f78 100644 --- a/src/Util/Proxy.php +++ b/src/Util/Proxy.php @@ -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/Cron.php b/src/Worker/Cron.php index 61077ae734..b6dd896cd7 100644 --- a/src/Worker/Cron.php +++ b/src/Worker/Cron.php @@ -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'); } diff --git a/src/Worker/CronJobs.php b/src/Worker/CronJobs.php index 098bce4d96..bd34449729 100644 --- a/src/Worker/CronJobs.php +++ b/src/Worker/CronJobs.php @@ -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'); diff --git a/src/Worker/Delivery.php b/src/Worker/Delivery.php index 3585b39989..f2951cce1f 100644 --- a/src/Worker/Delivery.php +++ b/src/Worker/Delivery.php @@ -112,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, ':')); } @@ -435,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') . ' get_hostname() . '>' . "\n"; + $headers = 'From: '. Email::encodeHeader($local_user['username'], 'UTF-8') . ' getHostName() . '>' . "\n"; } $headers .= 'Message-Id: <' . Email::iri2msgid($target_item['uri']) . '>' . "\n"; diff --git a/src/Worker/Notifier.php b/src/Worker/Notifier.php index 6bfd2bc3b3..ad33c3245d 100644 --- a/src/Worker/Notifier.php +++ b/src/Worker/Notifier.php @@ -194,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,':')); } diff --git a/src/Worker/OnePoll.php b/src/Worker/OnePoll.php index 01b63e98e0..21e3b44b3e 100644 --- a/src/Worker/OnePoll.php +++ b/src/Worker/OnePoll.php @@ -196,7 +196,7 @@ class OnePoll $handshake_xml = $ret['body']; - $html_code = $a->get_curl_code(); + $html_code = Network::getCurl()->getCode(); logger('handshake with url ' . $url . ' returns xml: ' . $handshake_xml, LOGGER_DATA); @@ -507,7 +507,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; diff --git a/src/Worker/PubSubPublish.php b/src/Worker/PubSubPublish.php index 1e18b4ccfa..07023e8247 100644 --- a/src/Worker/PubSubPublish.php +++ b/src/Worker/PubSubPublish.php @@ -57,7 +57,7 @@ class PubSubPublish logger('POST ' . print_r($headers, true) . "\n" . $params, LOGGER_DATA); Network::post($subscriber['callback_url'], $params, $headers); - $ret = $a->get_curl_code(); + $ret = Network::getCurl()->getCode(); $condition = ['id' => $subscriber['id']]; diff --git a/tests/ApiTest.php b/tests/ApiTest.php index cbc6f7e0b4..11c61f9fbb 100644 --- a/tests/ApiTest.php +++ b/tests/ApiTest.php @@ -75,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']; } /** diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php index 52ca3f68d3..70caba7122 100644 --- a/tests/DatabaseTest.php +++ b/tests/DatabaseTest.php @@ -5,6 +5,7 @@ namespace Friendica\Test; +use Friendica\App; use Friendica\BaseObject; use Friendica\Core\Config; use Friendica\Database\DBA; @@ -18,7 +19,12 @@ use PHPUnit_Extensions_Database_DB_IDatabaseConnection; */ abstract class DatabaseTest extends TestCase { - public function setUp() + /** + * @var App The Friendica App + */ + protected $app; + + protected function setUp() { // Reusable App object $this->app = BaseObject::getApp(); diff --git a/tests/src/Core/Cache/MemoryCacheTest.php b/tests/src/Core/Cache/MemoryCacheTest.php index 0f3f6192b2..b6889a6513 100644 --- a/tests/src/Core/Cache/MemoryCacheTest.php +++ b/tests/src/Core/Cache/MemoryCacheTest.php @@ -11,7 +11,7 @@ abstract class MemoryCacheTest extends CacheTest */ protected $instance; - function setUp() + protected function setUp() { parent::setUp(); if (!($this->instance instanceof IMemoryCacheDriver)) { diff --git a/view/theme/duepuntozero/theme.php b/view/theme/duepuntozero/theme.php index 02882ca943..588a6fa463 100644 --- a/view/theme/duepuntozero/theme.php +++ b/view/theme/duepuntozero/theme.php @@ -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) diff --git a/view/theme/frio/php/default.php b/view/theme/frio/php/default.php index d9ecb7cf0d..bf4aa2df46 100644 --- a/view/theme/frio/php/default.php +++ b/view/theme/frio/php/default.php @@ -26,7 +26,7 @@ if (!isset($minimal)) { 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 diff --git a/view/theme/frio/theme.php b/view/theme/frio/theme.php index 72e5ab0b61..18fb98cc9d 100644 --- a/view/theme/frio/theme.php +++ b/view/theme/frio/theme.php @@ -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())); diff --git a/view/theme/smoothly/theme.php b/view/theme/smoothly/theme.php index 555b65eed3..e961146f6a 100644 --- a/view/theme/smoothly/theme.php +++ b/view/theme/smoothly/theme.php @@ -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; diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php index 2533e50a89..887ef1c129 100644 --- a/view/theme/vier/theme.php +++ b/view/theme/vier/theme.php @@ -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; } From 8cc15fd2a8013086d4af9eeb766e18f9bc2007b6 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 10 Oct 2018 00:20:08 +0200 Subject: [PATCH 331/428] Bugfixing DatabaseTest --- tests/DatabaseTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php index 70caba7122..acd0b7ac18 100644 --- a/tests/DatabaseTest.php +++ b/tests/DatabaseTest.php @@ -19,6 +19,8 @@ use PHPUnit_Extensions_Database_DB_IDatabaseConnection; */ abstract class DatabaseTest extends TestCase { + use TestCaseTrait; + /** * @var App The Friendica App */ From 3eb4332f333a1db00bdbd90aa03396be5d667783 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 10 Oct 2018 01:16:51 +0200 Subject: [PATCH 332/428] Bugfixing Backend --- src/App.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.php b/src/App.php index 293d9d3a56..e947c13ffb 100644 --- a/src/App.php +++ b/src/App.php @@ -1065,7 +1065,7 @@ class App ]; // Check if current module is in backend or backend flag is set - $this->isBackend = (in_array($this->module, $backends) || $this->isBackend); + $this->isBackend = (in_array($this->module, $backends) || $backend || $this->isBackend); } /** From 307286fc475e241f32ebd11bb3ba1d42761995e3 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 10 Oct 2018 01:18:47 +0200 Subject: [PATCH 333/428] parameters and getURLpath to getURLPath --- mod/admin.php | 4 ++-- mod/dfrn_request.php | 6 +++--- mod/hcard.php | 2 +- mod/profile.php | 2 +- mod/redir.php | 2 +- mod/settings.php | 2 +- mod/xrd.php | 4 ++-- src/App.php | 14 +++++++------- src/Core/NotificationsManager.php | 2 +- src/Model/Contact.php | 2 +- src/Module/Magic.php | 2 +- view/theme/frio/php/default.php | 2 +- 12 files changed, 22 insertions(+), 22 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index f186f127ad..bd5e9ecea3 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -1124,7 +1124,7 @@ function admin_page_site_post(App $a) Worker::add(PRIORITY_LOW, 'Directory'); } - if ($a->getURLpath() != "") { + if ($a->getURLPath() != "") { $diaspora_enabled = false; } if ($ssl_policy != intval(Config::get('system', 'ssl_policy'))) { @@ -1421,7 +1421,7 @@ function admin_page_site(App $a) if (empty(Config::get('config', 'hostname'))) { Config::set('config', 'hostname', $a->getHostName()); } - $diaspora_able = ($a->getURLpath() == ""); + $diaspora_able = ($a->getURLPath() == ""); $optimize_max_tablesize = Config::get('system', 'optimize_max_tablesize', -1); diff --git a/mod/dfrn_request.php b/mod/dfrn_request.php index 4971cb8609..e611458281 100644 --- a/mod/dfrn_request.php +++ b/mod/dfrn_request.php @@ -453,8 +453,8 @@ function dfrn_request_post(App $a) if ($network == Protocol::DIASPORA) { $uri = $nickname . '@' . $a->getHostName(); - if ($a->getURLpath()) { - $uri .= '/' . $a->getURLpath(); + 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->getURLpath())) { + if (strlen($a->getURLPath())) { $myaddr = System::baseUrl() . '/profile/' . $a->user['nickname']; } else { $myaddr = $a->user['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3); diff --git a/mod/hcard.php b/mod/hcard.php index 11e5475f43..7e5c2cc08a 100644 --- a/mod/hcard.php +++ b/mod/hcard.php @@ -50,7 +50,7 @@ function hcard_init(App $a) $a->page['htmlhead'] .= '' . "\r\n" ; $a->page['htmlhead'] .= '' . "\r\n" ; - $uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->getHostName() . (($a->getURLpath()) ? '/' . $a->getURLpath() : '')); + $uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->getHostName() . (($a->getURLPath()) ? '/' . $a->getURLPath() : '')); $a->page['htmlhead'] .= '' . "\r\n"; header('Link: <' . System::baseUrl() . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false); diff --git a/mod/profile.php b/mod/profile.php index c57f403930..aa284d1669 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -91,7 +91,7 @@ function profile_init(App $a) $a->page['htmlhead'] .= '' . "\r\n"; $a->page['htmlhead'] .= '' . "\r\n"; $a->page['htmlhead'] .= '' . "\r\n"; - $uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->getHostName() . ($a->getURLpath() ? '/' . $a->getURLpath() : '')); + $uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->getHostName() . ($a->getURLPath() ? '/' . $a->getURLPath() : '')); $a->page['htmlhead'] .= '' . "\r\n"; header('Link: <' . System::baseUrl() . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false); diff --git a/mod/redir.php b/mod/redir.php index b9a24210b6..e989ad015a 100644 --- a/mod/redir.php +++ b/mod/redir.php @@ -57,7 +57,7 @@ function redir_init(App $a) { } if (remote_user()) { - $host = substr(System::baseUrl() . ($a->getURLpath() ? '/' . $a->getURLpath() : ''), 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 diff --git a/mod/settings.php b/mod/settings.php index 3a6c8c3fab..5632193e3b 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -1136,7 +1136,7 @@ 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 '%s' or '%s'.", $nickname . '@' . $a->getHostName() . $a->getURLpath(), System::baseUrl() . '/profile/' . $nickname), + '$desc' => L10n::t("Your Identity Address is '%s' or '%s'.", $nickname . '@' . $a->getHostName() . $a->getURLPath(), System::baseUrl() . '/profile/' . $nickname), '$basepath' => $a->getHostName() ]); diff --git a/mod/xrd.php b/mod/xrd.php index 801fa9d91b..2626b0c791 100644 --- a/mod/xrd.php +++ b/mod/xrd.php @@ -56,8 +56,8 @@ function xrd_init(App $a) $alias = str_replace('/profile/', '/~', $profile_url); $addr = 'acct:'.$user['nickname'].'@'.$a->getHostName(); - if ($a->getURLpath()) { - $addr .= '/'.$a->getURLpath(); + if ($a->getURLPath()) { + $addr .= '/'.$a->getURLPath(); } if ($mode == 'xml') { diff --git a/src/App.php b/src/App.php index e947c13ffb..e94067a08f 100644 --- a/src/App.php +++ b/src/App.php @@ -673,7 +673,7 @@ class App $this->hostname = Config::get('config', 'hostname'); } - return $scheme . '://' . $this->hostname . (!empty($this->getURLpath()) ? '/' . $this->getURLpath() : '' ); + return $scheme . '://' . $this->hostname . (!empty($this->getURLPath()) ? '/' . $this->getURLPath() : '' ); } /** @@ -727,7 +727,7 @@ class App return $this->hostname; } - public function getURLpath() + public function getURLPath() { return $this->urlpath; } @@ -873,20 +873,20 @@ class App /** * @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 removeBaseURL($orig_url) + public function removeBaseURL($origURL) { // Remove the hostname from the url if it is an internal link - $nurl = normalise_link($orig_url); + $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; } diff --git a/src/Core/NotificationsManager.php b/src/Core/NotificationsManager.php index 4f5ccb95a0..fb77605730 100644 --- a/src/Core/NotificationsManager.php +++ b/src/Core/NotificationsManager.php @@ -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()->getHostName() . ((self::getApp()->getURLpath()) ? '/' . self::getApp()->getURLpath() : '')); + $return_addr = bin2hex(self::getApp()->user['nickname'] . '@' . self::getApp()->getHostName() . ((self::getApp()->getURLPath()) ? '/' . self::getApp()->getURLPath() : '')); $intro = [ 'label' => 'friend_suggestion', diff --git a/src/Model/Contact.php b/src/Model/Contact.php index ab427efab9..23c31d0b17 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1632,7 +1632,7 @@ class Contact extends BaseObject if (($ret['network'] === Protocol::DFRN) && !DBA::isResult($contact)) { if ($interactive) { - if (strlen($a->getURLpath())) { + if (strlen($a->getURLPath())) { $myaddr = bin2hex(System::baseUrl() . '/profile/' . $a->user['nickname']); } else { $myaddr = bin2hex($a->user['nickname'] . '@' . $a->getHostName()); diff --git a/src/Module/Magic.php b/src/Module/Magic.php index 5bf176b251..042a9581df 100644 --- a/src/Module/Magic.php +++ b/src/Module/Magic.php @@ -78,7 +78,7 @@ class Magic extends BaseModule $headers = HTTPSignature::createSig( $headers, $user['prvkey'], - 'acct:' . $user['nickname'] . '@' . $a->getHostName() . ($a->getURLpath() ? '/' . $a->getURLpath() : '') + 'acct:' . $user['nickname'] . '@' . $a->getHostName() . ($a->getURLPath() ? '/' . $a->getURLPath() : '') ); // Try to get an authentication token from the other instance. diff --git a/view/theme/frio/php/default.php b/view/theme/frio/php/default.php index bf4aa2df46..aa86c97238 100644 --- a/view/theme/frio/php/default.php +++ b/view/theme/frio/php/default.php @@ -26,7 +26,7 @@ if (!isset($minimal)) { getURLpath() ? "/" . $a->getURLpath() . "/" : "/"; + $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 From 3d04562c87140a5d026e8405b6d1213b181ffc0d Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 10 Oct 2018 08:54:18 +0200 Subject: [PATCH 334/428] some more renamings & doku --- src/App.php | 65 ++++++++++++++++++++++++---------- src/Render/FriendicaSmarty.php | 4 +-- src/Util/Network.php | 6 ---- 3 files changed, 49 insertions(+), 26 deletions(-) diff --git a/src/App.php b/src/App.php index e94067a08f..fcde77846e 100644 --- a/src/App.php +++ b/src/App.php @@ -88,12 +88,12 @@ class App /** * @var string The App basepath */ - private $basepath; + private $basePath; /** * @var string The App URL path */ - private $urlpath; + private $urlPath; /** * @var bool true, if the call is from the Friendica APP, otherwise false @@ -182,20 +182,20 @@ class App /** * @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, $backend = true) + public function __construct($basePath, $backend = true) { - if (!static::isDirectoryUsable($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(); @@ -220,7 +220,7 @@ class App $this->callstack['rendering'] = []; $this->callstack['parser'] = []; - $this->mode = new App\Mode($basepath); + $this->mode = new App\Mode($basePath); $this->reload(); @@ -450,7 +450,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 */ @@ -522,7 +522,7 @@ class App */ private function determineURLPath() { - $this->urlpath = $this->getConfigValue('system', 'urlpath'); + $this->urlPath = $this->getConfigValue('system', 'urlpath'); /* SCRIPT_URL gives /path/to/friendica/module/parameter * QUERY_STRING gives pagename=module/parameter @@ -538,8 +538,8 @@ class App $path = trim($_SERVER['SCRIPT_URL'], '/'); } - if ($path && $path != $this->urlpath) { - $this->urlpath = $path; + if ($path && $path != $this->urlPath) { + $this->urlPath = $path; } } } @@ -593,7 +593,7 @@ class App */ public function getBasePath() { - $basepath = $this->basepath; + $basepath = $this->basePath; if (!$basepath) { $basepath = Config::get('system', 'basepath'); @@ -701,7 +701,7 @@ class App $hostname .= ':' . $parsed['port']; } if (x($parsed, 'path')) { - $this->urlpath = trim($parsed['path'], '\\/'); + $this->urlPath = trim($parsed['path'], '\\/'); } if (file_exists($this->getBasePath() . DIRECTORY_SEPARATOR . '.htpreconfig.php')) { @@ -729,7 +729,7 @@ class App public function getURLPath() { - return $this->urlpath; + return $this->urlPath; } public function setPagerTotal($n) @@ -942,24 +942,51 @@ class App /** * @brief Returns the active template engine. * - * @return string + * @return string the active template engine */ public function getActiveTemplateEngine() { return $this->theme['template_engine']; } + /** + * 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 getTemplateLdelim($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 getTemplateRdelim($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]; } @@ -1040,6 +1067,8 @@ class App * This isn't a perfect solution. But we need this check very early. * So we cannot wait until the modules are loaded. * + * @param string $backend true, if the backend flag was set during App initialization + * */ private function checkBackend($backend) { static $backends = [ diff --git a/src/Render/FriendicaSmarty.php b/src/Render/FriendicaSmarty.php index 559d501ca9..2052aa9e87 100644 --- a/src/Render/FriendicaSmarty.php +++ b/src/Render/FriendicaSmarty.php @@ -38,8 +38,8 @@ class FriendicaSmarty extends Smarty $this->setConfigDir('view/smarty3/config/'); $this->setCacheDir('view/smarty3/cache/'); - $this->left_delimiter = $a->getTemplateLdelim('smarty3'); - $this->right_delimiter = $a->getTemplateRdelim('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; diff --git a/src/Util/Network.php b/src/Util/Network.php index ec8b8c9b09..163be21d3a 100644 --- a/src/Util/Network.php +++ b/src/Util/Network.php @@ -4,16 +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\Curl; -use Friendica\Network\HTTPException\InternalServerErrorException; -use Friendica\Network\Probe; -use Friendica\Object\Image; -use Friendica\Util\XML; use DOMDocument; use DomXPath; From 97dc4bba1a89778fd4f6a5d8522abf3866105d4a Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 10 Oct 2018 09:16:06 +0200 Subject: [PATCH 335/428] some more renamings & doku --- src/App.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.php b/src/App.php index fcde77846e..9bfb10f7ce 100644 --- a/src/App.php +++ b/src/App.php @@ -86,7 +86,7 @@ class App private $mode; /** - * @var string The App basepath + * @var string The App base path */ private $basePath; From e6b1f9ef090c77ab76a9ced1f0126a1f3e8aefaf Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 10 Oct 2018 18:10:38 +0200 Subject: [PATCH 336/428] friendica-5875 Uncaught Error: Call to undefined method Friendica\App::getCurlCode() fixed --- src/Util/HTTPSignature.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Util/HTTPSignature.php b/src/Util/HTTPSignature.php index 494d6e0e65..247e554f00 100644 --- a/src/Util/HTTPSignature.php +++ b/src/Util/HTTPSignature.php @@ -303,7 +303,7 @@ class HTTPSignature $headers[] = 'Content-Type: application/activity+json'; Network::post($target, $content, $headers); - $return_code = BaseObject::getApp()->getCurlCode(); + $return_code = Network::getCurl()->getCode(); logger('Transmit to ' . $target . ' returned ' . $return_code); } From 2dec8895a99070281c2a13991b484c96c6e0cbed Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 10 Oct 2018 21:08:43 +0200 Subject: [PATCH 337/428] Curl Response Refactoring - extended Curl to parse Curl Response - refactored Network::curl() - replaced every Network::curl() execution with the new Curl container --- mod/admin.php | 3 +- mod/feedtest.php | 3 +- mod/ostatus_subscribe.php | 10 +- mod/parse_url.php | 6 +- src/Core/ACL.php | 6 +- src/Model/APContact.php | 6 +- src/Model/GContact.php | 6 +- src/Model/Profile.php | 2 +- src/Module/Magic.php | 6 +- src/Network/Curl.php | 280 +++++++++++++++++++++++++++---- src/Network/Probe.php | 50 +++--- src/Protocol/ActivityPub.php | 6 +- src/Protocol/DFRN.php | 24 +-- src/Protocol/OStatus.php | 56 +++---- src/Protocol/PortableContact.php | 166 +++++++++--------- src/Util/ExAuth.php | 8 +- src/Util/Network.php | 177 +++---------------- src/Util/ParseUrl.php | 12 +- src/Worker/DiscoverPoCo.php | 6 +- src/Worker/OnePoll.php | 15 +- 20 files changed, 466 insertions(+), 382 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index bd5e9ecea3..372210c403 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -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(); } diff --git a/mod/feedtest.php b/mod/feedtest.php index d9a9abb91f..e75e7a1b8e 100644 --- a/mod/feedtest.php +++ b/mod/feedtest.php @@ -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); diff --git a/mod/ostatus_subscribe.php b/mod/ostatus_subscribe.php index ffaa6791f3..7012ecd4bc 100644 --- a/mod/ostatus_subscribe.php +++ b/mod/ostatus_subscribe.php @@ -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 .= "

    ".$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"); diff --git a/mod/parse_url.php b/mod/parse_url.php index ebe34875b7..40eddc3bdd 100644 --- a/mod/parse_url.php +++ b/mod/parse_url.php @@ -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) { diff --git a/src/Core/ACL.php b/src/Core/ACL.php index 0b48895d65..8f630409ff 100644 --- a/src/Core/ACL.php +++ b/src/Core/ACL.php @@ -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']; } diff --git a/src/Model/APContact.php b/src/Model/APContact.php index ce66ec4c6e..4593e0377b 100644 --- a/src/Model/APContact.php +++ b/src/Model/APContact.php @@ -33,12 +33,12 @@ class APContact extends BaseObject $webfinger = 'https://' . $addr_parts[1] . '/.well-known/webfinger?resource=acct:' . urlencode($addr); - $ret = Network::curl($webfinger, false, $redirects, ['accept_content' => 'application/jrd+json,application/json']); - if (!$ret['success'] || empty($ret['body'])) { + $curlResult = Network::curl($webfinger, false, $redirects, ['accept_content' => 'application/jrd+json,application/json']); + if (!$curlResult->isSuccess() || empty($curlResult->getBody())) { return false; } - $data = json_decode($ret['body'], true); + $data = json_decode($curlResult->getBody(), true); if (empty($data['links'])) { return false; diff --git a/src/Model/GContact.php b/src/Model/GContact.php index f979abef52..26cb11175c 100644 --- a/src/Model/GContact.php +++ b/src/Model/GContact.php @@ -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) { diff --git a/src/Model/Profile.php b/src/Model/Profile.php index a1274c1ae4..28736750bd 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -1056,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); } } diff --git a/src/Module/Magic.php b/src/Module/Magic.php index 042a9581df..768fe69ebb 100644 --- a/src/Module/Magic.php +++ b/src/Module/Magic.php @@ -82,10 +82,10 @@ class Magic extends BaseModule ); // 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/Network/Curl.php b/src/Network/Curl.php index bc04f6b4e4..f67104bc0d 100644 --- a/src/Network/Curl.php +++ b/src/Network/Curl.php @@ -3,15 +3,17 @@ namespace Friendica\Network; +use Friendica\Network\HTTPException\InternalServerErrorException; + /** * A content class for Curl call results */ class Curl { /** - * @var string the Code of the Curl call + * @var int HTTP return code or 0 if timeout or failure */ - private $code; + private $returnCode; /** * @var string the content type of the Curl call @@ -19,25 +21,179 @@ class Curl private $contentType; /** - * @var string the headers of the Curl call + * @var string the HTTP headers of the Curl call */ - private $headers; + private $header; - public function __construct($code = '', $contentType = '', $headers = '') + /** + * @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 optional error numer + */ + private $errorNumber; + + /** + * @var string optional error message + */ + private $error; + + /** + * Creates an errored CURL response + * + * @param string $url optional URL + * + * @return Curl a CURL with error response + */ + public static function createErrorCurl($url = '') { - $this->code = $code; - $this->contentType = $contentType; - $this->headers = $headers; + return new Curl( + $url, + '', + ['http_code' => 0] + ); } /** - * Sets the Curl Code + * 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 * - * @param string $code The Curl Code + * @throws InternalServerErrorException when HTTP code of the CURL response is missing */ - public function setCode($code) + public function __construct($url, $result, $info, $errorNumber = 0, $error = '') { - $this->code = $code; + if (empty($info['http_code'])) { + 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\/[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)); + } + + $this->body = substr($result, strlen($header)); + $this->header = $header; + } + + private function checkSuccess() + { + $this->isSuccess = ((($this->returnCode >= 200 && $this->returnCode <= 299) || !empty($this->errorNumber)) ? true : false); + + if (!$this->isSuccess) { + logger('error: ' . $this->url . ': ' . $this->returnCode . ' - ' . $this->error, LOGGER_DEBUG); + 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 (empty($this->info['url'])) { + $this->redirectUrl = ''; + } else { + $this->redirectUrl = $this->info['url']; + } + + if ($this->returnCode == 301 || $this->returnCode == 302 || $this->returnCode == 303 || $this->returnCode== 307) { + $new_location_info = (empty($this->info['redirect_url']) ? '' : @parse_url($this->info['redirect_url'])); + $old_location_info = (empty($this->info['url'] ? '' : @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); + } else { + $this->isRedirectUrl = false; + } + } + + private function checkInfo() + { + if (isset($this->info['content_type'])) { + $this->contentType = $this->info['content_type']; + } else { + $this->contentType = ''; + } } /** @@ -45,19 +201,9 @@ class Curl * * @return string The Curl Code */ - public function getCode() + public function getReturnCode() { - return $this->code; - } - - /** - * Sets the Curl Content Type - * - * @param string $content_type The Curl Content Type - */ - public function setContentType($content_type) - { - $this->contentType = $content_type; + return $this->returnCode; } /** @@ -70,23 +216,85 @@ class Curl return $this->contentType; } - /** - * Sets the Curl headers - * - * @param string $headers the Curl headers - */ - public function setHeaders($headers) - { - $this->headers = $headers; - } - /** * Returns the Curl headers * * @return string the Curl headers */ - public function getHeaders() + public function getHeader() { - return $this->headers; + 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; } } diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 5a03a71f7b..7f80be4e47 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -112,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; } @@ -742,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)) { @@ -809,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; @@ -1054,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; } @@ -1301,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); @@ -1333,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 (!empty($curlResult["errno"]) && ($curlResult['errno'] == CURLE_OPERATION_TIMEDOUT)) { return false; } - $feed = $ret['body']; + $feed = $curlResult['body']; $dummy1 = null; $dummy2 = null; $dummy2 = null; @@ -1543,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); diff --git a/src/Protocol/ActivityPub.php b/src/Protocol/ActivityPub.php index b4668e9154..0af8ee5e35 100644 --- a/src/Protocol/ActivityPub.php +++ b/src/Protocol/ActivityPub.php @@ -58,12 +58,12 @@ class ActivityPub */ public static function fetchContent($url) { - $ret = Network::curl($url, false, $redirects, ['accept_content' => 'application/activity+json, application/ld+json']); - if (!$ret['success'] || empty($ret['body'])) { + $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($ret['body'], true); + return json_decode($curlResult->getBody(), true); } /** diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index ff468fb2c1..3a001de049 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -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 = Network::getCurl()->getCode(); + $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 = Network::getCurl()->getCode(); + $curl_stat = $postResult->getReturnCode(); if (empty($curl_stat) || empty($xml)) { Contact::markForArchival($contact); return -9; // timed out } - if (($curl_stat == 503) && stristr(Network::getCurl()->getHeaders(), 'retry-after')) { + if (($curl_stat == 503) && stristr($postResult->getHeader(), 'retry-after')) { Contact::markForArchival($contact); return -10; } diff --git a/src/Protocol/OStatus.php b/src/Protocol/OStatus.php index b9090d0e44..f589d3827f 100644 --- a/src/Protocol/OStatus.php +++ b/src/Protocol/OStatus.php @@ -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(); } } diff --git a/src/Protocol/PortableContact.php b/src/Protocol/PortableContact.php index a5932e158b..8ce732bfcc 100644 --- a/src/Protocol/PortableContact.php +++ b/src/Protocol/PortableContact.php @@ -290,8 +290,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 ""; } @@ -370,10 +370,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 +484,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 +496,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 +645,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 +698,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 +782,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 +997,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 +1051,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 +1083,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 +1097,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 +1125,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 +1176,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 +1213,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 +1286,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 +1350,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 +1442,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 +1538,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 +1575,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 +1594,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 +1613,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 +1643,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 +1666,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 +1766,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); diff --git a/src/Util/ExAuth.php b/src/Util/ExAuth.php index de5d52d895..8d38b33661 100644 --- a/src/Util/ExAuth.php +++ b/src/Util/ExAuth.php @@ -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; } diff --git a/src/Util/Network.php b/src/Util/Network.php index 163be21d3a..f8e4ee9e5b 100644 --- a/src/Util/Network.php +++ b/src/Util/Network.php @@ -13,25 +13,6 @@ use DomXPath; class Network { - /** - * @var Curl The latest Curl output - */ - private static $curl; - - /** - * Returns the latest Curl output - * - * @return Curl The latest Curl output - */ - public static function getCurl() - { - if (empty(self::$curl)) { - self::$curl = new Curl(); - } - - return self::$curl; - } - /** * Curl wrapper * @@ -54,7 +35,7 @@ class Network { $ret = self::fetchUrlFull($url, $binary, $redirects, $timeout, $accept_content, $cookiejar); - return $ret['body']; + return $ret->getBody(); } /** @@ -72,7 +53,7 @@ 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 Curl 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 = '') { @@ -102,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 Curl */ public static function curl($url, $binary = false, &$redirects = 0, $opts = []) { @@ -120,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 Curl::createErrorCurl($url); } $ch = @curl_init($url); if (($redirects > 8) || (!$ch)) { - return $ret; + return Curl::createErrorCurl($url); } @curl_setopt($ch, CURLOPT_HEADER, true); @@ -236,87 +212,20 @@ class Network logger('error fetching ' . $url . ': ' . curl_error($ch), LOGGER_INFO); } - $ret['errno'] = curl_errno($ch); + $curlResponse = new Curl($url, $s, $curl_info, curl_errno($ch), curl_error($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)); - } - - self::$curl = new Curl($http_code, (isset($curl_info['content_type']) ? $curl_info['content_type'] : ''), $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); - } - } - - self::$curl->setCode($http_code); - if (isset($curl_info['content_type'])) { - self::$curl->setContentType($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; - - 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->saveTimestamp($stamp1, 'network'); - return($ret); + return $curlResponse; } /** @@ -328,7 +237,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 Curl The content */ public static function post($url, $params, $headers = null, &$redirects = 0, $timeout = 0) { @@ -336,14 +245,14 @@ class Network if (self::isUrlBlocked($url)) { logger('post_url: domain of ' . $url . ' is blocked', LOGGER_DATA); - return false; + return Curl::createErrorCurl($url); } $a = get_app(); $ch = curl_init($url); if (($redirects > 8) || (!$ch)) { - return false; + return Curl::createErrorCurl($url); } logger('post_url: start ' . $url, LOGGER_DATA); @@ -397,8 +306,6 @@ class Network } } - self::getCurl()->setCode(0); - // don't let curl abort the entire application // if it throws any errors. @@ -406,53 +313,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 Curl($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 ($curlResponse->isRedirectUrl()) { + $redirects++; + logger('post_url: redirect ' . $url . ' to ' . $curlResponse->getRedirectUrl()); + curl_close($ch); + return self::post($curlResponse->getRedirectUrl(), $params, $headers, $redirects, $timeout); } - 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); - } - } - - self::getCurl()->setCode($http_code); - - $body = substr($s, strlen($header)); - - self::getCurl()->setHeaders($header); - curl_close($ch); $a->saveTimestamp($stamp1, 'network'); logger('post_url: end ' . $url, LOGGER_DATA); - return $body; + return $curlResponse; } /** diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index 00eac13902..f2a5eccd39 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -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); diff --git a/src/Worker/DiscoverPoCo.php b/src/Worker/DiscoverPoCo.php index e6fc8391ff..497684497f 100644 --- a/src/Worker/DiscoverPoCo.php +++ b/src/Worker/DiscoverPoCo.php @@ -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; diff --git a/src/Worker/OnePoll.php b/src/Worker/OnePoll.php index 21e3b44b3e..ab8a305494 100644 --- a/src/Worker/OnePoll.php +++ b/src/Worker/OnePoll.php @@ -185,18 +185,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 = Network::getCurl()->getCode(); + $handshake_xml = $curlResult->getBody(); + $html_code = $curlResult->getReturnCode(); logger('handshake with url ' . $url . ' returns xml: ' . $handshake_xml, LOGGER_DATA); @@ -319,17 +318,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); From c4da138eee992d0380b8b1791e641116d86c3f8b Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 10 Oct 2018 19:15:16 +0000 Subject: [PATCH 338/428] Issue 5859: Avoid returning empty arrays --- src/Util/JsonLD.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Util/JsonLD.php b/src/Util/JsonLD.php index a581892939..cf23276d75 100644 --- a/src/Util/JsonLD.php +++ b/src/Util/JsonLD.php @@ -128,7 +128,7 @@ class JsonLD $elements[] = $entry; } elseif (!empty($entry[$key])) { $elements[] = $entry[$key]; - } else { + } elseif (!empty($entry) || !is_array($entry)) { $elements[] = $entry; } } From 7c73e8634c954cc2bd0d1138729459d7d5090f62 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 10 Oct 2018 21:15:26 +0200 Subject: [PATCH 339/428] Curl Response Refactoring - refactored Network::post() - replaced every Network::post() execution with the new Curl container --- include/items.php | 4 ++-- mod/dfrn_confirm.php | 2 +- mod/dfrn_poll.php | 2 +- mod/match.php | 4 ++-- src/Protocol/DFRN.php | 7 ++++--- src/Protocol/Diaspora.php | 6 +++--- src/Protocol/Salmon.php | 13 ++++++------- src/Util/HTTPSignature.php | 5 ++--- src/Worker/OnePoll.php | 2 +- src/Worker/PubSubPublish.php | 4 ++-- 10 files changed, 24 insertions(+), 25 deletions(-) diff --git a/include/items.php b/include/items.php index 236e63dd25..27a7db767b 100644 --- a/include/items.php +++ b/include/items.php @@ -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: ' . Network::getCurl()->getCode(), LOGGER_DEBUG); + logger('subscribe_to_hub: returns: ' . $postResult->getReturnCode(), LOGGER_DEBUG); return; diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php index d3fa45d361..969e2286c8 100644 --- a/mod/dfrn_confirm.php +++ b/mod/dfrn_confirm.php @@ -221,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); diff --git a/mod/dfrn_poll.php b/mod/dfrn_poll.php index 54539ee03d..af597d76ff 100644 --- a/mod/dfrn_poll.php +++ b/mod/dfrn_poll.php @@ -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); diff --git a/mod/match.php b/mod/match.php index bb1e4542ae..7e805d5baf 100644 --- a/mod/match.php +++ b/mod/match.php @@ -59,9 +59,9 @@ 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); diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index 3a001de049..f92d1401df 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -1469,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 = Network::getCurl()->getCode(); + $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(Network::getCurl()->getHeaders(), 'retry-after'))) { + if (($curl_stat == 503) && (stristr($postResult->getHeader(), 'retry-after'))) { Contact::markForArchival($contact); return -10; } diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index ebdc84ce7f..d3cda6c2da 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -3079,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 = Network::getCurl()->getCode(); + $postResult = Network::post($dest_url."/", $envelope, ["Content-Type: ".$content_type]); + $return_code = $postResult->getReturnCode(); } else { logger("test_mode"); return 200; @@ -3089,7 +3089,7 @@ class Diaspora logger("transmit: ".$logid."-".$guid." to ".$dest_url." returns: ".$return_code); - if (!$return_code || (($return_code == 503) && (stristr(Network::getCurl()->getHeaders(), "retry-after")))) { + if (!$return_code || (($return_code == 503) && (stristr($postResult->getHeaders(), "retry-after")))) { if (!$no_queue && !empty($contact['contact-type']) && ($contact['contact-type'] != Contact::ACCOUNT_TYPE_RELAY)) { logger("queue message"); // queue message for redelivery diff --git a/src/Protocol/Salmon.php b/src/Protocol/Salmon.php index b71be6e2fa..02d08c3d4e 100644 --- a/src/Protocol/Salmon.php +++ b/src/Protocol/Salmon.php @@ -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 = Network::getCurl()->getCode(); + $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 = Network::getCurl()->getCode(); + $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 = Network::getCurl()->getCode(); + $return_code = $postResult->getReturnCode(); } logger('slapper for '.$url.' returned ' . $return_code); diff --git a/src/Util/HTTPSignature.php b/src/Util/HTTPSignature.php index 247e554f00..503cbff0ad 100644 --- a/src/Util/HTTPSignature.php +++ b/src/Util/HTTPSignature.php @@ -302,10 +302,9 @@ class HTTPSignature $headers[] = 'Content-Type: application/activity+json'; - Network::post($target, $content, $headers); - $return_code = Network::getCurl()->getCode(); + $postResult = Network::post($target, $content, $headers); - logger('Transmit to ' . $target . ' returned ' . $return_code); + logger('Transmit to ' . $target . ' returned ' . $postResult->getReturnCode()); } /** diff --git a/src/Worker/OnePoll.php b/src/Worker/OnePoll.php index ab8a305494..a68ad1336d 100644 --- a/src/Worker/OnePoll.php +++ b/src/Worker/OnePoll.php @@ -287,7 +287,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) diff --git a/src/Worker/PubSubPublish.php b/src/Worker/PubSubPublish.php index 07023e8247..38d9c07868 100644 --- a/src/Worker/PubSubPublish.php +++ b/src/Worker/PubSubPublish.php @@ -56,8 +56,8 @@ class PubSubPublish logger('POST ' . print_r($headers, true) . "\n" . $params, LOGGER_DATA); - Network::post($subscriber['callback_url'], $params, $headers); - $ret = Network::getCurl()->getCode(); + $postResult = Network::post($subscriber['callback_url'], $params, $headers); + $ret = $postResult->getReturnCode(); $condition = ['id' => $subscriber['id']]; From ffbc6887977c34072e2a3043486a1b0e768a9844 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 10 Oct 2018 21:20:30 +0200 Subject: [PATCH 340/428] Curl Response Refactoring - refactored Network::getCurl() - replaced every Network::getCur() execution with a Curl Response --- mod/pubsubhubbub.php | 5 +++-- src/Core/Install.php | 12 ++++++------ src/Module/Proxy.php | 5 +++-- src/Network/Curl.php | 18 +++++++++--------- src/Object/Image.php | 5 +++-- src/Protocol/Diaspora.php | 2 +- src/Protocol/PortableContact.php | 7 ++++--- src/Protocol/Salmon.php | 2 +- src/Util/Network.php | 4 ---- 9 files changed, 30 insertions(+), 30 deletions(-) diff --git a/mod/pubsubhubbub.php b/mod/pubsubhubbub.php index 5697be8305..d7b204e89c 100644 --- a/mod/pubsubhubbub.php +++ b/mod/pubsubhubbub.php @@ -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 = Network::getCurl()->getCode(); + $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) { diff --git a/src/Core/Install.php b/src/Core/Install.php index ba767f3f9b..3ba683a56f 100644 --- a/src/Core/Install.php +++ b/src/Core/Install.php @@ -345,20 +345,20 @@ class Install extends BaseObject $help = ""; $error_msg = ""; if (function_exists('curl_init')) { - $test = Network::fetchUrlFull(System::baseUrl() . "/install/testrewrite"); + $fetchResult = Network::fetchUrlFull(System::baseUrl() . "/install/testrewrite"); $url = normalise_link(System::baseUrl() . "/install/testrewrite"); - if ($test['body'] != "ok") { - $test = Network::fetchUrlFull($url); + 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); } else { diff --git a/src/Module/Proxy.php b/src/Module/Proxy.php index 14e842562f..776dcccb35 100644 --- a/src/Module/Proxy.php +++ b/src/Module/Proxy.php @@ -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(Network::getCurl()->getCode(), 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/Curl.php b/src/Network/Curl.php index f67104bc0d..7cab25ee87 100644 --- a/src/Network/Curl.php +++ b/src/Network/Curl.php @@ -61,12 +61,12 @@ class Curl private $isTimeout; /** - * @var int optional error numer + * @var int the error number or 0 (zero) if no error */ private $errorNumber; /** - * @var string optional error message + * @var string the error message or '' (the empty string) if no */ private $error; @@ -82,7 +82,7 @@ class Curl return new Curl( $url, '', - ['http_code' => 0] + [ 'http_code' => 0 ] ); } @@ -98,7 +98,7 @@ class Curl */ public function __construct($url, $result, $info, $errorNumber = 0, $error = '') { - if (empty($info['http_code'])) { + if (!array_key_exists('http_code', $info)) { throw new InternalServerErrorException('CURL response doesn\'t contains a response HTTP code'); } @@ -135,10 +135,10 @@ class Curl private function checkSuccess() { - $this->isSuccess = ((($this->returnCode >= 200 && $this->returnCode <= 299) || !empty($this->errorNumber)) ? true : false); + $this->isSuccess = ($this->returnCode >= 200 && $this->returnCode <= 299) || $this->errorNumber == 0; if (!$this->isSuccess) { - logger('error: ' . $this->url . ': ' . $this->returnCode . ' - ' . $this->error, LOGGER_DEBUG); + logger('error: ' . $this->url . ': ' . $this->returnCode . ' - ' . $this->error, LOGGER_INFO); logger('debug: ' . print_r($this->info, true), LOGGER_DATA); } @@ -151,15 +151,15 @@ class Curl private function checkRedirect() { - if (empty($this->info['url'])) { + 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 = (empty($this->info['redirect_url']) ? '' : @parse_url($this->info['redirect_url'])); - $old_location_info = (empty($this->info['url'] ? '' : @parse_url($this->info['url'])); + $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; diff --git a/src/Object/Image.php b/src/Object/Image.php index 166e150bf5..a76599223d 100644 --- a/src/Object/Image.php +++ b/src/Object/Image.php @@ -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", Network::getCurl()->getHeaders()); + $h = explode("\n", $header); foreach ($h as $l) { $data = array_map("trim", explode(":", trim($l), 2)); if (count($data) > 1) { diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index d3cda6c2da..eb52c05037 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -3089,7 +3089,7 @@ class Diaspora logger("transmit: ".$logid."-".$guid." to ".$dest_url." returns: ".$return_code); - if (!$return_code || (($return_code == 503) && (stristr($postResult->getHeaders(), "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 diff --git a/src/Protocol/PortableContact.php b/src/Protocol/PortableContact.php index 8ce732bfcc..0e4d58d1c1 100644 --- a/src/Protocol/PortableContact.php +++ b/src/Protocol/PortableContact.php @@ -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: ' . Network::getCurl()->getCode(), LOGGER_DEBUG); + logger('load: return code: ' . $fetchresult->getReturnCode(), LOGGER_DEBUG); - if ((Network::getCurl()->getCode() > 299) || (! $s)) { + if (($fetchresult->getReturnCode() > 299) || (! $s)) { return; } diff --git a/src/Protocol/Salmon.php b/src/Protocol/Salmon.php index 02d08c3d4e..e3407844a6 100644 --- a/src/Protocol/Salmon.php +++ b/src/Protocol/Salmon.php @@ -193,7 +193,7 @@ class Salmon return -1; } - if (($return_code == 503) && (stristr(Network::getCurl()->getHeaders(), 'retry-after'))) { + if (($return_code == 503) && (stristr($postResult->getHeader(), 'retry-after'))) { return -1; } diff --git a/src/Util/Network.php b/src/Util/Network.php index f8e4ee9e5b..00eaa80fa6 100644 --- a/src/Util/Network.php +++ b/src/Util/Network.php @@ -208,10 +208,6 @@ class Network $curl_info = @curl_getinfo($ch); } - if (curl_errno($ch) !== CURLE_OK) { - logger('error fetching ' . $url . ': ' . curl_error($ch), LOGGER_INFO); - } - $curlResponse = new Curl($url, $s, $curl_info, curl_errno($ch), curl_error($ch)); if ($curlResponse->isRedirectUrl()) { From b2e7ce47b31cbc79dbba2bac91a425f4df63cad8 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 10 Oct 2018 22:08:13 +0200 Subject: [PATCH 341/428] Renaming Curl to CurlResult --- src/Network/{Curl.php => CurlResult.php} | 10 +++------- src/Util/Network.php | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 17 deletions(-) rename src/Network/{Curl.php => CurlResult.php} (98%) diff --git a/src/Network/Curl.php b/src/Network/CurlResult.php similarity index 98% rename from src/Network/Curl.php rename to src/Network/CurlResult.php index 7cab25ee87..d100361e22 100644 --- a/src/Network/Curl.php +++ b/src/Network/CurlResult.php @@ -8,7 +8,7 @@ use Friendica\Network\HTTPException\InternalServerErrorException; /** * A content class for Curl call results */ -class Curl +class CurlResult { /** * @var int HTTP return code or 0 if timeout or failure @@ -75,15 +75,11 @@ class Curl * * @param string $url optional URL * - * @return Curl a CURL with error response + * @return CurlResult a CURL with error response */ public static function createErrorCurl($url = '') { - return new Curl( - $url, - '', - [ 'http_code' => 0 ] - ); + return new CurlResult($url,'', [ 'http_code' => 0 ]); } /** diff --git a/src/Util/Network.php b/src/Util/Network.php index 00eaa80fa6..1038fa3f04 100644 --- a/src/Util/Network.php +++ b/src/Util/Network.php @@ -7,7 +7,7 @@ namespace Friendica\Util; use Friendica\Core\Addon; use Friendica\Core\System; use Friendica\Core\Config; -use Friendica\Network\Curl; +use Friendica\Network\CurlResult; use DOMDocument; use DomXPath; @@ -53,7 +53,7 @@ class Network * @param string $accept_content supply Accept: header with 'accept_content' as the value * @param string $cookiejar Path to cookie jar file * - * @return Curl 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 = '') { @@ -83,7 +83,7 @@ class Network * 'nobody' => only return the header * 'cookiejar' => path to cookie jar file * - * @return Curl + * @return CurlResult */ public static function curl($url, $binary = false, &$redirects = 0, $opts = []) { @@ -107,13 +107,13 @@ class Network if (self::isUrlBlocked($url)) { logger('domain of ' . $url . ' is blocked', LOGGER_DATA); - return Curl::createErrorCurl($url); + return CurlResult::createErrorCurl($url); } $ch = @curl_init($url); if (($redirects > 8) || (!$ch)) { - return Curl::createErrorCurl($url); + return CurlResult::createErrorCurl($url); } @curl_setopt($ch, CURLOPT_HEADER, true); @@ -208,7 +208,7 @@ class Network $curl_info = @curl_getinfo($ch); } - $curlResponse = new Curl($url, $s, $curl_info, curl_errno($ch), curl_error($ch)); + $curlResponse = new CurlResult($url, $s, $curl_info, curl_errno($ch), curl_error($ch)); if ($curlResponse->isRedirectUrl()) { $redirects++; @@ -233,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 Curl The content + * @return CurlResult The content */ public static function post($url, $params, $headers = null, &$redirects = 0, $timeout = 0) { @@ -241,14 +241,14 @@ class Network if (self::isUrlBlocked($url)) { logger('post_url: domain of ' . $url . ' is blocked', LOGGER_DATA); - return Curl::createErrorCurl($url); + return CurlResult::createErrorCurl($url); } $a = get_app(); $ch = curl_init($url); if (($redirects > 8) || (!$ch)) { - return Curl::createErrorCurl($url); + return CurlResult::createErrorCurl($url); } logger('post_url: start ' . $url, LOGGER_DATA); @@ -310,7 +310,7 @@ class Network $base = $s; $curl_info = curl_getinfo($ch); - $curlResponse = new Curl($url, $s, $curl_info, curl_errno($ch), curl_error($ch)); + $curlResponse = new CurlResult($url, $s, $curl_info, curl_errno($ch), curl_error($ch)); if ($curlResponse->isRedirectUrl()) { $redirects++; From 9711581d4972f3418f3246c84c5310053df8d2f4 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Wed, 10 Oct 2018 22:51:26 +0200 Subject: [PATCH 342/428] Code standard --- src/Network/CurlResult.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Network/CurlResult.php b/src/Network/CurlResult.php index d100361e22..dc83182a64 100644 --- a/src/Network/CurlResult.php +++ b/src/Network/CurlResult.php @@ -79,7 +79,7 @@ class CurlResult */ public static function createErrorCurl($url = '') { - return new CurlResult($url,'', [ 'http_code' => 0 ]); + return new CurlResult($url, '', ['http_code' => 0]); } /** From a95e7f6504dd079b1b65503eac90177a3b088f17 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Thu, 11 Oct 2018 07:45:04 +0200 Subject: [PATCH 343/428] Bugfixing CurlResult --- src/Network/Probe.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 7f80be4e47..2c42643b44 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -1334,10 +1334,10 @@ class Probe // Fetch all additional data from the feed $curlResult = Network::curl($data["poll"]); - if (!empty($curlResult["errno"]) && ($curlResult['errno'] == CURLE_OPERATION_TIMEDOUT)) { + if ($curlResult->isTimeout()) { return false; } - $feed = $curlResult['body']; + $feed = $curlResult->getBody(); $dummy1 = null; $dummy2 = null; $dummy2 = null; From a419eff23a4a1412115862db24f3d5d476ec01d7 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 11 Oct 2018 08:49:52 -0400 Subject: [PATCH 344/428] Replace missing App->getURLPath in mod/install --- mod/install.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mod/install.php b/mod/install.php index 7a69a731ba..97677344a0 100644 --- a/mod/install.php +++ b/mod/install.php @@ -42,7 +42,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 +56,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'])); @@ -97,8 +96,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.'); From ac1ff6c8ce9f23eebf5e53ce799c3b8b84d6de93 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Thu, 11 Oct 2018 08:54:45 -0400 Subject: [PATCH 345/428] Try additional $_SERVER properties to get relative path of Friendica --- src/App.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/App.php b/src/App.php index 9bfb10f7ce..d763cfa43f 100644 --- a/src/App.php +++ b/src/App.php @@ -522,20 +522,29 @@ class App */ private function determineURLPath() { + /* 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) { From 00bf0c24b6cc4a4a1ee88e180eeae01386b414b0 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Thu, 11 Oct 2018 21:19:38 +0200 Subject: [PATCH 346/428] CurlResult Tests --- src/Network/CurlResult.php | 2 +- tests/datasets/curl/about.body | 189 +++++++++++++++++++++++++++ tests/datasets/curl/about.head | 21 +++ tests/src/Network/CurlResultTest.php | 30 +++++ 4 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 tests/datasets/curl/about.body create mode 100644 tests/datasets/curl/about.head create mode 100644 tests/src/Network/CurlResultTest.php diff --git a/src/Network/CurlResult.php b/src/Network/CurlResult.php index dc83182a64..04f183538a 100644 --- a/src/Network/CurlResult.php +++ b/src/Network/CurlResult.php @@ -119,7 +119,7 @@ class CurlResult $header = ''; $base = $result; - while (preg_match('/^HTTP\/[1-2].+? [1-5][0-9][0-9]/', $base)) { + 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)); diff --git a/tests/datasets/curl/about.body b/tests/datasets/curl/about.body new file mode 100644 index 0000000000..b49bca8d97 --- /dev/null +++ b/tests/datasets/curl/about.body @@ -0,0 +1,189 @@ + + + + + + + + + + + + +mastodonten.de - Mastodonten.de + + + + + + + + + + + + + + + + + + + + + + +

    +
    +
    +
    +
    +Mastodon +
    +
    +
    +
    +
    +Mastodon +
    +Sign up on another server +
    +Ich habe die öffentliche Registrierung geschlossen, nachdem sich etwas über 1000 Nutzer bei mastodonten.de angemeldet hatten. Mastodonten.de ist ein Freizeit-Projekt. Würde es weiter wachsen, wäre es in der Freizeit, ohne Beeinträchtigungen meiner Familie, wegen des höheren Administrations- und Moderationsaufwands nicht mehr zu stemmen. Daher dieser Schritt. Jeder, der Nutzer von mastodonten.de kennt, kann sich aber von diesen einladen lassen. Ansonsten gibt es auch viele andere nette Instanzen. +
    +
    + +I closed the public registration after a little over 1000 users had registered at mastodonten.de. Mastodonten.de is a leisure project. If it would grow further, it would be no more to stemmed in the spare time, without impairments of my family, because of the higher administration and moderation expenditure. Hence this step. Everybody who knows users of mastodonten.de can be invited by them. Otherwise there are also many other nice instances. +
    +
    +or +
    +Log in + +
    +
    +
    +
    +Mastodonten.de +
    +
    +
    +
    + +

    +Mastodonten.de +Mastodon hosted on mastodonten.de +

    +
    +

    mastodonten.de ist eine Mastodon Instanz offen für alle netten Leute (über 16). +Geht gut miteinander um (und lest die Regeln wenn ihr euch nicht sicher seid, was das heißt). Wer möchte, kann auch gerne etwas spenden, um den Betrieb von mastodonten.de zu unterstützen. + +
    +
    +mastodonten.de is a Mastodon instance open to nice people (over 16). +Be excellent to each other (and read the rules if you're not sure what that means). Who would like, can donate something, in order to support the operation of mastodonten.de. +

    +
    +
    +
    +
    +
    +
    +Home to +1,034 +users +
    +
    +Who authored +82,821 +statuses +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    What is Mastodon?

    +

    Mastodon is a social network based on open web protocols and free, open-source software. It is decentralized like e-mail.

    +
    + +
    +
    +
    +
    +
    Built for real conversation
    +With 500 characters at your disposal and support for granular content and media warnings, you can express yourself the way you want to. +
    +
    + +
    +
    +
    +
    +
    You’re a person, not a product
    +Mastodon is not a commercial network. No advertising, no data mining, no walled gardens. There is no central authority. +
    +
    + +
    +
    +
    +
    +
    Always within reach
    +Multiple apps for iOS, Android, and other platforms thanks to a developer-friendly API ecosystem allow you to keep up with your friends anywhere. +
    +
    + +
    +
    +
    +
    +
    A more humane approach
    +Learning from failures of other networks, Mastodon aims to make ethical design choices to combat the misuse of social media. +
    +
    + +
    +
    +
    + + +
    + +
    +
    +
    +
    + + + + diff --git a/tests/datasets/curl/about.head b/tests/datasets/curl/about.head new file mode 100644 index 0000000000..c1d4b165d0 --- /dev/null +++ b/tests/datasets/curl/about.head @@ -0,0 +1,21 @@ +HTTP/2 200 +date: Thu, 11 Oct 2018 18:43:54 GMT +content-type: text/html; charset=utf-8 +vary: Accept-Encoding +server: Mastodon +x-frame-options: DENY +x-content-type-options: nosniff +x-xss-protection: 1; mode=block +vary: Accept-Encoding +etag: W/"706e6c48957e1d46ecf9d7597a7880af" +cache-control: max-age=0, private, must-revalidate +set-cookie: _mastodon_session=v3kcy%2FW3aZYBBvZUohuwksEKwzYIyEUlEuJ1KqTAfWPKvVQq%2F4UuJ39zp621VyfpQNlvY46TL%2FYutzXowSLYQBNFCJcrEiF04aU0TdtHls9zynMiyeHhoVgCijOXWXNt9%2FCmpQ49RkNEujkv9NaJ0cum32MCVZKjE9%2BMKmLM%2F8ZygZeLBGJ7sg%3D%3D--QGIiU0%2FpXc3Aym8F--he2iRRPePOdtEs3z%2BufSXg%3D%3D; path=/; secure; HttpOnly +x-request-id: a0c0b8e7-cd60-4efa-b79b-cf1b0d5a0784 +x-runtime: 0.049566 +strict-transport-security: max-age=31536000; includeSubDomains; preload +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +referrer-policy: same-origin +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 +x-xss-protection: 1; mode=block + diff --git a/tests/src/Network/CurlResultTest.php b/tests/src/Network/CurlResultTest.php new file mode 100644 index 0000000000..79b950ca18 --- /dev/null +++ b/tests/src/Network/CurlResultTest.php @@ -0,0 +1,30 @@ + 200 ]); + + $this->assertTrue($curlResult->isSuccess()); + $this->assertSame($header, $curlResult->getHeader()); + $this->assertSame($body, $curlResult->getBody()); + } +} \ No newline at end of file From 1bf7521af87c017ef4fbae192ee4b7cd76c896e7 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 11 Oct 2018 20:08:04 +0000 Subject: [PATCH 347/428] Store conversation data directly from the AP receiver --- src/Protocol/ActivityPub/Processor.php | 23 +++++----------- src/Protocol/ActivityPub/Receiver.php | 36 +++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 69da8b7e5c..5d2d7fe116 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -107,9 +107,8 @@ class Processor * Prepares data for a message * * @param array $activity Activity array - * @param string $body original source */ - public static function createItem($activity, $body) + public static function createItem($activity) { $item = []; $item['verb'] = ACTIVITY_POST; @@ -128,16 +127,15 @@ class Processor self::fetchMissingActivity($activity['reply-to-id'], $activity); } - self::postItem($activity, $item, $body); + self::postItem($activity, $item); } /** * Prepare the item array for a "like" * * @param array $activity Activity array - * @param string $body original source */ - public static function likeItem($activity, $body) + public static function likeItem($activity) { $item = []; $item['verb'] = ACTIVITY_LIKE; @@ -145,7 +143,7 @@ class Processor $item['gravity'] = GRAVITY_ACTIVITY; $item['object-type'] = ACTIVITY_OBJ_NOTE; - self::postItem($activity, $item, $body); + self::postItem($activity, $item); } /** @@ -165,9 +163,8 @@ class Processor * Prepare the item array for a "dislike" * * @param array $activity Activity array - * @param string $body original source */ - public static function dislikeItem($activity, $body) + public static function dislikeItem($activity) { $item = []; $item['verb'] = ACTIVITY_DISLIKE; @@ -175,7 +172,7 @@ class Processor $item['gravity'] = GRAVITY_ACTIVITY; $item['object-type'] = ACTIVITY_OBJ_NOTE; - self::postItem($activity, $item, $body); + self::postItem($activity, $item); } /** @@ -183,9 +180,8 @@ class Processor * * @param array $activity Activity data * @param array $item item array - * @param string $body original source */ - private static function postItem($activity, $item, $body) + private static function postItem($activity, $item) { /// @todo What to do with $activity['context']? @@ -226,11 +222,6 @@ class Processor $item['body'] = $activity['source']; } - $item['protocol'] = Conversation::PARCEL_ACTIVITYPUB; - $item['source'] = $body; - $item['conversation-href'] = $activity['context']; - $item['conversation-uri'] = $activity['conversation']; - foreach ($activity['receiver'] as $receiver) { $item['uid'] = $receiver; $item['contact-id'] = Contact::getIdForURL($activity['author'], $receiver, true); diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index f371eede7f..f54503708b 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -14,6 +14,8 @@ 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 @@ -229,6 +231,32 @@ class Receiver 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 * @@ -268,6 +296,8 @@ class Receiver 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']; @@ -276,15 +306,15 @@ class Receiver switch ($type) { case 'as:Create': case 'as:Announce': - ActivityPub\Processor::createItem($object_data, $body); + ActivityPub\Processor::createItem($object_data); break; case 'as:Like': - ActivityPub\Processor::likeItem($object_data, $body); + ActivityPub\Processor::likeItem($object_data); break; case 'as:Dislike': - ActivityPub\Processor::dislikeItem($object_data, $body); + ActivityPub\Processor::dislikeItem($object_data); break; case 'as:Update': From b099cba4b473686ae3e769b7e5c481b310c726e8 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Thu, 11 Oct 2018 22:18:27 +0200 Subject: [PATCH 348/428] CurlResult Tests & RegEx fix --- src/Network/CurlResult.php | 4 +- tests/datasets/curl/about.redirect | 22 +++++++ tests/src/Network/CurlResultTest.php | 95 +++++++++++++++++++++++++++- 3 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 tests/datasets/curl/about.redirect diff --git a/src/Network/CurlResult.php b/src/Network/CurlResult.php index 04f183538a..e246f4fa56 100644 --- a/src/Network/CurlResult.php +++ b/src/Network/CurlResult.php @@ -119,7 +119,7 @@ class CurlResult $header = ''; $base = $result; - while (preg_match('/^HTTP\/[1-2].+?[1-5][0-9][0-9]/', $base)) { + while (preg_match('/^HTTP\/.+? \d+/', $base)) { $chunk = substr($base, 0, strpos($base, "\r\n\r\n") + 4); $header .= $chunk; $base = substr($base, strlen($chunk)); @@ -177,7 +177,7 @@ class CurlResult $this->redirectUrl .= '?' . $old_location_query; } - $this->isRedirectUrl = filter_var($this->redirectUrl, FILTER_VALIDATE_URL); + $this->isRedirectUrl = filter_var($this->redirectUrl, FILTER_VALIDATE_URL) !== false; } else { $this->isRedirectUrl = false; } diff --git a/tests/datasets/curl/about.redirect b/tests/datasets/curl/about.redirect new file mode 100644 index 0000000000..9033e0f665 --- /dev/null +++ b/tests/datasets/curl/about.redirect @@ -0,0 +1,22 @@ +HTTP/2 301 +date: Thu, 11 Oct 2018 18:43:54 GMT +content-type: text/html; charset=utf-8 +vary: Accept-Encoding +server: Mastodon +Location: https://test.other/some/ +x-frame-options: DENY +x-content-type-options: nosniff +x-xss-protection: 1; mode=block +vary: Accept-Encoding +etag: W/"706e6c48957e1d46ecf9d7597a7880af" +cache-control: max-age=0, private, must-revalidate +set-cookie: _mastodon_session=v3kcy%2FW3aZYBBvZUohuwksEKwzYIyEUlEuJ1KqTAfWPKvVQq%2F4UuJ39zp621VyfpQNlvY46TL%2FYutzXowSLYQBNFCJcrEiF04aU0TdtHls9zynMiyeHhoVgCijOXWXNt9%2FCmpQ49RkNEujkv9NaJ0cum32MCVZKjE9%2BMKmLM%2F8ZygZeLBGJ7sg%3D%3D--QGIiU0%2FpXc3Aym8F--he2iRRPePOdtEs3z%2BufSXg%3D%3D; path=/; secure; HttpOnly +x-request-id: a0c0b8e7-cd60-4efa-b79b-cf1b0d5a0784 +x-runtime: 0.049566 +strict-transport-security: max-age=31536000; includeSubDomains; preload +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +referrer-policy: same-origin +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 +x-xss-protection: 1; mode=block + diff --git a/tests/src/Network/CurlResultTest.php b/tests/src/Network/CurlResultTest.php index 79b950ca18..13a14d985e 100644 --- a/tests/src/Network/CurlResultTest.php +++ b/tests/src/Network/CurlResultTest.php @@ -9,22 +9,111 @@ class CurlResultTest extends TestCase { public function setUp() { - parent::setUp(); // TODO: Change the autogenerated stub + 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 ]); + $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()); } -} \ No newline at end of file + + /** + * @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()); + } +} From 5f9065e00aaa47a0348c4f22ce588a01a75f0a18 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Thu, 11 Oct 2018 22:21:05 +0200 Subject: [PATCH 349/428] smaller about.body --- tests/datasets/curl/about.body | 172 --------------------------------- 1 file changed, 172 deletions(-) diff --git a/tests/datasets/curl/about.body b/tests/datasets/curl/about.body index b49bca8d97..86d8712d03 100644 --- a/tests/datasets/curl/about.body +++ b/tests/datasets/curl/about.body @@ -3,184 +3,12 @@ - - - - - - - -mastodonten.de - Mastodonten.de - - - - - - - - - - - - - - - - -
    -
    -
    -
    -
    -Mastodon -
    -
    -
    -
    -
    -Mastodon -
    -Sign up on another server -
    -Ich habe die öffentliche Registrierung geschlossen, nachdem sich etwas über 1000 Nutzer bei mastodonten.de angemeldet hatten. Mastodonten.de ist ein Freizeit-Projekt. Würde es weiter wachsen, wäre es in der Freizeit, ohne Beeinträchtigungen meiner Familie, wegen des höheren Administrations- und Moderationsaufwands nicht mehr zu stemmen. Daher dieser Schritt. Jeder, der Nutzer von mastodonten.de kennt, kann sich aber von diesen einladen lassen. Ansonsten gibt es auch viele andere nette Instanzen. -
    -
    - -I closed the public registration after a little over 1000 users had registered at mastodonten.de. Mastodonten.de is a leisure project. If it would grow further, it would be no more to stemmed in the spare time, without impairments of my family, because of the higher administration and moderation expenditure. Hence this step. Everybody who knows users of mastodonten.de can be invited by them. Otherwise there are also many other nice instances. -
    -
    -or -
    -Log in - -
    -
    -
    -
    -Mastodonten.de -
    -
    -
    -
    - -

    -Mastodonten.de -Mastodon hosted on mastodonten.de -

    -
    -

    mastodonten.de ist eine Mastodon Instanz offen für alle netten Leute (über 16). -Geht gut miteinander um (und lest die Regeln wenn ihr euch nicht sicher seid, was das heißt). Wer möchte, kann auch gerne etwas spenden, um den Betrieb von mastodonten.de zu unterstützen. - -
    -
    -mastodonten.de is a Mastodon instance open to nice people (over 16). -Be excellent to each other (and read the rules if you're not sure what that means). Who would like, can donate something, in order to support the operation of mastodonten.de. -

    -
    -
    -
    -
    -
    -
    -Home to -1,034 -users -
    -
    -Who authored -82,821 -statuses -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    What is Mastodon?

    -

    Mastodon is a social network based on open web protocols and free, open-source software. It is decentralized like e-mail.

    -
    - -
    -
    -
    -
    -
    Built for real conversation
    -With 500 characters at your disposal and support for granular content and media warnings, you can express yourself the way you want to. -
    -
    - -
    -
    -
    -
    -
    You’re a person, not a product
    -Mastodon is not a commercial network. No advertising, no data mining, no walled gardens. There is no central authority. -
    -
    - -
    -
    -
    -
    -
    Always within reach
    -Multiple apps for iOS, Android, and other platforms thanks to a developer-friendly API ecosystem allow you to keep up with your friends anywhere. -
    -
    - -
    -
    -
    -
    -
    A more humane approach
    -Learning from failures of other networks, Mastodon aims to make ethical design choices to combat the misuse of social media. -
    -
    - -
    -
    -
    - - -
    - -
    -
    From 82682889536046ca650ce35ff1410be2bb736c56 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 11 Oct 2018 20:38:57 +0000 Subject: [PATCH 350/428] We now store the diaspora comment data as well --- src/Protocol/ActivityPub/Processor.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 5d2d7fe116..166530f472 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -215,6 +215,7 @@ class Processor $item['tag'] = self::constructTagList($activity['tags'], $activity['sensitive']); $item['app'] = $activity['service']; $item['plink'] = defaults($activity, 'alternate-url', $item['uri']); + $item['diaspora_signed_text'] = defaults($activity, 'diaspora:comment', ''); $item = self::constructAttachList($activity['attachments'], $item); From 80ea86113d7646e9ab24948fcdf11183d07920df Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Thu, 11 Oct 2018 23:14:12 +0200 Subject: [PATCH 351/428] Move mod Contacts to /src/Module --- mod/allfriends.php | 4 +- mod/common.php | 4 +- mod/crepair.php | 3 +- mod/dirfind.php | 5 +- mod/group.php | 9 +- mod/update_contacts.php | 5 +- src/Module/Contacts.php | 1138 +++++++++++++++++++++++++++++++++++++ view/theme/frio/theme.php | 5 +- 8 files changed, 1153 insertions(+), 20 deletions(-) create mode 100644 src/Module/Contacts.php diff --git a/mod/allfriends.php b/mod/allfriends.php index b41d0c891b..190ab12a66 100644 --- a/mod/allfriends.php +++ b/mod/allfriends.php @@ -12,9 +12,9 @@ use Friendica\Model\Contact; use Friendica\Model\GContact; use Friendica\Model\Profile; use Friendica\Util\Proxy as ProxyUtils; +use Friendica\Module\Contacts; require_once 'include/dba.php'; -require_once 'mod/contacts.php'; function allfriends_content(App $a) { @@ -96,7 +96,7 @@ function allfriends_content(App $a) $entries[] = $entry; } - $tab_str = contacts_tab($a, $contact, 4); + $tab_str = Contacts::contacts_tab($a, $contact, 4); $tpl = get_markup_template('viewcontact_template.tpl'); diff --git a/mod/common.php b/mod/common.php index d694527b86..13e5bf0927 100644 --- a/mod/common.php +++ b/mod/common.php @@ -11,9 +11,9 @@ use Friendica\Model\Contact; use Friendica\Model\GContact; use Friendica\Model\Profile; use Friendica\Util\Proxy as ProxyUtils; +use Friendica\Module\Contacts; require_once 'include/dba.php'; -require_once 'mod/contacts.php'; function common_content(App $a) { @@ -137,7 +137,7 @@ function common_content(App $a) $title = ''; $tab_str = ''; if ($cmd === 'loc' && $cid && local_user() == $uid) { - $tab_str = contacts_tab($a, $contact, 4); + $tab_str = Contacts::contacts_tab($a, $contact, 4); } else { $title = L10n::t('Common Friends'); } diff --git a/mod/crepair.php b/mod/crepair.php index 076c611db4..99aee13578 100644 --- a/mod/crepair.php +++ b/mod/crepair.php @@ -10,6 +10,7 @@ use Friendica\Core\Protocol; use Friendica\Database\DBA; use Friendica\Model\Contact; use Friendica\Model\Profile; +use Friendica\Module\Contacts; require_once 'mod/contacts.php'; @@ -135,7 +136,7 @@ function crepair_content(App $a) $update_profile = in_array($contact['network'], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]); - $tab_str = contacts_tab($a, $contact, 5); + $tab_str = Contacts::contacts_tab($a, $contact, 5); $tpl = get_markup_template('crepair.tpl'); $o = replace_macros($tpl, [ diff --git a/mod/dirfind.php b/mod/dirfind.php index 5fe9ae13af..e183e6c029 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -18,8 +18,7 @@ use Friendica\Network\Probe; use Friendica\Protocol\PortableContact; use Friendica\Util\Network; use Friendica\Util\Proxy as ProxyUtils; - -require_once 'mod/contacts.php'; +use Friendica\Module\Contacts; function dirfind_init(App $a) { @@ -211,7 +210,7 @@ function dirfind_content(App $a, $prefix = "") { $contact = DBA::selectFirst('contact', [], ['id' => $jj->cid]); if (DBA::isResult($contact)) { $photo_menu = Contact::photoMenu($contact); - $details = _contact_detail_for_template($contact); + $details = Contacts::_contact_detail_for_template($contact); $alt_text = $details['alt_text']; } else { $photo_menu = []; diff --git a/mod/group.php b/mod/group.php index 8f65eb643d..cfcbca4e47 100644 --- a/mod/group.php +++ b/mod/group.php @@ -13,6 +13,7 @@ use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model\Contact; use Friendica\Model\Group; +use Friendica\Module\Contacts; function group_init(App $a) { if (local_user()) { @@ -116,8 +117,6 @@ function group_content(App $a) { $nogroup = false; if (($a->argc == 2) && ($a->argv[1] === 'none')) { - require_once 'mod/contacts.php'; - $id = -1; $nogroup = true; $group = [ @@ -176,8 +175,6 @@ function group_content(App $a) { } if (($a->argc > 1) && intval($a->argv[1])) { - require_once 'mod/contacts.php'; - $r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1", intval($a->argv[1]), intval(local_user()) @@ -253,7 +250,7 @@ function group_content(App $a) { // Format the data of the group members foreach ($members as $member) { if ($member['url']) { - $entry = _contact_detail_for_template($member); + $entry = Contacts::_contact_detail_for_template($member); $entry['label'] = 'members'; $entry['photo_menu'] = ''; $entry['change_member'] = [ @@ -282,7 +279,7 @@ function group_content(App $a) { // Format the data of the contacts who aren't in the contact group foreach ($r as $member) { if (!in_array($member['id'], $preselected)) { - $entry = _contact_detail_for_template($member); + $entry = Contacts::_contact_detail_for_template($member); $entry['label'] = 'contacts'; if (!$nogroup) $entry['photo_menu'] = []; diff --git a/mod/update_contacts.php b/mod/update_contacts.php index 863542e666..1ad5cd4a3b 100644 --- a/mod/update_contacts.php +++ b/mod/update_contacts.php @@ -5,8 +5,7 @@ use Friendica\App; use Friendica\Core\L10n; use Friendica\Core\PConfig; - -require_once 'mod/contacts.php'; +use Friendica\Module\Contacts; function update_contacts_content(App $a) { @@ -15,7 +14,7 @@ function update_contacts_content(App $a) echo "
    "; if ($_GET["force"] == 1) { - $text = contacts_content($a, true); + $text = Contacts::contacts_content($a, true); } else { $text = ''; } diff --git a/src/Module/Contacts.php b/src/Module/Contacts.php new file mode 100644 index 0000000000..a017b55b1e --- /dev/null +++ b/src/Module/Contacts.php @@ -0,0 +1,1138 @@ +page, 'aside')) { + $a->page['aside'] = ''; + } + + $contact_id = null; + $contact = null; + if ((($a->argc == 2) && intval($a->argv[1])) || (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations']))) { + $contact_id = intval($a->argv[1]); + $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); + + if (!DBA::isResult($contact)) { + $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => 0]); + } + + // Don't display contacts that are about to be deleted + if ($contact['network'] == Protocol::PHANTOM) { + $contact = false; + } + } + + if (DBA::isResult($contact)) { + if ($contact['self']) { + if (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations'])) { + goaway('profile/' . $contact['nick']); + } else { + goaway('profile/' . $contact['nick'] . '?tab=profile'); + } + } + + $a->data['contact'] = $contact; + + if (($a->data['contact']['network'] != "") && ($a->data['contact']['network'] != Protocol::DFRN)) { + $networkname = format_network_name($a->data['contact']['network'], $a->data['contact']['url']); + } else { + $networkname = ''; + } + + /// @TODO Add nice spaces + $vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"), [ + '$name' => htmlentities($a->data['contact']['name']), + '$photo' => $a->data['contact']['photo'], + '$url' => Contact::MagicLink($a->data['contact']['url']), + '$addr' => (($a->data['contact']['addr'] != "") ? ($a->data['contact']['addr']) : ""), + '$network_name' => $networkname, + '$network' => L10n::t('Network:'), + '$account_type' => Contact::getAccountType($a->data['contact']) + ]); + + $findpeople_widget = ''; + $follow_widget = ''; + $networks_widget = ''; + } else { + $vcard_widget = ''; + $networks_widget = Widget::networks('contacts', $nets); + if (isset($_GET['add'])) { + $follow_widget = Widget::follow($_GET['add']); + } else { + $follow_widget = Widget::follow(); + } + + $findpeople_widget = Widget::findPeople(); + } + + if ($contact['uid'] != 0) { + $groups_widget = Group::sidebarWidget('contacts', 'group', 'full', 'everyone', $contact_id); + } else { + $groups_widget = null; + } + + $a->page['aside'] .= replace_macros(get_markup_template("contacts-widget-sidebar.tpl"), [ + '$vcard_widget' => $vcard_widget, + '$findpeople_widget' => $findpeople_widget, + '$follow_widget' => $follow_widget, + '$groups_widget' => $groups_widget, + '$networks_widget' => $networks_widget + ]); + + $base = System::baseUrl(); + $tpl = get_markup_template("contacts-head.tpl"); + $a->page['htmlhead'] .= replace_macros($tpl, [ + '$baseurl' => System::baseUrl(true), + '$base' => $base + ]); + } + + private static function contacts_batch_actions(App $a) + { + if (empty($_POST['contact_batch']) || !is_array($_POST['contact_batch'])) { + return; + } + + $contacts_id = $_POST['contact_batch']; + + $orig_records = q("SELECT * FROM `contact` WHERE `id` IN (%s) AND `uid` = %d AND `self` = 0", + implode(",", $contacts_id), + intval(local_user()) + ); + + $count_actions = 0; + foreach ($orig_records as $orig_record) { + $contact_id = $orig_record['id']; + if (x($_POST, 'contacts_batch_update')) { + self::_contact_update($contact_id); + $count_actions++; + } + if (x($_POST, 'contacts_batch_block')) { + self::_contact_block($contact_id); + $count_actions++; + } + if (x($_POST, 'contacts_batch_ignore')) { + self::_contact_ignore($contact_id); + $count_actions++; + } + if (x($_POST, 'contacts_batch_archive')) { + $r = self::_contact_archive($contact_id, $orig_record); + if ($r) { + $count_actions++; + } + } + if (x($_POST, 'contacts_batch_drop')) { + self::_contact_drop($orig_record); + $count_actions++; + } + } + if ($count_actions > 0) { + info(L10n::tt("%d contact edited.", "%d contacts edited.", $count_actions)); + } + + goaway('contacts'); + } + + public static function post() + { + $a = self::getApp(); + + if (!local_user()) { + return; + } + + if ($a->argv[1] === "batch") { + contacts_batch_actions($a); + return; + } + + $contact_id = intval($a->argv[1]); + if (!$contact_id) { + return; + } + + if (!DBA::exists('contact', ['id' => $contact_id, 'uid' => local_user()])) { + notice(L10n::t('Could not access contact record.') . EOL); + goaway('contacts'); + return; // NOTREACHED + } + + Addon::callHooks('contact_edit_post', $_POST); + + $profile_id = intval(defaults($_POST, 'profile-assign', 0)); + if ($profile_id) { + if (!DBA::exists('profile', ['id' => $profile_id, 'uid' => local_user()])) { + notice(L10n::t('Could not locate selected profile.') . EOL); + return; + } + } + + $hidden = intval($_POST['hidden']); + + $notify = intval($_POST['notify']); + + $fetch_further_information = intval(defaults($_POST, 'fetch_further_information', 0)); + + $ffi_keyword_blacklist = escape_tags(trim(defaults($_POST, 'ffi_keyword_blacklist', ''))); + + $priority = intval(defaults($_POST, 'poll', 0)); + if ($priority > 5 || $priority < 0) { + $priority = 0; + } + + $info = escape_tags(trim($_POST['info'])); + + $r = q("UPDATE `contact` SET `profile-id` = %d, `priority` = %d , `info` = '%s', + `hidden` = %d, `notify_new_posts` = %d, `fetch_further_information` = %d, + `ffi_keyword_blacklist` = '%s' WHERE `id` = %d AND `uid` = %d", + intval($profile_id), + intval($priority), + DBA::escape($info), + intval($hidden), + intval($notify), + intval($fetch_further_information), + DBA::escape($ffi_keyword_blacklist), + intval($contact_id), + intval(local_user()) + ); + if (DBA::isResult($r)) { + info(L10n::t('Contact updated.') . EOL); + } else { + notice(L10n::t('Failed to update contact record.') . EOL); + } + + $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); + if (DBA::isResult($contact)) { + $a->data['contact'] = $contact; + } + + return; + } + + /* contact actions */ + + private static function _contact_update($contact_id) + { + $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()]); + if (!DBA::isResult($contact)) { + return; + } + + $uid = $contact["uid"]; + + if ($contact["network"] == Protocol::OSTATUS) { + $result = Contact::createFromProbe($uid, $contact["url"], false, $contact["network"]); + + if ($result['success']) { + q("UPDATE `contact` SET `subhub` = 1 WHERE `id` = %d", intval($contact_id)); + } + } else { + // pull feed and consume it, which should subscribe to the hub. + Worker::add(PRIORITY_HIGH, "OnePoll", $contact_id, "force"); + } + } + + private static function _contact_update_profile($contact_id) + { + $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()]); + if (!DBA::isResult($contact)) { + return; + } + + $uid = $contact["uid"]; + + $data = Probe::uri($contact["url"], "", 0, false); + + // "Feed" or "Unknown" is mostly a sign of communication problems + if ((in_array($data["network"], [Protocol::FEED, Protocol::PHANTOM])) && ($data["network"] != $contact["network"])) { + return; + } + + $updatefields = ["name", "nick", "url", "addr", "batch", "notify", "poll", "request", "confirm", + "poco", "network", "alias"]; + $update = []; + + if ($data["network"] == Protocol::OSTATUS) { + $result = Contact::createFromProbe($uid, $data["url"], false); + + if ($result['success']) { + $update["subhub"] = true; + } + } + + foreach ($updatefields AS $field) { + if (isset($data[$field]) && ($data[$field] != "")) { + $update[$field] = $data[$field]; + } + } + + $update["nurl"] = normalise_link($data["url"]); + + $query = ""; + + if (isset($data["priority"]) && ($data["priority"] != 0)) { + $query = "`priority` = " . intval($data["priority"]); + } + + foreach ($update AS $key => $value) { + if ($query != "") { + $query .= ", "; + } + + $query .= "`" . $key . "` = '" . DBA::escape($value) . "'"; + } + + if ($query == "") { + return; + } + + $r = q("UPDATE `contact` SET $query WHERE `id` = %d AND `uid` = %d", + intval($contact_id), + intval(local_user()) + ); + + // Update the entry in the contact table + Contact::updateAvatar($data['photo'], local_user(), $contact_id, true); + + // Update the entry in the gcontact table + GContact::updateFromProbe($data["url"]); + } + + private static function _contact_block($contact_id) + { + $blocked = !Contact::isBlockedByUser($contact_id, local_user()); + Contact::setBlockedForUser($contact_id, local_user(), $blocked); + } + + private static function _contact_ignore($contact_id) + { + $ignored = !Contact::isIgnoredByUser($contact_id, local_user()); + Contact::setIgnoredForUser($contact_id, local_user(), $ignored); + } + + private static function _contact_archive($contact_id, $orig_record) + { + $archived = (($orig_record['archive']) ? 0 : 1); + $r = q("UPDATE `contact` SET `archive` = %d WHERE `id` = %d AND `uid` = %d", + intval($archived), + intval($contact_id), + intval(local_user()) + ); + return DBA::isResult($r); + } + + private static function _contact_drop($orig_record) + { + $a = get_app(); + + $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` + WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1", + intval($a->user['uid']) + ); + if (!DBA::isResult($r)) { + return; + } + + Contact::terminateFriendship($r[0], $orig_record, true); + Contact::remove($orig_record['id']); + } + + public static function contacts_content($update = 0) + { + $a = self::getApp(); + $sort_type = 0; + $o = ''; + Nav::setSelected('contacts'); + + if (!local_user()) { + notice(L10n::t('Permission denied.') . EOL); + return Login::form(); + } + + if ($a->argc == 3) { + $contact_id = intval($a->argv[1]); + if (!$contact_id) { + return; + } + + $cmd = $a->argv[2]; + + $orig_record = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => [0, local_user()], 'self' => false]); + if (!DBA::isResult($orig_record)) { + notice(L10n::t('Could not access contact record.') . EOL); + goaway('contacts'); + return; // NOTREACHED + } + + if ($cmd === 'update' && ($orig_record['uid'] != 0)) { + self::_contact_update($contact_id); + goaway('contacts/' . $contact_id); + // NOTREACHED + } + + if ($cmd === 'updateprofile' && ($orig_record['uid'] != 0)) { + self::_contact_update_profile($contact_id); + goaway('crepair/' . $contact_id); + // NOTREACHED + } + + if ($cmd === 'block') { + self::_contact_block($contact_id); + + $blocked = Contact::isBlockedByUser($contact_id, local_user()); + info(($blocked ? L10n::t('Contact has been blocked') : L10n::t('Contact has been unblocked')) . EOL); + + goaway('contacts/' . $contact_id); + return; // NOTREACHED + } + + if ($cmd === 'ignore') { + self::_contact_ignore($contact_id); + + $ignored = Contact::isIgnoredByUser($contact_id, local_user()); + info(($ignored ? L10n::t('Contact has been ignored') : L10n::t('Contact has been unignored')) . EOL); + + goaway('contacts/' . $contact_id); + return; // NOTREACHED + } + + if ($cmd === 'archive' && ($orig_record['uid'] != 0)) { + $r = self::_contact_archive($contact_id, $orig_record); + if ($r) { + $archived = (($orig_record['archive']) ? 0 : 1); + info((($archived) ? L10n::t('Contact has been archived') : L10n::t('Contact has been unarchived')) . EOL); + } + + goaway('contacts/' . $contact_id); + return; // NOTREACHED + } + + if ($cmd === 'drop' && ($orig_record['uid'] != 0)) { + // Check if we should do HTML-based delete confirmation + if (x($_REQUEST, 'confirm')) { + //
    can't take arguments in its "action" parameter + // so add any arguments as hidden inputs + $query = explode_querystring($a->query_string); + $inputs = []; + foreach ($query['args'] as $arg) { + if (strpos($arg, 'confirm=') === false) { + $arg_parts = explode('=', $arg); + $inputs[] = ['name' => $arg_parts[0], 'value' => $arg_parts[1]]; + } + } + + $a->page['aside'] = ''; + + return replace_macros(get_markup_template('contact_drop_confirm.tpl'), [ + '$header' => L10n::t('Drop contact'), + '$contact' => self::_contact_detail_for_template($orig_record), + '$method' => 'get', + '$message' => L10n::t('Do you really want to delete this contact?'), + '$extra_inputs' => $inputs, + '$confirm' => L10n::t('Yes'), + '$confirm_url' => $query['base'], + '$confirm_name' => 'confirmed', + '$cancel' => L10n::t('Cancel'), + ]); + } + // Now check how the user responded to the confirmation query + if (x($_REQUEST, 'canceled')) { + goaway('contacts'); + } + + self::_contact_drop($orig_record); + info(L10n::t('Contact has been removed.') . EOL); + + goaway('contacts'); + return; // NOTREACHED + } + if ($cmd === 'posts') { + return self::contact_posts($a, $contact_id); + } + if ($cmd === 'conversations') { + return self::contact_conversations($a, $contact_id, $update); + } + } + + $_SESSION['return_url'] = $a->query_string; + + if ((x($a->data, 'contact')) && (is_array($a->data['contact']))) { + $contact_id = $a->data['contact']['id']; + $contact = $a->data['contact']; + + $a->page['htmlhead'] .= replace_macros(get_markup_template('contact_head.tpl'), [ + '$baseurl' => System::baseUrl(true), + ]); + + $contact['blocked'] = Contact::isBlockedByUser($contact['id'], local_user()); + $contact['readonly'] = Contact::isIgnoredByUser($contact['id'], local_user()); + + $dir_icon = ''; + $relation_text = ''; + switch ($contact['rel']) { + case Contact::FRIEND: + $dir_icon = 'images/lrarrow.gif'; + $relation_text = L10n::t('You are mutual friends with %s'); + break; + + case Contact::FOLLOWER; + $dir_icon = 'images/larrow.gif'; + $relation_text = L10n::t('You are sharing with %s'); + break; + + case Contact::SHARING; + $dir_icon = 'images/rarrow.gif'; + $relation_text = L10n::t('%s is sharing with you'); + break; + + default: + break; + } + + if ($contact['uid'] == 0) { + $relation_text = ''; + } + + if (!in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])) { + $relation_text = ""; + } + + $relation_text = sprintf($relation_text, htmlentities($contact['name'])); + + $url = Contact::magicLink($contact['url']); + if (strpos($url, 'redir/') === 0) { + $sparkle = ' class="sparkle" '; + } else { + $sparkle = ''; + } + + $insecure = L10n::t('Private communications are not available for this contact.'); + + $last_update = (($contact['last-update'] <= NULL_DATE) ? L10n::t('Never') : DateTimeFormat::local($contact['last-update'], 'D, j M Y, g:i A')); + + if ($contact['last-update'] > NULL_DATE) { + $last_update .= ' ' . (($contact['last-update'] <= $contact['success_update']) ? L10n::t("\x28Update was successful\x29") : L10n::t("\x28Update was not successful\x29")); + } + $lblsuggest = (($contact['network'] === Protocol::DFRN) ? L10n::t('Suggest friends') : ''); + + $poll_enabled = in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]); + + $nettype = L10n::t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact["url"])); + + // tabs + $tab_str = self::contacts_tab($a, $contact, 3); + + $lost_contact = (($contact['archive'] && $contact['term-date'] > NULL_DATE && $contact['term-date'] < DateTimeFormat::utcNow()) ? L10n::t('Communications lost with this contact!') : ''); + + $fetch_further_information = null; + if ($contact['network'] == Protocol::FEED) { + $fetch_further_information = [ + 'fetch_further_information', + L10n::t('Fetch further information for feeds'), + $contact['fetch_further_information'], + L10n::t("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."), + ['0' => L10n::t('Disabled'), + '1' => L10n::t('Fetch information'), + '3' => L10n::t('Fetch keywords'), + '2' => L10n::t('Fetch information and keywords') + ] + ]; + } + + $poll_interval = null; + if (in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) { + $poll_interval = ContactSelector::pollInterval($contact['priority'], (!$poll_enabled)); + } + + $profile_select = null; + if ($contact['network'] == Protocol::DFRN) { + $profile_select = ContactSelector::profileAssign($contact['profile-id'], (($contact['network'] !== Protocol::DFRN) ? true : false)); + } + + /// @todo Only show the following link with DFRN when the remote version supports it + $follow = ''; + $follow_text = ''; + if (in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) { + if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { + $follow = System::baseUrl(true) . "/unfollow?url=" . urlencode($contact["url"]); + $follow_text = L10n::t("Disconnect/Unfollow"); + } + } else { + $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]); + $follow_text = L10n::t("Connect/Follow"); + } + + // Load contactact related actions like hide, suggest, delete and others + $contact_actions = self::contact_actions($contact); + + if ($contact['uid'] != 0) { + $lbl_vis1 = L10n::t('Profile Visibility'); + $lbl_info1 = L10n::t('Contact Information / Notes'); + $contact_settings_label = L10n::t('Contact Settings'); + } else { + $lbl_vis1 = null; + $lbl_info1 = null; + $contact_settings_label = null; + } + + $tpl = get_markup_template("contact_edit.tpl"); + $o .= replace_macros($tpl, [ + '$header' => L10n::t("Contact"), + '$tab_str' => $tab_str, + '$submit' => L10n::t('Submit'), + '$lbl_vis1' => $lbl_vis1, + '$lbl_vis2' => L10n::t('Please choose the profile you would like to display to %s when viewing your profile securely.', $contact['name']), + '$lbl_info1' => $lbl_info1, + '$lbl_info2' => L10n::t('Their personal note'), + '$reason' => trim(notags($contact['reason'])), + '$infedit' => L10n::t('Edit contact notes'), + '$common_link' => 'common/loc/' . local_user() . '/' . $contact['id'], + '$relation_text' => $relation_text, + '$visit' => L10n::t('Visit %s\'s profile [%s]', $contact['name'], $contact['url']), + '$blockunblock' => L10n::t('Block/Unblock contact'), + '$ignorecont' => L10n::t('Ignore contact'), + '$lblcrepair' => L10n::t("Repair URL settings"), + '$lblrecent' => L10n::t('View conversations'), + '$lblsuggest' => $lblsuggest, + '$nettype' => $nettype, + '$poll_interval' => $poll_interval, + '$poll_enabled' => $poll_enabled, + '$lastupdtext' => L10n::t('Last update:'), + '$lost_contact' => $lost_contact, + '$updpub' => L10n::t('Update public posts'), + '$last_update' => $last_update, + '$udnow' => L10n::t('Update now'), + '$follow' => $follow, + '$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' => (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') : ''), + '$hidden' => ['hidden', L10n::t('Hide this contact from others'), ($contact['hidden'] == 1), L10n::t('Replies/likes to your public posts may 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, + '$ffi_keyword_blacklist' => $contact['ffi_keyword_blacklist'], + '$ffi_keyword_blacklist' => ['ffi_keyword_blacklist', L10n::t('Blacklisted keywords'), $contact['ffi_keyword_blacklist'], L10n::t('Comma separated list of keywords that should not be converted to hashtags, when "Fetch information and keywords" is selected')], + '$photo' => $contact['photo'], + '$name' => htmlentities($contact['name']), + '$dir_icon' => $dir_icon, + '$sparkle' => $sparkle, + '$url' => $url, + '$profileurllabel' => L10n::t('Profile URL'), + '$profileurl' => $contact['url'], + '$account_type' => Contact::getAccountType($contact), + '$location' => BBCode::convert($contact["location"]), + '$location_label' => L10n::t("Location:"), + '$xmpp' => BBCode::convert($contact["xmpp"]), + '$xmpp_label' => L10n::t("XMPP:"), + '$about' => BBCode::convert($contact["about"], false), + '$about_label' => L10n::t("About:"), + '$keywords' => $contact["keywords"], + '$keywords_label' => L10n::t("Tags:"), + '$contact_action_button' => L10n::t("Actions"), + '$contact_actions' => $contact_actions, + '$contact_status' => L10n::t("Status"), + '$contact_settings_label' => $contact_settings_label, + '$contact_profile_label' => L10n::t("Profile"), + ]); + + $arr = ['contact' => $contact, 'output' => $o]; + + Addon::callHooks('contact_edit', $arr); + + return $arr['output']; + } + + $blocked = false; + $hidden = false; + $ignored = false; + $archived = false; + $all = false; + + if (($a->argc == 2) && ($a->argv[1] === 'all')) { + $sql_extra = ''; + $all = true; + } elseif (($a->argc == 2) && ($a->argv[1] === 'blocked')) { + $sql_extra = " AND `blocked` = 1 "; + $blocked = true; + } elseif (($a->argc == 2) && ($a->argv[1] === 'hidden')) { + $sql_extra = " AND `hidden` = 1 "; + $hidden = true; + } elseif (($a->argc == 2) && ($a->argv[1] === 'ignored')) { + $sql_extra = " AND `readonly` = 1 "; + $ignored = true; + } elseif (($a->argc == 2) && ($a->argv[1] === 'archived')) { + $sql_extra = " AND `archive` = 1 "; + $archived = true; + } else { + $sql_extra = " AND `blocked` = 0 "; + } + + $sql_extra .= sprintf(" AND `network` != '%s' ", Protocol::PHANTOM); + + $search = x($_GET, 'search') ? notags(trim($_GET['search'])) : ''; + $nets = x($_GET, 'nets' ) ? notags(trim($_GET['nets'])) : ''; + + $tabs = [ + [ + 'label' => L10n::t('Suggestions'), + 'url' => 'suggest', + 'sel' => '', + 'title' => L10n::t('Suggest potential friends'), + 'id' => 'suggestions-tab', + 'accesskey' => 'g', + ], + [ + 'label' => L10n::t('All Contacts'), + 'url' => 'contacts/all', + 'sel' => ($all) ? 'active' : '', + 'title' => L10n::t('Show all contacts'), + 'id' => 'showall-tab', + 'accesskey' => 'l', + ], + [ + 'label' => L10n::t('Unblocked'), + 'url' => 'contacts', + 'sel' => ((!$all) && (!$blocked) && (!$hidden) && (!$search) && (!$nets) && (!$ignored) && (!$archived)) ? 'active' : '', + 'title' => L10n::t('Only show unblocked contacts'), + 'id' => 'showunblocked-tab', + 'accesskey' => 'o', + ], + [ + 'label' => L10n::t('Blocked'), + 'url' => 'contacts/blocked', + 'sel' => ($blocked) ? 'active' : '', + 'title' => L10n::t('Only show blocked contacts'), + 'id' => 'showblocked-tab', + 'accesskey' => 'b', + ], + [ + 'label' => L10n::t('Ignored'), + 'url' => 'contacts/ignored', + 'sel' => ($ignored) ? 'active' : '', + 'title' => L10n::t('Only show ignored contacts'), + 'id' => 'showignored-tab', + 'accesskey' => 'i', + ], + [ + 'label' => L10n::t('Archived'), + 'url' => 'contacts/archived', + 'sel' => ($archived) ? 'active' : '', + 'title' => L10n::t('Only show archived contacts'), + 'id' => 'showarchived-tab', + 'accesskey' => 'y', + ], + [ + 'label' => L10n::t('Hidden'), + 'url' => 'contacts/hidden', + 'sel' => ($hidden) ? 'active' : '', + 'title' => L10n::t('Only show hidden contacts'), + 'id' => 'showhidden-tab', + 'accesskey' => 'h', + ], + ]; + + $tab_tpl = get_markup_template('common_tabs.tpl'); + $t = replace_macros($tab_tpl, ['$tabs' => $tabs]); + + $total = 0; + $searching = false; + $search_hdr = null; + if ($search) { + $searching = true; + $search_hdr = $search; + $search_txt = DBA::escape(protect_sprintf(preg_quote($search))); + $sql_extra .= " AND (name REGEXP '$search_txt' OR url REGEXP '$search_txt' OR nick REGEXP '$search_txt') "; + } + + if ($nets) { + $sql_extra .= sprintf(" AND network = '%s' ", DBA::escape($nets)); + } + + $sql_extra2 = ((($sort_type > 0) && ($sort_type <= Contact::FRIEND)) ? sprintf(" AND `rel` = %d ", intval($sort_type)) : ''); + + $r = q("SELECT COUNT(*) AS `total` FROM `contact` + WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 ", + intval($_SESSION['uid']) + ); + if (DBA::isResult($r)) { + $a->set_pager_total($r[0]['total']); + $total = $r[0]['total']; + } + + $sql_extra3 = Widget::unavailableNetworks(); + + $contacts = []; + + $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 $sql_extra3 ORDER BY `name` ASC LIMIT %d , %d ", + intval($_SESSION['uid']), + intval($a->pager['start']), + intval($a->pager['itemspage']) + ); + if (DBA::isResult($r)) { + foreach ($r as $rr) { + $rr['blocked'] = Contact::isBlockedByUser($rr['id'], local_user()); + $rr['readonly'] = Contact::isIgnoredByUser($rr['id'], local_user()); + $contacts[] = self::_contact_detail_for_template($rr); + } + } + + $tpl = get_markup_template("contacts-template.tpl"); + $o .= replace_macros($tpl, [ + '$baseurl' => System::baseUrl(), + '$header' => L10n::t('Contacts') . (($nets) ? ' - ' . ContactSelector::networkToName($nets) : ''), + '$tabs' => $t, + '$total' => $total, + '$search' => $search_hdr, + '$desc' => L10n::t('Search your contacts'), + '$finding' => $searching ? L10n::t('Results for: %s', $search) : "", + '$submit' => L10n::t('Find'), + '$cmd' => $a->cmd, + '$contacts' => $contacts, + '$contact_drop_confirm' => L10n::t('Do you really want to delete this contact?'), + 'multiselect' => 1, + '$batch_actions' => [ + 'contacts_batch_update' => L10n::t('Update'), + 'contacts_batch_block' => L10n::t('Block') . "/" . L10n::t("Unblock"), + "contacts_batch_ignore" => L10n::t('Ignore') . "/" . L10n::t("Unignore"), + "contacts_batch_archive" => L10n::t('Archive') . "/" . L10n::t("Unarchive"), + "contacts_batch_drop" => L10n::t('Delete'), + ], + '$h_batch_actions' => L10n::t('Batch Actions'), + '$paginate' => paginate($a), + ]); + + return $o; + } + + /** + * @brief List of pages for the Contact TabBar + * + * Available Pages are 'Status', 'Profile', 'Contacts' and 'Common Friends' + * + * @param App $a + * @param array $contact The contact array + * @param int $active_tab 1 if tab should be marked as active + * + * @return string + */ + public static function contacts_tab($a, $contact, $active_tab) + { + // tabs + $tabs = [ + [ + 'label' => L10n::t('Status'), + 'url' => "contacts/" . $contact['id'] . "/conversations", + 'sel' => (($active_tab == 1) ? 'active' : ''), + 'title' => L10n::t('Conversations started by this contact'), + 'id' => 'status-tab', + 'accesskey' => 'm', + ], + [ + 'label' => L10n::t('Posts and Comments'), + 'url' => "contacts/" . $contact['id'] . "/posts", + 'sel' => (($active_tab == 2) ? 'active' : ''), + 'title' => L10n::t('Status Messages and Posts'), + 'id' => 'posts-tab', + 'accesskey' => 'p', + ], + [ + 'label' => L10n::t('Profile'), + 'url' => "contacts/" . $contact['id'], + 'sel' => (($active_tab == 3) ? 'active' : ''), + 'title' => L10n::t('Profile Details'), + 'id' => 'profile-tab', + 'accesskey' => 'o', + ] + ]; + + // Show this tab only if there is visible friend list + $x = GContact::countAllFriends(local_user(), $contact['id']); + if ($x) { + $tabs[] = ['label' => L10n::t('Contacts'), + 'url' => "allfriends/" . $contact['id'], + 'sel' => (($active_tab == 4) ? 'active' : ''), + 'title' => L10n::t('View all contacts'), + 'id' => 'allfriends-tab', + 'accesskey' => 't']; + } + + // Show this tab only if there is visible common friend list + $common = GContact::countCommonFriends(local_user(), $contact['id']); + if ($common) { + $tabs[] = ['label' => L10n::t('Common Friends'), + 'url' => "common/loc/" . local_user() . "/" . $contact['id'], + 'sel' => (($active_tab == 5) ? 'active' : ''), + 'title' => L10n::t('View all common friends'), + 'id' => 'common-loc-tab', + 'accesskey' => 'd' + ]; + } + + if (!empty($contact['uid'])) { + $tabs[] = ['label' => L10n::t('Advanced'), + 'url' => 'crepair/' . $contact['id'], + 'sel' => (($active_tab == 6) ? 'active' : ''), + 'title' => L10n::t('Advanced Contact Settings'), + 'id' => 'advanced-tab', + 'accesskey' => 'r' + ]; + } + + $tab_tpl = get_markup_template('common_tabs.tpl'); + $tab_str = replace_macros($tab_tpl, ['$tabs' => $tabs]); + + return $tab_str; + } + + private static function contact_conversations($a, $contact_id, $update) + { + $o = ''; + + if (!$update) { + // We need the editor here to be able to reshare an item. + if (local_user()) { + $x = [ + 'is_owner' => true, + 'allow_location' => $a->user['allow_location'], + 'default_location' => $a->user['default-location'], + 'nickname' => $a->user['nickname'], + 'lockstate' => (is_array($a->user) && (strlen($a->user['allow_cid']) || strlen($a->user['allow_gid']) || strlen($a->user['deny_cid']) || strlen($a->user['deny_gid'])) ? 'lock' : 'unlock'), + 'acl' => ACL::getFullSelectorHTML($a->user, true), + 'bang' => '', + 'visitor' => 'block', + 'profile_uid' => local_user(), + ]; + $o = status_editor($a, $x, 0, true); + } + } + + $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); + + if (!$update) { + $o .= self::contacts_tab($a, $contact, 1); + } + + if (DBA::isResult($contact)) { + $a->page['aside'] = ""; + + $profiledata = Contact::getDetailsByURL($contact["url"]); + + if (local_user()) { + if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { + $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]); + } + } + + Profile::load($a, "", 0, $profiledata, true); + $o .= Contact::getPostsFromUrl($contact["url"], true, $update); + } + + return $o; + } + + public static function contact_posts($a, $contact_id) + { + $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); + + $o = self::contacts_tab($a, $contact, 2); + + if (DBA::isResult($contact)) { + $a->page['aside'] = ""; + + $profiledata = Contact::getDetailsByURL($contact["url"]); + + if (local_user()) { + if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { + $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]); + } + } + + Profile::load($a, "", 0, $profiledata, true); + $o .= Contact::getPostsFromUrl($contact["url"]); + } + + return $o; + } + + public static function _contact_detail_for_template(array $rr) + { + $dir_icon = ''; + $alt_text = ''; + + switch ($rr['rel']) { + case Contact::FRIEND: + $dir_icon = 'images/lrarrow.gif'; + $alt_text = L10n::t('Mutual Friendship'); + break; + + case Contact::FOLLOWER; + $dir_icon = 'images/larrow.gif'; + $alt_text = L10n::t('is a fan of yours'); + break; + + case Contact::SHARING; + $dir_icon = 'images/rarrow.gif'; + $alt_text = L10n::t('you are a fan of'); + break; + + default: + break; + } + + $url = Contact::magicLink($rr['url']); + + if (strpos($url, 'redir/') === 0) { + $sparkle = ' class="sparkle" '; + } else { + $sparkle = ''; + } + + if ($rr['self']) { + $dir_icon = 'images/larrow.gif'; + $alt_text = L10n::t('This is you'); + $url = $rr['url']; + $sparkle = ''; + } + + return [ + 'img_hover' => L10n::t('Visit %s\'s profile [%s]', $rr['name'], $rr['url']), + 'edit_hover' => L10n::t('Edit contact'), + 'photo_menu' => Contact::photoMenu($rr), + 'id' => $rr['id'], + 'alt_text' => $alt_text, + 'dir_icon' => $dir_icon, + 'thumb' => ProxyUtils::proxifyUrl($rr['thumb'], false, ProxyUtils::SIZE_THUMB), + 'name' => htmlentities($rr['name']), + 'username' => htmlentities($rr['name']), + 'account_type' => Contact::getAccountType($rr), + 'sparkle' => $sparkle, + 'itemurl' => (($rr['addr'] != "") ? $rr['addr'] : $rr['url']), + 'url' => $url, + 'network' => ContactSelector::networkToName($rr['network'], $rr['url']), + 'nick' => htmlentities($rr['nick']), + ]; + } + + /** + * @brief Gives a array with actions which can performed to a given contact + * + * This includes actions like e.g. 'block', 'hide', 'archive', 'delete' and others + * + * @param array $contact Data about the Contact + * @return array with contact related actions + */ + private static function contact_actions($contact) + { + $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 + if ($contact['network'] === Protocol::DFRN) { + $contact_actions['suggest'] = [ + 'label' => L10n::t('Suggest friends'), + 'url' => 'fsuggest/' . $contact['id'], + 'title' => '', + 'sel' => '', + 'id' => 'suggest', + ]; + } + + if ($poll_enabled) { + $contact_actions['update'] = [ + 'label' => L10n::t('Update now'), + 'url' => 'contacts/' . $contact['id'] . '/update', + 'title' => '', + 'sel' => '', + 'id' => 'update', + ]; + } + + $contact_actions['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' : ''), + 'id' => 'toggle-block', + ]; + + $contact_actions['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' : ''), + 'id' => 'toggle-ignore', + ]; + + if ($contact['uid'] != 0) { + $contact_actions['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' : ''), + 'id' => 'toggle-archive', + ]; + + $contact_actions['delete'] = [ + 'label' => L10n::t('Delete'), + 'url' => 'contacts/' . $contact['id'] . '/drop', + 'title' => L10n::t('Delete contact'), + 'sel' => '', + 'id' => 'delete', + ]; + } + + return $contact_actions; + } + + +} \ No newline at end of file diff --git a/view/theme/frio/theme.php b/view/theme/frio/theme.php index 18fb98cc9d..fb9ac95cea 100644 --- a/view/theme/frio/theme.php +++ b/view/theme/frio/theme.php @@ -17,6 +17,7 @@ use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model\Profile; +use Friendica\Module\Contacts; $frio = 'view/theme/frio'; @@ -297,8 +298,6 @@ function frio_remote_nav($a, &$nav) */ function frio_acl_lookup(App $a, &$results) { - require_once 'mod/contacts.php'; - $nets = x($_GET, 'nets') ? notags(trim($_GET['nets'])) : ''; // we introduce a new search type, r should do the same query like it's @@ -334,7 +333,7 @@ function frio_acl_lookup(App $a, &$results) if (DBA::isResult($r)) { foreach ($r as $rr) { - $contacts[] = _contact_detail_for_template($rr); + $contacts[] = Contacts::_contact_detail_for_template($rr); } } From ba95487abf3f56edd0ea862fd7859303ceedab46 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Thu, 11 Oct 2018 23:41:27 +0200 Subject: [PATCH 352/428] Upate Contacts module file --- src/Module/Contacts.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Module/Contacts.php b/src/Module/Contacts.php index a017b55b1e..34cc18c3e9 100644 --- a/src/Module/Contacts.php +++ b/src/Module/Contacts.php @@ -25,9 +25,9 @@ use Friendica\Core\ACL; use Friendica\Module\Login; /** - * + * Manages and show Contacts and their content * - * + * @brief manages contacts */ class Contacts extends BaseModule { @@ -184,7 +184,7 @@ class Contacts extends BaseModule } if ($a->argv[1] === "batch") { - contacts_batch_actions($a); + self::contacts_batch_actions($a); return; } @@ -805,7 +805,7 @@ class Contacts extends BaseModule intval($_SESSION['uid']) ); if (DBA::isResult($r)) { - $a->set_pager_total($r[0]['total']); + $a->setPagerTotal($r[0]['total']); $total = $r[0]['total']; } @@ -980,7 +980,7 @@ class Contacts extends BaseModule return $o; } - public static function contact_posts($a, $contact_id) + private static function contact_posts($a, $contact_id) { $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); @@ -1134,5 +1134,4 @@ class Contacts extends BaseModule return $contact_actions; } - } \ No newline at end of file From 93ab82b7f02e9ea1c8fc072e7b3891d0e9f0d617 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Thu, 11 Oct 2018 23:45:01 +0200 Subject: [PATCH 353/428] Rename Contacts:content function --- mod/update_contacts.php | 2 +- src/Module/Contacts.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mod/update_contacts.php b/mod/update_contacts.php index 1ad5cd4a3b..33ba85055f 100644 --- a/mod/update_contacts.php +++ b/mod/update_contacts.php @@ -14,7 +14,7 @@ function update_contacts_content(App $a) echo "
    "; if ($_GET["force"] == 1) { - $text = Contacts::contacts_content($a, true); + $text = Contacts::content($a, true); } else { $text = ''; } diff --git a/src/Module/Contacts.php b/src/Module/Contacts.php index 34cc18c3e9..8d26b3eb5e 100644 --- a/src/Module/Contacts.php +++ b/src/Module/Contacts.php @@ -379,7 +379,7 @@ class Contacts extends BaseModule Contact::remove($orig_record['id']); } - public static function contacts_content($update = 0) + public static function content($update = 0) { $a = self::getApp(); $sort_type = 0; From 986528b77f25e24b6777f25ed4e5d7659b7ab6b7 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Fri, 12 Oct 2018 10:35:43 -0400 Subject: [PATCH 354/428] Revert "We now store the diaspora comment data as well" --- src/Protocol/ActivityPub/Processor.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 166530f472..5d2d7fe116 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -215,7 +215,6 @@ class Processor $item['tag'] = self::constructTagList($activity['tags'], $activity['sensitive']); $item['app'] = $activity['service']; $item['plink'] = defaults($activity, 'alternate-url', $item['uri']); - $item['diaspora_signed_text'] = defaults($activity, 'diaspora:comment', ''); $item = self::constructAttachList($activity['attachments'], $item); From 1b18be671523c8ea85ecab8e5e1c5025e91c53e0 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 12 Oct 2018 18:47:32 +0000 Subject: [PATCH 355/428] The virtuel fields for the diaspora signatures have to be removed at any time --- src/Model/Item.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index c0c67352e4..fe7757a46f 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1292,15 +1292,15 @@ class Item extends BaseObject if (x($item, 'dsprsig')) { $encoded_signature = $item['dsprsig']; $dsprsig = json_decode(base64_decode($item['dsprsig'])); - unset($item['dsprsig']); } + unset($item['dsprsig']); if (!empty($item['diaspora_signed_text'])) { $diaspora_signed_text = $item['diaspora_signed_text']; - unset($item['diaspora_signed_text']); } else { $diaspora_signed_text = ''; } + unset($item['diaspora_signed_text']); // Converting the plink /// @TODO Check if this is really still needed From 5af0ee1b9543e806ebec7e4583f9d98fa124f9b0 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 12 Oct 2018 18:53:13 +0000 Subject: [PATCH 356/428] We can now store it without any problem --- src/Protocol/ActivityPub/Processor.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 5d2d7fe116..166530f472 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -215,6 +215,7 @@ class Processor $item['tag'] = self::constructTagList($activity['tags'], $activity['sensitive']); $item['app'] = $activity['service']; $item['plink'] = defaults($activity, 'alternate-url', $item['uri']); + $item['diaspora_signed_text'] = defaults($activity, 'diaspora:comment', ''); $item = self::constructAttachList($activity['attachments'], $item); From 4d4dd1a99cce47d1f8cb3636ccf497222d00b6ff Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 12 Oct 2018 20:52:22 +0000 Subject: [PATCH 357/428] Some beautification --- src/Model/Item.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index fe7757a46f..ed80f4e9e8 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1289,18 +1289,17 @@ 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']); } - 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']; - } else { - $diaspora_signed_text = ''; + unset($item['diaspora_signed_text']); } - unset($item['diaspora_signed_text']); // Converting the plink /// @TODO Check if this is really still needed @@ -1488,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']; @@ -1534,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 @@ -1574,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; From b6f2144237a9f4d2366da6ae4c170a281c2c5dd5 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 13 Oct 2018 04:31:37 +0000 Subject: [PATCH 358/428] Avoid beeing flooded by invalid requests --- index.php | 4 ++++ mod/xrd.php | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/index.php b/index.php index 19b85b9356..faa86575eb 100644 --- a/index.php +++ b/index.php @@ -48,6 +48,10 @@ if ($a->isMaxProcessesReached() || $a->isMaxLoadReached()) { System::httpExit(503, ['title' => 'Error 503 - Service Temporarily Unavailable', 'description' => 'System is currently overloaded. Please try again later.']); } +if (strstr($a->query_string, '.well-known/host-meta') and ($a->query_string != '.well-known/host-meta')) { + System::httpExit(404); +} + if (!$a->getMode()->isInstall()) { if (Config::get('system', 'force_ssl') && ($a->get_scheme() == "http") && (intval(Config::get('system', 'ssl_policy')) == SSL_POLICY_FULL) diff --git a/mod/xrd.php b/mod/xrd.php index 6a5fdbbdb9..921d48fe93 100644 --- a/mod/xrd.php +++ b/mod/xrd.php @@ -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,7 +48,7 @@ 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']; From cdbddd0103d80e8ad935f21134f26e8c5872357a Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Sat, 13 Oct 2018 11:23:52 +0200 Subject: [PATCH 359/428] Renaming functions and class --- mod/allfriends.php | 23 +- mod/common.php | 31 +- mod/contacts.php | 1123 ------------------------------------- mod/crepair.php | 9 +- mod/dirfind.php | 24 +- mod/group.php | 15 +- src/Module/Contacts.php | 69 ++- view/theme/frio/theme.php | 2 +- 8 files changed, 84 insertions(+), 1212 deletions(-) delete mode 100644 mod/contacts.php diff --git a/mod/allfriends.php b/mod/allfriends.php index 190ab12a66..aa5fb0a679 100644 --- a/mod/allfriends.php +++ b/mod/allfriends.php @@ -8,11 +8,10 @@ use Friendica\Content\ContactSelector; use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Database\DBA; -use Friendica\Model\Contact; -use Friendica\Model\GContact; -use Friendica\Model\Profile; +use Friendica\Model;\ +use Friendica\Module\Contact; use Friendica\Util\Proxy as ProxyUtils; -use Friendica\Module\Contacts; + require_once 'include/dba.php'; @@ -42,13 +41,13 @@ function allfriends_content(App $a) } $a->page['aside'] = ""; - Profile::load($a, "", 0, Contact::getDetailsByURL($contact["url"])); + Model\Profile::load($a, "", 0, Model\Contact::getDetailsByURL($contact["url"])); - $total = GContact::countAllFriends(local_user(), $cid); + $total = Model\GContact::countAllFriends(local_user(), $cid); $a->setPagerTotal($total); - $r = GContact::allFriends(local_user(), $cid, $a->pager['start'], $a->pager['itemspage']); + $r = Model\GContact::allFriends(local_user(), $cid, $a->pager['start'], $a->pager['itemspage']); if (!DBA::isResult($r)) { $o .= L10n::t('No friends to display.'); return $o; @@ -59,7 +58,7 @@ function allfriends_content(App $a) $entries = []; foreach ($r as $rr) { //get further details of the contact - $contact_details = Contact::getDetailsByURL($rr['url'], $uid, $rr); + $contact_details = Model\Contact::getDetailsByURL($rr['url'], $uid, $rr); $photo_menu = ''; @@ -68,11 +67,11 @@ function allfriends_content(App $a) // If the contact is not common to the user, Connect/Follow' will be added to the photo menu if ($rr['cid']) { $rr['id'] = $rr['cid']; - $photo_menu = Contact::photoMenu($rr); + $photo_menu = Model\Contact::photoMenu($rr); } else { $connlnk = System::baseUrl() . '/follow/?url=' . $rr['url']; $photo_menu = [ - 'profile' => [L10n::t("View Profile"), Contact::magicLink($rr['url'])], + 'profile' => [L10n::t("View Profile"), Model\Contact::magicLink($rr['url'])], 'follow' => [L10n::t("Connect/Follow"), $connlnk] ]; } @@ -86,7 +85,7 @@ function allfriends_content(App $a) 'details' => $contact_details['location'], 'tags' => $contact_details['keywords'], 'about' => $contact_details['about'], - 'account_type' => Contact::getAccountType($contact_details), + 'account_type' => Model\Contact::getAccountType($contact_details), 'network' => ContactSelector::networkToName($contact_details['network'], $contact_details['url']), 'photo_menu' => $photo_menu, 'conntxt' => L10n::t('Connect'), @@ -96,7 +95,7 @@ function allfriends_content(App $a) $entries[] = $entry; } - $tab_str = Contacts::contacts_tab($a, $contact, 4); + $tab_str = Contact::getTabsHTML($a, $contact, 4); $tpl = get_markup_template('viewcontact_template.tpl'); diff --git a/mod/common.php b/mod/common.php index 13e5bf0927..c011c6d38a 100644 --- a/mod/common.php +++ b/mod/common.php @@ -7,11 +7,10 @@ use Friendica\App; use Friendica\Content\ContactSelector; use Friendica\Core\L10n; use Friendica\Database\DBA; -use Friendica\Model\Contact; -use Friendica\Model\GContact; -use Friendica\Model\Profile; +use Friendica\Model; +use Friendica\Module\Contact; use Friendica\Util\Proxy as ProxyUtils; -use Friendica\Module\Contacts; + require_once 'include/dba.php'; @@ -42,7 +41,7 @@ function common_content(App $a) if (DBA::isResult($contact)) { $a->page['aside'] = ""; - Profile::load($a, "", 0, Contact::getDetailsByURL($contact["url"])); + Model\Profile::load($a, "", 0,Model\Contact::getDetailsByURL($contact["url"])); } } else { $contact = DBA::selectFirst('contact', ['name', 'url', 'photo', 'uid', 'id'], ['self' => true, 'uid' => $uid]); @@ -65,12 +64,12 @@ function common_content(App $a) return; } - if (!$cid && Profile::getMyURL()) { - $contact = DBA::selectFirst('contact', ['id'], ['nurl' => normalise_link(Profile::getMyURL()), 'uid' => $uid]); + if (!$cid &&Model\Profile::getMyURL()) { + $contact = DBA::selectFirst('contact', ['id'], ['nurl' => normalise_link(Model\Profile::getMyURL()), 'uid' => $uid]); if (DBA::isResult($contact)) { $cid = $contact['id']; } else { - $gcontact = DBA::selectFirst('gcontact', ['id'], ['nurl' => normalise_link(Profile::getMyURL())]); + $gcontact = DBA::selectFirst('gcontact', ['id'], ['nurl' => normalise_link(Model\Profile::getMyURL())]); if (DBA::isResult($gcontact)) { $zcid = $gcontact['id']; } @@ -82,9 +81,9 @@ function common_content(App $a) } if ($cid) { - $t = GContact::countCommonFriends($uid, $cid); + $t =Model\GContact::countCommonFriends($uid, $cid); } else { - $t = GContact::countCommonFriendsZcid($uid, $zcid); + $t =Model\GContact::countCommonFriendsZcid($uid, $zcid); } if ($t > 0) { @@ -95,9 +94,9 @@ function common_content(App $a) } if ($cid) { - $r = GContact::commonFriends($uid, $cid, $a->pager['start'], $a->pager['itemspage']); + $r =Model\GContact::commonFriends($uid, $cid, $a->pager['start'], $a->pager['itemspage']); } else { - $r = GContact::commonFriendsZcid($uid, $zcid, $a->pager['start'], $a->pager['itemspage']); + $r =Model\GContact::commonFriendsZcid($uid, $zcid, $a->pager['start'], $a->pager['itemspage']); } if (!DBA::isResult($r)) { @@ -109,13 +108,13 @@ function common_content(App $a) $entries = []; foreach ($r as $rr) { //get further details of the contact - $contact_details = Contact::getDetailsByURL($rr['url'], $uid); + $contact_details =Model\Contact::getDetailsByURL($rr['url'], $uid); // $rr['id'] is needed to use contact_photo_menu() /// @TODO Adding '/" here avoids E_NOTICE on missing constants $rr['id'] = $rr['cid']; - $photo_menu = Contact::photoMenu($rr); + $photo_menu =Model\Contact::photoMenu($rr); $entry = [ 'url' => $rr['url'], @@ -126,7 +125,7 @@ function common_content(App $a) 'details' => $contact_details['location'], 'tags' => $contact_details['keywords'], 'about' => $contact_details['about'], - 'account_type' => Contact::getAccountType($contact_details), + 'account_type' =>Model\Contact::getAccountType($contact_details), 'network' => ContactSelector::networkToName($contact_details['network'], $contact_details['url']), 'photo_menu' => $photo_menu, 'id' => ++$id, @@ -137,7 +136,7 @@ function common_content(App $a) $title = ''; $tab_str = ''; if ($cmd === 'loc' && $cid && local_user() == $uid) { - $tab_str = Contacts::contacts_tab($a, $contact, 4); + $tab_str = Contact::getTabsHTML($a, $contact, 4); } else { $title = L10n::t('Common Friends'); } diff --git a/mod/contacts.php b/mod/contacts.php deleted file mode 100644 index 4e149ab74f..0000000000 --- a/mod/contacts.php +++ /dev/null @@ -1,1123 +0,0 @@ -page, 'aside')) { - $a->page['aside'] = ''; - } - - $contact_id = null; - $contact = null; - if ((($a->argc == 2) && intval($a->argv[1])) || (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations']))) { - $contact_id = intval($a->argv[1]); - $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); - - if (!DBA::isResult($contact)) { - $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => 0]); - } - - // Don't display contacts that are about to be deleted - if ($contact['network'] == Protocol::PHANTOM) { - $contact = false; - } - } - - if (DBA::isResult($contact)) { - if ($contact['self']) { - if (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations'])) { - goaway('profile/' . $contact['nick']); - } else { - goaway('profile/' . $contact['nick'] . '?tab=profile'); - } - } - - $a->data['contact'] = $contact; - - if (($a->data['contact']['network'] != "") && ($a->data['contact']['network'] != Protocol::DFRN)) { - $networkname = format_network_name($a->data['contact']['network'], $a->data['contact']['url']); - } else { - $networkname = ''; - } - - /// @TODO Add nice spaces - $vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"), [ - '$name' => htmlentities($a->data['contact']['name']), - '$photo' => $a->data['contact']['photo'], - '$url' => Contact::MagicLink($a->data['contact']['url']), - '$addr' => (($a->data['contact']['addr'] != "") ? ($a->data['contact']['addr']) : ""), - '$network_name' => $networkname, - '$network' => L10n::t('Network:'), - '$account_type' => Contact::getAccountType($a->data['contact']) - ]); - - $findpeople_widget = ''; - $follow_widget = ''; - $networks_widget = ''; - } else { - $vcard_widget = ''; - $networks_widget = Widget::networks('contacts', $nets); - if (isset($_GET['add'])) { - $follow_widget = Widget::follow($_GET['add']); - } else { - $follow_widget = Widget::follow(); - } - - $findpeople_widget = Widget::findPeople(); - } - - if ($contact['uid'] != 0) { - $groups_widget = Group::sidebarWidget('contacts', 'group', 'full', 'everyone', $contact_id); - } else { - $groups_widget = null; - } - - $a->page['aside'] .= replace_macros(get_markup_template("contacts-widget-sidebar.tpl"), [ - '$vcard_widget' => $vcard_widget, - '$findpeople_widget' => $findpeople_widget, - '$follow_widget' => $follow_widget, - '$groups_widget' => $groups_widget, - '$networks_widget' => $networks_widget - ]); - - $base = System::baseUrl(); - $tpl = get_markup_template("contacts-head.tpl"); - $a->page['htmlhead'] .= replace_macros($tpl, [ - '$baseurl' => System::baseUrl(true), - '$base' => $base - ]); -} - -function contacts_batch_actions(App $a) -{ - if (empty($_POST['contact_batch']) || !is_array($_POST['contact_batch'])) { - return; - } - - $contacts_id = $_POST['contact_batch']; - - $orig_records = q("SELECT * FROM `contact` WHERE `id` IN (%s) AND `uid` = %d AND `self` = 0", - implode(",", $contacts_id), - intval(local_user()) - ); - - $count_actions = 0; - foreach ($orig_records as $orig_record) { - $contact_id = $orig_record['id']; - if (x($_POST, 'contacts_batch_update')) { - _contact_update($contact_id); - $count_actions++; - } - if (x($_POST, 'contacts_batch_block')) { - _contact_block($contact_id); - $count_actions++; - } - if (x($_POST, 'contacts_batch_ignore')) { - _contact_ignore($contact_id); - $count_actions++; - } - if (x($_POST, 'contacts_batch_archive')) { - $r = _contact_archive($contact_id, $orig_record); - if ($r) { - $count_actions++; - } - } - if (x($_POST, 'contacts_batch_drop')) { - _contact_drop($orig_record); - $count_actions++; - } - } - if ($count_actions > 0) { - info(L10n::tt("%d contact edited.", "%d contacts edited.", $count_actions)); - } - - goaway('contacts'); -} - -function contacts_post(App $a) -{ - if (!local_user()) { - return; - } - - if ($a->argv[1] === "batch") { - contacts_batch_actions($a); - return; - } - - $contact_id = intval($a->argv[1]); - if (!$contact_id) { - return; - } - - if (!DBA::exists('contact', ['id' => $contact_id, 'uid' => local_user()])) { - notice(L10n::t('Could not access contact record.') . EOL); - goaway('contacts'); - return; // NOTREACHED - } - - Addon::callHooks('contact_edit_post', $_POST); - - $profile_id = intval(defaults($_POST, 'profile-assign', 0)); - if ($profile_id) { - if (!DBA::exists('profile', ['id' => $profile_id, 'uid' => local_user()])) { - notice(L10n::t('Could not locate selected profile.') . EOL); - return; - } - } - - $hidden = intval($_POST['hidden']); - - $notify = intval($_POST['notify']); - - $fetch_further_information = intval(defaults($_POST, 'fetch_further_information', 0)); - - $ffi_keyword_blacklist = escape_tags(trim(defaults($_POST, 'ffi_keyword_blacklist', ''))); - - $priority = intval(defaults($_POST, 'poll', 0)); - if ($priority > 5 || $priority < 0) { - $priority = 0; - } - - $info = escape_tags(trim($_POST['info'])); - - $r = q("UPDATE `contact` SET `profile-id` = %d, `priority` = %d , `info` = '%s', - `hidden` = %d, `notify_new_posts` = %d, `fetch_further_information` = %d, - `ffi_keyword_blacklist` = '%s' WHERE `id` = %d AND `uid` = %d", - intval($profile_id), - intval($priority), - DBA::escape($info), - intval($hidden), - intval($notify), - intval($fetch_further_information), - DBA::escape($ffi_keyword_blacklist), - intval($contact_id), - intval(local_user()) - ); - if (DBA::isResult($r)) { - info(L10n::t('Contact updated.') . EOL); - } else { - notice(L10n::t('Failed to update contact record.') . EOL); - } - - $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); - if (DBA::isResult($contact)) { - $a->data['contact'] = $contact; - } - - return; -} - -/* contact actions */ - -function _contact_update($contact_id) -{ - $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()]); - if (!DBA::isResult($contact)) { - return; - } - - $uid = $contact["uid"]; - - if ($contact["network"] == Protocol::OSTATUS) { - $result = Contact::createFromProbe($uid, $contact["url"], false, $contact["network"]); - - if ($result['success']) { - q("UPDATE `contact` SET `subhub` = 1 WHERE `id` = %d", intval($contact_id)); - } - } else { - // pull feed and consume it, which should subscribe to the hub. - Worker::add(PRIORITY_HIGH, "OnePoll", $contact_id, "force"); - } -} - -function _contact_update_profile($contact_id) -{ - $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()]); - if (!DBA::isResult($contact)) { - return; - } - - $uid = $contact["uid"]; - - $data = Probe::uri($contact["url"], "", 0, false); - - // "Feed" or "Unknown" is mostly a sign of communication problems - if ((in_array($data["network"], [Protocol::FEED, Protocol::PHANTOM])) && ($data["network"] != $contact["network"])) { - return; - } - - $updatefields = ["name", "nick", "url", "addr", "batch", "notify", "poll", "request", "confirm", - "poco", "network", "alias"]; - $update = []; - - if ($data["network"] == Protocol::OSTATUS) { - $result = Contact::createFromProbe($uid, $data["url"], false); - - if ($result['success']) { - $update["subhub"] = true; - } - } - - foreach ($updatefields AS $field) { - if (isset($data[$field]) && ($data[$field] != "")) { - $update[$field] = $data[$field]; - } - } - - $update["nurl"] = normalise_link($data["url"]); - - $query = ""; - - if (isset($data["priority"]) && ($data["priority"] != 0)) { - $query = "`priority` = " . intval($data["priority"]); - } - - foreach ($update AS $key => $value) { - if ($query != "") { - $query .= ", "; - } - - $query .= "`" . $key . "` = '" . DBA::escape($value) . "'"; - } - - if ($query == "") { - return; - } - - $r = q("UPDATE `contact` SET $query WHERE `id` = %d AND `uid` = %d", - intval($contact_id), - intval(local_user()) - ); - - // Update the entry in the contact table - Contact::updateAvatar($data['photo'], local_user(), $contact_id, true); - - // Update the entry in the gcontact table - GContact::updateFromProbe($data["url"]); -} - -function _contact_block($contact_id) -{ - $blocked = !Contact::isBlockedByUser($contact_id, local_user()); - Contact::setBlockedForUser($contact_id, local_user(), $blocked); -} - -function _contact_ignore($contact_id) -{ - $ignored = !Contact::isIgnoredByUser($contact_id, local_user()); - Contact::setIgnoredForUser($contact_id, local_user(), $ignored); -} - -function _contact_archive($contact_id, $orig_record) -{ - $archived = (($orig_record['archive']) ? 0 : 1); - $r = q("UPDATE `contact` SET `archive` = %d WHERE `id` = %d AND `uid` = %d", - intval($archived), - intval($contact_id), - intval(local_user()) - ); - return DBA::isResult($r); -} - -function _contact_drop($orig_record) -{ - $a = get_app(); - - $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` - WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1", - intval($a->user['uid']) - ); - if (!DBA::isResult($r)) { - return; - } - - Contact::terminateFriendship($r[0], $orig_record, true); - Contact::remove($orig_record['id']); -} - -function contacts_content(App $a, $update = 0) -{ - $sort_type = 0; - $o = ''; - Nav::setSelected('contacts'); - - if (!local_user()) { - notice(L10n::t('Permission denied.') . EOL); - return Login::form(); - } - - if ($a->argc == 3) { - $contact_id = intval($a->argv[1]); - if (!$contact_id) { - return; - } - - $cmd = $a->argv[2]; - - $orig_record = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => [0, local_user()], 'self' => false]); - if (!DBA::isResult($orig_record)) { - notice(L10n::t('Could not access contact record.') . EOL); - goaway('contacts'); - return; // NOTREACHED - } - - if ($cmd === 'update' && ($orig_record['uid'] != 0)) { - _contact_update($contact_id); - goaway('contacts/' . $contact_id); - // NOTREACHED - } - - if ($cmd === 'updateprofile' && ($orig_record['uid'] != 0)) { - _contact_update_profile($contact_id); - goaway('crepair/' . $contact_id); - // NOTREACHED - } - - if ($cmd === 'block') { - _contact_block($contact_id); - - $blocked = Contact::isBlockedByUser($contact_id, local_user()); - info(($blocked ? L10n::t('Contact has been blocked') : L10n::t('Contact has been unblocked')) . EOL); - - goaway('contacts/' . $contact_id); - return; // NOTREACHED - } - - if ($cmd === 'ignore') { - _contact_ignore($contact_id); - - $ignored = Contact::isIgnoredByUser($contact_id, local_user()); - info(($ignored ? L10n::t('Contact has been ignored') : L10n::t('Contact has been unignored')) . EOL); - - goaway('contacts/' . $contact_id); - return; // NOTREACHED - } - - if ($cmd === 'archive' && ($orig_record['uid'] != 0)) { - $r = _contact_archive($contact_id, $orig_record); - if ($r) { - $archived = (($orig_record['archive']) ? 0 : 1); - info((($archived) ? L10n::t('Contact has been archived') : L10n::t('Contact has been unarchived')) . EOL); - } - - goaway('contacts/' . $contact_id); - return; // NOTREACHED - } - - if ($cmd === 'drop' && ($orig_record['uid'] != 0)) { - // Check if we should do HTML-based delete confirmation - if (x($_REQUEST, 'confirm')) { - // can't take arguments in its "action" parameter - // so add any arguments as hidden inputs - $query = explode_querystring($a->query_string); - $inputs = []; - foreach ($query['args'] as $arg) { - if (strpos($arg, 'confirm=') === false) { - $arg_parts = explode('=', $arg); - $inputs[] = ['name' => $arg_parts[0], 'value' => $arg_parts[1]]; - } - } - - $a->page['aside'] = ''; - - return replace_macros(get_markup_template('contact_drop_confirm.tpl'), [ - '$header' => L10n::t('Drop contact'), - '$contact' => _contact_detail_for_template($orig_record), - '$method' => 'get', - '$message' => L10n::t('Do you really want to delete this contact?'), - '$extra_inputs' => $inputs, - '$confirm' => L10n::t('Yes'), - '$confirm_url' => $query['base'], - '$confirm_name' => 'confirmed', - '$cancel' => L10n::t('Cancel'), - ]); - } - // Now check how the user responded to the confirmation query - if (x($_REQUEST, 'canceled')) { - goaway('contacts'); - } - - _contact_drop($orig_record); - info(L10n::t('Contact has been removed.') . EOL); - - goaway('contacts'); - return; // NOTREACHED - } - if ($cmd === 'posts') { - return contact_posts($a, $contact_id); - } - if ($cmd === 'conversations') { - return contact_conversations($a, $contact_id, $update); - } - } - - $_SESSION['return_url'] = $a->query_string; - - if ((x($a->data, 'contact')) && (is_array($a->data['contact']))) { - $contact_id = $a->data['contact']['id']; - $contact = $a->data['contact']; - - $a->page['htmlhead'] .= replace_macros(get_markup_template('contact_head.tpl'), [ - '$baseurl' => System::baseUrl(true), - ]); - - $contact['blocked'] = Contact::isBlockedByUser($contact['id'], local_user()); - $contact['readonly'] = Contact::isIgnoredByUser($contact['id'], local_user()); - - $dir_icon = ''; - $relation_text = ''; - switch ($contact['rel']) { - case Contact::FRIEND: - $dir_icon = 'images/lrarrow.gif'; - $relation_text = L10n::t('You are mutual friends with %s'); - break; - - case Contact::FOLLOWER; - $dir_icon = 'images/larrow.gif'; - $relation_text = L10n::t('You are sharing with %s'); - break; - - case Contact::SHARING; - $dir_icon = 'images/rarrow.gif'; - $relation_text = L10n::t('%s is sharing with you'); - break; - - default: - break; - } - - if ($contact['uid'] == 0) { - $relation_text = ''; - } - - if (!in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])) { - $relation_text = ""; - } - - $relation_text = sprintf($relation_text, htmlentities($contact['name'])); - - $url = Contact::magicLink($contact['url']); - if (strpos($url, 'redir/') === 0) { - $sparkle = ' class="sparkle" '; - } else { - $sparkle = ''; - } - - $insecure = L10n::t('Private communications are not available for this contact.'); - - $last_update = (($contact['last-update'] <= NULL_DATE) ? L10n::t('Never') : DateTimeFormat::local($contact['last-update'], 'D, j M Y, g:i A')); - - if ($contact['last-update'] > NULL_DATE) { - $last_update .= ' ' . (($contact['last-update'] <= $contact['success_update']) ? L10n::t("\x28Update was successful\x29") : L10n::t("\x28Update was not successful\x29")); - } - $lblsuggest = (($contact['network'] === Protocol::DFRN) ? L10n::t('Suggest friends') : ''); - - $poll_enabled = in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]); - - $nettype = L10n::t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact["url"])); - - // tabs - $tab_str = contacts_tab($a, $contact, 3); - - $lost_contact = (($contact['archive'] && $contact['term-date'] > NULL_DATE && $contact['term-date'] < DateTimeFormat::utcNow()) ? L10n::t('Communications lost with this contact!') : ''); - - $fetch_further_information = null; - if ($contact['network'] == Protocol::FEED) { - $fetch_further_information = [ - 'fetch_further_information', - L10n::t('Fetch further information for feeds'), - $contact['fetch_further_information'], - L10n::t("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."), - ['0' => L10n::t('Disabled'), - '1' => L10n::t('Fetch information'), - '3' => L10n::t('Fetch keywords'), - '2' => L10n::t('Fetch information and keywords') - ] - ]; - } - - $poll_interval = null; - if (in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) { - $poll_interval = ContactSelector::pollInterval($contact['priority'], (!$poll_enabled)); - } - - $profile_select = null; - if ($contact['network'] == Protocol::DFRN) { - $profile_select = ContactSelector::profileAssign($contact['profile-id'], (($contact['network'] !== Protocol::DFRN) ? true : false)); - } - - /// @todo Only show the following link with DFRN when the remote version supports it - $follow = ''; - $follow_text = ''; - if (in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) { - if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { - $follow = System::baseUrl(true) . "/unfollow?url=" . urlencode($contact["url"]); - $follow_text = L10n::t("Disconnect/Unfollow"); - } - } else { - $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]); - $follow_text = L10n::t("Connect/Follow"); - } - - // Load contactact related actions like hide, suggest, delete and others - $contact_actions = contact_actions($contact); - - if ($contact['uid'] != 0) { - $lbl_vis1 = L10n::t('Profile Visibility'); - $lbl_info1 = L10n::t('Contact Information / Notes'); - $contact_settings_label = L10n::t('Contact Settings'); - } else { - $lbl_vis1 = null; - $lbl_info1 = null; - $contact_settings_label = null; - } - - $tpl = get_markup_template("contact_edit.tpl"); - $o .= replace_macros($tpl, [ - '$header' => L10n::t("Contact"), - '$tab_str' => $tab_str, - '$submit' => L10n::t('Submit'), - '$lbl_vis1' => $lbl_vis1, - '$lbl_vis2' => L10n::t('Please choose the profile you would like to display to %s when viewing your profile securely.', $contact['name']), - '$lbl_info1' => $lbl_info1, - '$lbl_info2' => L10n::t('Their personal note'), - '$reason' => trim(notags($contact['reason'])), - '$infedit' => L10n::t('Edit contact notes'), - '$common_link' => 'common/loc/' . local_user() . '/' . $contact['id'], - '$relation_text' => $relation_text, - '$visit' => L10n::t('Visit %s\'s profile [%s]', $contact['name'], $contact['url']), - '$blockunblock' => L10n::t('Block/Unblock contact'), - '$ignorecont' => L10n::t('Ignore contact'), - '$lblcrepair' => L10n::t("Repair URL settings"), - '$lblrecent' => L10n::t('View conversations'), - '$lblsuggest' => $lblsuggest, - '$nettype' => $nettype, - '$poll_interval' => $poll_interval, - '$poll_enabled' => $poll_enabled, - '$lastupdtext' => L10n::t('Last update:'), - '$lost_contact' => $lost_contact, - '$updpub' => L10n::t('Update public posts'), - '$last_update' => $last_update, - '$udnow' => L10n::t('Update now'), - '$follow' => $follow, - '$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' => (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') : ''), - '$hidden' => ['hidden', L10n::t('Hide this contact from others'), ($contact['hidden'] == 1), L10n::t('Replies/likes to your public posts may 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, - '$ffi_keyword_blacklist' => $contact['ffi_keyword_blacklist'], - '$ffi_keyword_blacklist' => ['ffi_keyword_blacklist', L10n::t('Blacklisted keywords'), $contact['ffi_keyword_blacklist'], L10n::t('Comma separated list of keywords that should not be converted to hashtags, when "Fetch information and keywords" is selected')], - '$photo' => $contact['photo'], - '$name' => htmlentities($contact['name']), - '$dir_icon' => $dir_icon, - '$sparkle' => $sparkle, - '$url' => $url, - '$profileurllabel' => L10n::t('Profile URL'), - '$profileurl' => $contact['url'], - '$account_type' => Contact::getAccountType($contact), - '$location' => BBCode::convert($contact["location"]), - '$location_label' => L10n::t("Location:"), - '$xmpp' => BBCode::convert($contact["xmpp"]), - '$xmpp_label' => L10n::t("XMPP:"), - '$about' => BBCode::convert($contact["about"], false), - '$about_label' => L10n::t("About:"), - '$keywords' => $contact["keywords"], - '$keywords_label' => L10n::t("Tags:"), - '$contact_action_button' => L10n::t("Actions"), - '$contact_actions' => $contact_actions, - '$contact_status' => L10n::t("Status"), - '$contact_settings_label' => $contact_settings_label, - '$contact_profile_label' => L10n::t("Profile"), - ]); - - $arr = ['contact' => $contact, 'output' => $o]; - - Addon::callHooks('contact_edit', $arr); - - return $arr['output']; - } - - $blocked = false; - $hidden = false; - $ignored = false; - $archived = false; - $all = false; - - if (($a->argc == 2) && ($a->argv[1] === 'all')) { - $sql_extra = ''; - $all = true; - } elseif (($a->argc == 2) && ($a->argv[1] === 'blocked')) { - $sql_extra = " AND `blocked` = 1 "; - $blocked = true; - } elseif (($a->argc == 2) && ($a->argv[1] === 'hidden')) { - $sql_extra = " AND `hidden` = 1 "; - $hidden = true; - } elseif (($a->argc == 2) && ($a->argv[1] === 'ignored')) { - $sql_extra = " AND `readonly` = 1 "; - $ignored = true; - } elseif (($a->argc == 2) && ($a->argv[1] === 'archived')) { - $sql_extra = " AND `archive` = 1 "; - $archived = true; - } else { - $sql_extra = " AND `blocked` = 0 "; - } - - $sql_extra .= sprintf(" AND `network` != '%s' ", Protocol::PHANTOM); - - $search = x($_GET, 'search') ? notags(trim($_GET['search'])) : ''; - $nets = x($_GET, 'nets' ) ? notags(trim($_GET['nets'])) : ''; - - $tabs = [ - [ - 'label' => L10n::t('Suggestions'), - 'url' => 'suggest', - 'sel' => '', - 'title' => L10n::t('Suggest potential friends'), - 'id' => 'suggestions-tab', - 'accesskey' => 'g', - ], - [ - 'label' => L10n::t('All Contacts'), - 'url' => 'contacts/all', - 'sel' => ($all) ? 'active' : '', - 'title' => L10n::t('Show all contacts'), - 'id' => 'showall-tab', - 'accesskey' => 'l', - ], - [ - 'label' => L10n::t('Unblocked'), - 'url' => 'contacts', - 'sel' => ((!$all) && (!$blocked) && (!$hidden) && (!$search) && (!$nets) && (!$ignored) && (!$archived)) ? 'active' : '', - 'title' => L10n::t('Only show unblocked contacts'), - 'id' => 'showunblocked-tab', - 'accesskey' => 'o', - ], - [ - 'label' => L10n::t('Blocked'), - 'url' => 'contacts/blocked', - 'sel' => ($blocked) ? 'active' : '', - 'title' => L10n::t('Only show blocked contacts'), - 'id' => 'showblocked-tab', - 'accesskey' => 'b', - ], - [ - 'label' => L10n::t('Ignored'), - 'url' => 'contacts/ignored', - 'sel' => ($ignored) ? 'active' : '', - 'title' => L10n::t('Only show ignored contacts'), - 'id' => 'showignored-tab', - 'accesskey' => 'i', - ], - [ - 'label' => L10n::t('Archived'), - 'url' => 'contacts/archived', - 'sel' => ($archived) ? 'active' : '', - 'title' => L10n::t('Only show archived contacts'), - 'id' => 'showarchived-tab', - 'accesskey' => 'y', - ], - [ - 'label' => L10n::t('Hidden'), - 'url' => 'contacts/hidden', - 'sel' => ($hidden) ? 'active' : '', - 'title' => L10n::t('Only show hidden contacts'), - 'id' => 'showhidden-tab', - 'accesskey' => 'h', - ], - ]; - - $tab_tpl = get_markup_template('common_tabs.tpl'); - $t = replace_macros($tab_tpl, ['$tabs' => $tabs]); - - $total = 0; - $searching = false; - $search_hdr = null; - if ($search) { - $searching = true; - $search_hdr = $search; - $search_txt = DBA::escape(protect_sprintf(preg_quote($search))); - $sql_extra .= " AND (name REGEXP '$search_txt' OR url REGEXP '$search_txt' OR nick REGEXP '$search_txt') "; - } - - if ($nets) { - $sql_extra .= sprintf(" AND network = '%s' ", DBA::escape($nets)); - } - - $sql_extra2 = ((($sort_type > 0) && ($sort_type <= Contact::FRIEND)) ? sprintf(" AND `rel` = %d ", intval($sort_type)) : ''); - - $r = q("SELECT COUNT(*) AS `total` FROM `contact` - WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 ", - intval($_SESSION['uid']) - ); - if (DBA::isResult($r)) { - $a->setPagerTotal($r[0]['total']); - $total = $r[0]['total']; - } - - $sql_extra3 = Widget::unavailableNetworks(); - - $contacts = []; - - $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 $sql_extra3 ORDER BY `name` ASC LIMIT %d , %d ", - intval($_SESSION['uid']), - intval($a->pager['start']), - intval($a->pager['itemspage']) - ); - if (DBA::isResult($r)) { - foreach ($r as $rr) { - $rr['blocked'] = Contact::isBlockedByUser($rr['id'], local_user()); - $rr['readonly'] = Contact::isIgnoredByUser($rr['id'], local_user()); - $contacts[] = _contact_detail_for_template($rr); - } - } - - $tpl = get_markup_template("contacts-template.tpl"); - $o .= replace_macros($tpl, [ - '$baseurl' => System::baseUrl(), - '$header' => L10n::t('Contacts') . (($nets) ? ' - ' . ContactSelector::networkToName($nets) : ''), - '$tabs' => $t, - '$total' => $total, - '$search' => $search_hdr, - '$desc' => L10n::t('Search your contacts'), - '$finding' => $searching ? L10n::t('Results for: %s', $search) : "", - '$submit' => L10n::t('Find'), - '$cmd' => $a->cmd, - '$contacts' => $contacts, - '$contact_drop_confirm' => L10n::t('Do you really want to delete this contact?'), - 'multiselect' => 1, - '$batch_actions' => [ - 'contacts_batch_update' => L10n::t('Update'), - 'contacts_batch_block' => L10n::t('Block') . "/" . L10n::t("Unblock"), - "contacts_batch_ignore" => L10n::t('Ignore') . "/" . L10n::t("Unignore"), - "contacts_batch_archive" => L10n::t('Archive') . "/" . L10n::t("Unarchive"), - "contacts_batch_drop" => L10n::t('Delete'), - ], - '$h_batch_actions' => L10n::t('Batch Actions'), - '$paginate' => paginate($a), - ]); - - return $o; -} - -/** - * @brief List of pages for the Contact TabBar - * - * Available Pages are 'Status', 'Profile', 'Contacts' and 'Common Friends' - * - * @param App $a - * @param array $contact The contact array - * @param int $active_tab 1 if tab should be marked as active - * - * @return string - */ -function contacts_tab($a, $contact, $active_tab) -{ - // tabs - $tabs = [ - [ - 'label' => L10n::t('Status'), - 'url' => "contacts/" . $contact['id'] . "/conversations", - 'sel' => (($active_tab == 1) ? 'active' : ''), - 'title' => L10n::t('Conversations started by this contact'), - 'id' => 'status-tab', - 'accesskey' => 'm', - ], - [ - 'label' => L10n::t('Posts and Comments'), - 'url' => "contacts/" . $contact['id'] . "/posts", - 'sel' => (($active_tab == 2) ? 'active' : ''), - 'title' => L10n::t('Status Messages and Posts'), - 'id' => 'posts-tab', - 'accesskey' => 'p', - ], - [ - 'label' => L10n::t('Profile'), - 'url' => "contacts/" . $contact['id'], - 'sel' => (($active_tab == 3) ? 'active' : ''), - 'title' => L10n::t('Profile Details'), - 'id' => 'profile-tab', - 'accesskey' => 'o', - ] - ]; - - // Show this tab only if there is visible friend list - $x = GContact::countAllFriends(local_user(), $contact['id']); - if ($x) { - $tabs[] = ['label' => L10n::t('Contacts'), - 'url' => "allfriends/" . $contact['id'], - 'sel' => (($active_tab == 4) ? 'active' : ''), - 'title' => L10n::t('View all contacts'), - 'id' => 'allfriends-tab', - 'accesskey' => 't']; - } - - // Show this tab only if there is visible common friend list - $common = GContact::countCommonFriends(local_user(), $contact['id']); - if ($common) { - $tabs[] = ['label' => L10n::t('Common Friends'), - 'url' => "common/loc/" . local_user() . "/" . $contact['id'], - 'sel' => (($active_tab == 5) ? 'active' : ''), - 'title' => L10n::t('View all common friends'), - 'id' => 'common-loc-tab', - 'accesskey' => 'd' - ]; - } - - if (!empty($contact['uid'])) { - $tabs[] = ['label' => L10n::t('Advanced'), - 'url' => 'crepair/' . $contact['id'], - 'sel' => (($active_tab == 6) ? 'active' : ''), - 'title' => L10n::t('Advanced Contact Settings'), - 'id' => 'advanced-tab', - 'accesskey' => 'r' - ]; - } - - $tab_tpl = get_markup_template('common_tabs.tpl'); - $tab_str = replace_macros($tab_tpl, ['$tabs' => $tabs]); - - return $tab_str; -} - -function contact_conversations(App $a, $contact_id, $update) -{ - $o = ''; - - if (!$update) { - // We need the editor here to be able to reshare an item. - if (local_user()) { - $x = [ - 'is_owner' => true, - 'allow_location' => $a->user['allow_location'], - 'default_location' => $a->user['default-location'], - 'nickname' => $a->user['nickname'], - 'lockstate' => (is_array($a->user) && (strlen($a->user['allow_cid']) || strlen($a->user['allow_gid']) || strlen($a->user['deny_cid']) || strlen($a->user['deny_gid'])) ? 'lock' : 'unlock'), - 'acl' => ACL::getFullSelectorHTML($a->user, true), - 'bang' => '', - 'visitor' => 'block', - 'profile_uid' => local_user(), - ]; - $o = status_editor($a, $x, 0, true); - } - } - - $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); - - if (!$update) { - $o .= contacts_tab($a, $contact, 1); - } - - if (DBA::isResult($contact)) { - $a->page['aside'] = ""; - - $profiledata = Contact::getDetailsByURL($contact["url"]); - - if (local_user()) { - if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { - $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]); - } - } - - Profile::load($a, "", 0, $profiledata, true); - $o .= Contact::getPostsFromUrl($contact["url"], true, $update); - } - - return $o; -} - -function contact_posts(App $a, $contact_id) -{ - $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); - - $o = contacts_tab($a, $contact, 2); - - if (DBA::isResult($contact)) { - $a->page['aside'] = ""; - - $profiledata = Contact::getDetailsByURL($contact["url"]); - - if (local_user()) { - if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { - $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]); - } - } - - Profile::load($a, "", 0, $profiledata, true); - $o .= Contact::getPostsFromUrl($contact["url"]); - } - - return $o; -} - -function _contact_detail_for_template(array $rr) -{ - $dir_icon = ''; - $alt_text = ''; - - switch ($rr['rel']) { - case Contact::FRIEND: - $dir_icon = 'images/lrarrow.gif'; - $alt_text = L10n::t('Mutual Friendship'); - break; - - case Contact::FOLLOWER; - $dir_icon = 'images/larrow.gif'; - $alt_text = L10n::t('is a fan of yours'); - break; - - case Contact::SHARING; - $dir_icon = 'images/rarrow.gif'; - $alt_text = L10n::t('you are a fan of'); - break; - - default: - break; - } - - $url = Contact::magicLink($rr['url']); - - if (strpos($url, 'redir/') === 0) { - $sparkle = ' class="sparkle" '; - } else { - $sparkle = ''; - } - - if ($rr['self']) { - $dir_icon = 'images/larrow.gif'; - $alt_text = L10n::t('This is you'); - $url = $rr['url']; - $sparkle = ''; - } - - return [ - 'img_hover' => L10n::t('Visit %s\'s profile [%s]', $rr['name'], $rr['url']), - 'edit_hover' => L10n::t('Edit contact'), - 'photo_menu' => Contact::photoMenu($rr), - 'id' => $rr['id'], - 'alt_text' => $alt_text, - 'dir_icon' => $dir_icon, - 'thumb' => ProxyUtils::proxifyUrl($rr['thumb'], false, ProxyUtils::SIZE_THUMB), - 'name' => htmlentities($rr['name']), - 'username' => htmlentities($rr['name']), - 'account_type' => Contact::getAccountType($rr), - 'sparkle' => $sparkle, - 'itemurl' => (($rr['addr'] != "") ? $rr['addr'] : $rr['url']), - 'url' => $url, - 'network' => ContactSelector::networkToName($rr['network'], $rr['url']), - 'nick' => htmlentities($rr['nick']), - ]; -} - -/** - * @brief Gives a array with actions which can performed to a given contact - * - * This includes actions like e.g. 'block', 'hide', 'archive', 'delete' and others - * - * @param array $contact Data about the Contact - * @return array with contact related actions - */ -function contact_actions($contact) -{ - $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 - if ($contact['network'] === Protocol::DFRN) { - $contact_actions['suggest'] = [ - 'label' => L10n::t('Suggest friends'), - 'url' => 'fsuggest/' . $contact['id'], - 'title' => '', - 'sel' => '', - 'id' => 'suggest', - ]; - } - - if ($poll_enabled) { - $contact_actions['update'] = [ - 'label' => L10n::t('Update now'), - 'url' => 'contacts/' . $contact['id'] . '/update', - 'title' => '', - 'sel' => '', - 'id' => 'update', - ]; - } - - $contact_actions['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' : ''), - 'id' => 'toggle-block', - ]; - - $contact_actions['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' : ''), - 'id' => 'toggle-ignore', - ]; - - if ($contact['uid'] != 0) { - $contact_actions['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' : ''), - 'id' => 'toggle-archive', - ]; - - $contact_actions['delete'] = [ - 'label' => L10n::t('Delete'), - 'url' => 'contacts/' . $contact['id'] . '/drop', - 'title' => L10n::t('Delete contact'), - 'sel' => '', - 'id' => 'delete', - ]; - } - - return $contact_actions; -} diff --git a/mod/crepair.php b/mod/crepair.php index 99aee13578..e5fb1e3347 100644 --- a/mod/crepair.php +++ b/mod/crepair.php @@ -8,9 +8,8 @@ use Friendica\Core\Config; use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Database\DBA; -use Friendica\Model\Contact; -use Friendica\Model\Profile; -use Friendica\Module\Contacts; +use Friendica\Model; +use Friendica\Module\Contact; require_once 'mod/contacts.php'; @@ -83,7 +82,7 @@ function crepair_post(App $a) if ($photo) { logger('mod-crepair: updating photo from ' . $photo); - Contact::updateAvatar($photo, local_user(), $contact['id']); + Model\Contact::updateAvatar($photo, local_user(), $contact['id']); } if ($r) { @@ -136,7 +135,7 @@ function crepair_content(App $a) $update_profile = in_array($contact['network'], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]); - $tab_str = Contacts::contacts_tab($a, $contact, 5); + $tab_str = Contact::getTabsHTML($a, $contact, 5); $tpl = get_markup_template('crepair.tpl'); $o = replace_macros($tpl, [ diff --git a/mod/dirfind.php b/mod/dirfind.php index e183e6c029..8fcf98d402 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -12,13 +12,13 @@ use Friendica\Core\Protocol; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBA; -use Friendica\Model\Contact; -use Friendica\Model\GContact; +use Friendica\Model; +use Friendica\Module\Contact; use Friendica\Network\Probe; use Friendica\Protocol\PortableContact; use Friendica\Util\Network; use Friendica\Util\Proxy as ProxyUtils; -use Friendica\Module\Contacts; + function dirfind_init(App $a) { @@ -82,7 +82,7 @@ function dirfind_content(App $a, $prefix = "") { $objresult->tags = ""; $objresult->network = $user_data["network"]; - $contact = Contact::getDetailsByURL($user_data["url"], local_user()); + $contact = Model\Contact::getDetailsByURL($user_data["url"], local_user()); $objresult->cid = $contact["cid"]; $objresult->pcid = $contact["zid"]; @@ -90,7 +90,7 @@ function dirfind_content(App $a, $prefix = "") { // Add the contact to the global contacts if it isn't already in our system if (($contact["cid"] == 0) && ($contact["zid"] == 0) && ($contact["gid"] == 0)) { - GContact::update($user_data); + Model\GContact::update($user_data); } } elseif ($local) { @@ -155,7 +155,7 @@ function dirfind_content(App $a, $prefix = "") { continue; } - $result = Contact::getDetailsByURL($result["nurl"], local_user()); + $result = Model\Contact::getDetailsByURL($result["nurl"], local_user()); if ($result["name"] == "") { $result["name"] = end(explode("/", $urlparts["path"])); @@ -199,7 +199,7 @@ function dirfind_content(App $a, $prefix = "") { $alt_text = ""; - $contact_details = Contact::getDetailsByURL($jj->url, local_user()); + $contact_details = Model\Contact::getDetailsByURL($jj->url, local_user()); $itemurl = (($contact_details["addr"] != "") ? $contact_details["addr"] : $jj->url); @@ -209,8 +209,8 @@ function dirfind_content(App $a, $prefix = "") { $conntxt = ""; $contact = DBA::selectFirst('contact', [], ['id' => $jj->cid]); if (DBA::isResult($contact)) { - $photo_menu = Contact::photoMenu($contact); - $details = Contacts::_contact_detail_for_template($contact); + $photo_menu =Model\Contact::photoMenu($contact); + $details = Contact::getContactTemplateVars($contact); $alt_text = $details['alt_text']; } else { $photo_menu = []; @@ -221,7 +221,7 @@ function dirfind_content(App $a, $prefix = "") { $contact = DBA::selectFirst('contact', [], ['id' => $jj->pcid]); if (DBA::isResult($contact)) { - $photo_menu = Contact::photoMenu($contact); + $photo_menu = Model\Contact::photoMenu($contact); } else { $photo_menu = []; } @@ -234,7 +234,7 @@ function dirfind_content(App $a, $prefix = "") { $entry = [ 'alt_text' => $alt_text, - 'url' => Contact::magicLink($jj->url), + 'url' => Model\Contact::magicLink($jj->url), 'itemurl' => $itemurl, 'name' => htmlentities($jj->name), 'thumb' => ProxyUtils::proxifyUrl($jj->photo, false, ProxyUtils::SIZE_THUMB), @@ -245,7 +245,7 @@ function dirfind_content(App $a, $prefix = "") { 'details' => $contact_details['location'], 'tags' => $contact_details['keywords'], 'about' => $contact_details['about'], - 'account_type' => Contact::getAccountType($contact_details), + 'account_type' => Model\Contact::getAccountType($contact_details), 'network' => ContactSelector::networkToName($jj->network, $jj->url), 'id' => ++$id, ]; diff --git a/mod/group.php b/mod/group.php index cfcbca4e47..ec4ee4da2b 100644 --- a/mod/group.php +++ b/mod/group.php @@ -11,9 +11,8 @@ use Friendica\Core\L10n; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBA; -use Friendica\Model\Contact; -use Friendica\Model\Group; -use Friendica\Module\Contacts; +use Friendica\Model; +use Friendica\Module\Contact; function group_init(App $a) { if (local_user()) { @@ -186,7 +185,7 @@ function group_content(App $a) { } $group = $r[0]; - $members = Contact::getByGroupId($group['id']); + $members = Model\Contact::getByGroupId($group['id']); $preselected = []; $entry = []; $id = 0; @@ -204,7 +203,7 @@ function group_content(App $a) { Group::addMember($group['id'], $change); } - $members = Contact::getByGroupId($group['id']); + $members = Model\Contact::getByGroupId($group['id']); $preselected = []; if (count($members)) { foreach ($members as $member) { @@ -250,7 +249,7 @@ function group_content(App $a) { // Format the data of the group members foreach ($members as $member) { if ($member['url']) { - $entry = Contacts::_contact_detail_for_template($member); + $entry = Contact::getContactTemplateVars($member); $entry['label'] = 'members'; $entry['photo_menu'] = ''; $entry['change_member'] = [ @@ -267,7 +266,7 @@ function group_content(App $a) { } if ($nogroup) { - $r = Contact::getUngroupedList(local_user()); + $r = Model\Contact::getUngroupedList(local_user()); } else { $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND NOT `blocked` AND NOT `pending` AND NOT `self` ORDER BY `name` ASC", intval(local_user()) @@ -279,7 +278,7 @@ function group_content(App $a) { // Format the data of the contacts who aren't in the contact group foreach ($r as $member) { if (!in_array($member['id'], $preselected)) { - $entry = Contacts::_contact_detail_for_template($member); + $entry = Contact::getContactTemplateVars($member); $entry['label'] = 'contacts'; if (!$nogroup) $entry['photo_menu'] = []; diff --git a/src/Module/Contacts.php b/src/Module/Contacts.php index 8d26b3eb5e..eb21b3b3e1 100644 --- a/src/Module/Contacts.php +++ b/src/Module/Contacts.php @@ -29,7 +29,7 @@ use Friendica\Module\Login; * * @brief manages contacts */ -class Contacts extends BaseModule +class Contact extends BaseModule { public static function init() { @@ -129,7 +129,7 @@ class Contacts extends BaseModule ]); } - private static function contacts_batch_actions(App $a) + private static function batchActions(App $a) { if (empty($_POST['contact_batch']) || !is_array($_POST['contact_batch'])) { return; @@ -146,25 +146,25 @@ class Contacts extends BaseModule foreach ($orig_records as $orig_record) { $contact_id = $orig_record['id']; if (x($_POST, 'contacts_batch_update')) { - self::_contact_update($contact_id); + self::updateContactFromPoll($contact_id); $count_actions++; } if (x($_POST, 'contacts_batch_block')) { - self::_contact_block($contact_id); + self::blockContact($contact_id); $count_actions++; } if (x($_POST, 'contacts_batch_ignore')) { - self::_contact_ignore($contact_id); + self::ignoreContact($contact_id); $count_actions++; } if (x($_POST, 'contacts_batch_archive')) { - $r = self::_contact_archive($contact_id, $orig_record); + $r = self::archiveContact($contact_id, $orig_record); if ($r) { $count_actions++; } } if (x($_POST, 'contacts_batch_drop')) { - self::_contact_drop($orig_record); + self::dropContact($orig_record); $count_actions++; } } @@ -184,7 +184,7 @@ class Contacts extends BaseModule } if ($a->argv[1] === "batch") { - self::contacts_batch_actions($a); + self::batchActions($a); return; } @@ -253,7 +253,7 @@ class Contacts extends BaseModule /* contact actions */ - private static function _contact_update($contact_id) + private static function updateContactFromPoll($contact_id) { $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()]); if (!DBA::isResult($contact)) { @@ -274,7 +274,7 @@ class Contacts extends BaseModule } } - private static function _contact_update_profile($contact_id) + private static function updateContactFromProbe($contact_id) { $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()]); if (!DBA::isResult($contact)) { @@ -340,19 +340,19 @@ class Contacts extends BaseModule GContact::updateFromProbe($data["url"]); } - private static function _contact_block($contact_id) + private static function blockContact($contact_id) { $blocked = !Contact::isBlockedByUser($contact_id, local_user()); Contact::setBlockedForUser($contact_id, local_user(), $blocked); } - private static function _contact_ignore($contact_id) + private static function ignoreContact($contact_id) { $ignored = !Contact::isIgnoredByUser($contact_id, local_user()); Contact::setIgnoredForUser($contact_id, local_user(), $ignored); } - private static function _contact_archive($contact_id, $orig_record) + private static function archiveContact($contact_id, $orig_record) { $archived = (($orig_record['archive']) ? 0 : 1); $r = q("UPDATE `contact` SET `archive` = %d WHERE `id` = %d AND `uid` = %d", @@ -363,7 +363,7 @@ class Contacts extends BaseModule return DBA::isResult($r); } - private static function _contact_drop($orig_record) + private static function dropContact($orig_record) { $a = get_app(); @@ -407,19 +407,19 @@ class Contacts extends BaseModule } if ($cmd === 'update' && ($orig_record['uid'] != 0)) { - self::_contact_update($contact_id); + self::updateContactFromPoll($contact_id); goaway('contacts/' . $contact_id); // NOTREACHED } if ($cmd === 'updateprofile' && ($orig_record['uid'] != 0)) { - self::_contact_update_profile($contact_id); + self::updateContactFromProbe($contact_id); goaway('crepair/' . $contact_id); // NOTREACHED } if ($cmd === 'block') { - self::_contact_block($contact_id); + self::blockContact($contact_id); $blocked = Contact::isBlockedByUser($contact_id, local_user()); info(($blocked ? L10n::t('Contact has been blocked') : L10n::t('Contact has been unblocked')) . EOL); @@ -429,7 +429,7 @@ class Contacts extends BaseModule } if ($cmd === 'ignore') { - self::_contact_ignore($contact_id); + self::ignoreContact($contact_id); $ignored = Contact::isIgnoredByUser($contact_id, local_user()); info(($ignored ? L10n::t('Contact has been ignored') : L10n::t('Contact has been unignored')) . EOL); @@ -439,7 +439,7 @@ class Contacts extends BaseModule } if ($cmd === 'archive' && ($orig_record['uid'] != 0)) { - $r = self::_contact_archive($contact_id, $orig_record); + $r = self::archiveContact($contact_id, $orig_record); if ($r) { $archived = (($orig_record['archive']) ? 0 : 1); info((($archived) ? L10n::t('Contact has been archived') : L10n::t('Contact has been unarchived')) . EOL); @@ -467,7 +467,7 @@ class Contacts extends BaseModule return replace_macros(get_markup_template('contact_drop_confirm.tpl'), [ '$header' => L10n::t('Drop contact'), - '$contact' => self::_contact_detail_for_template($orig_record), + '$contact' => self::getContactTemplateVars($orig_record), '$method' => 'get', '$message' => L10n::t('Do you really want to delete this contact?'), '$extra_inputs' => $inputs, @@ -482,17 +482,17 @@ class Contacts extends BaseModule goaway('contacts'); } - self::_contact_drop($orig_record); + self::dropContact($orig_record); info(L10n::t('Contact has been removed.') . EOL); goaway('contacts'); return; // NOTREACHED } if ($cmd === 'posts') { - return self::contact_posts($a, $contact_id); + return self::getPostsHTML($a, $contact_id); } if ($cmd === 'conversations') { - return self::contact_conversations($a, $contact_id, $update); + return self::getConversationsHMTL($a, $contact_id, $update); } } @@ -562,7 +562,7 @@ class Contacts extends BaseModule $nettype = L10n::t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact["url"])); // tabs - $tab_str = self::contacts_tab($a, $contact, 3); + $tab_str = self::getTabsHTML($a, $contact, 3); $lost_contact = (($contact['archive'] && $contact['term-date'] > NULL_DATE && $contact['term-date'] < DateTimeFormat::utcNow()) ? L10n::t('Communications lost with this contact!') : ''); @@ -605,7 +605,7 @@ class Contacts extends BaseModule } // Load contactact related actions like hide, suggest, delete and others - $contact_actions = self::contact_actions($contact); + $contact_actions = self::getContactActions($contact); if ($contact['uid'] != 0) { $lbl_vis1 = L10n::t('Profile Visibility'); @@ -822,7 +822,7 @@ class Contacts extends BaseModule foreach ($r as $rr) { $rr['blocked'] = Contact::isBlockedByUser($rr['id'], local_user()); $rr['readonly'] = Contact::isIgnoredByUser($rr['id'], local_user()); - $contacts[] = self::_contact_detail_for_template($rr); + $contacts[] = self::getContactTemplateVars($rr); } } @@ -865,7 +865,7 @@ class Contacts extends BaseModule * * @return string */ - public static function contacts_tab($a, $contact, $active_tab) + public static function getTabsHTML($a, $contact, $active_tab) { // tabs $tabs = [ @@ -934,7 +934,7 @@ class Contacts extends BaseModule return $tab_str; } - private static function contact_conversations($a, $contact_id, $update) + private static function getConversationsHMTL($a, $contact_id, $update) { $o = ''; @@ -959,7 +959,7 @@ class Contacts extends BaseModule $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); if (!$update) { - $o .= self::contacts_tab($a, $contact, 1); + $o .= self::getTabsHTML($a, $contact, 1); } if (DBA::isResult($contact)) { @@ -980,11 +980,11 @@ class Contacts extends BaseModule return $o; } - private static function contact_posts($a, $contact_id) + private static function getPostsHTML($a, $contact_id) { $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); - $o = self::contacts_tab($a, $contact, 2); + $o = self::getTabsHTML($a, $contact, 2); if (DBA::isResult($contact)) { $a->page['aside'] = ""; @@ -1004,7 +1004,7 @@ class Contacts extends BaseModule return $o; } - public static function _contact_detail_for_template(array $rr) + public static function getContactTemplateVars(array $rr) { $dir_icon = ''; $alt_text = ''; @@ -1071,7 +1071,7 @@ class Contacts extends BaseModule * @param array $contact Data about the Contact * @return array with contact related actions */ - private static function contact_actions($contact) + private static function getContactActions($contact) { $poll_enabled = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]); $contact_actions = []; @@ -1133,5 +1133,4 @@ class Contacts extends BaseModule return $contact_actions; } - -} \ No newline at end of file +} diff --git a/view/theme/frio/theme.php b/view/theme/frio/theme.php index fb9ac95cea..98c1b8e7b3 100644 --- a/view/theme/frio/theme.php +++ b/view/theme/frio/theme.php @@ -333,7 +333,7 @@ function frio_acl_lookup(App $a, &$results) if (DBA::isResult($r)) { foreach ($r as $rr) { - $contacts[] = Contacts::_contact_detail_for_template($rr); + $contacts[] = Contacts::getContactTemplateVars($rr); } } From 738cb4ace6cb3dc4a78320577ffbdb3cdb773132 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Sat, 13 Oct 2018 11:35:51 +0200 Subject: [PATCH 360/428] finish refactoring to Module\Contact --- mod/update_contacts.php | 2 +- src/Module/Contact.php | 1136 +++++++++++++++++++++++++++++++++++++ view/theme/frio/theme.php | 10 +- 3 files changed, 1142 insertions(+), 6 deletions(-) create mode 100644 src/Module/Contact.php diff --git a/mod/update_contacts.php b/mod/update_contacts.php index 33ba85055f..6123d03045 100644 --- a/mod/update_contacts.php +++ b/mod/update_contacts.php @@ -14,7 +14,7 @@ function update_contacts_content(App $a) echo "
    "; if ($_GET["force"] == 1) { - $text = Contacts::content($a, true); + $text = Contact::content($a, true); } else { $text = ''; } diff --git a/src/Module/Contact.php b/src/Module/Contact.php new file mode 100644 index 0000000000..eb21b3b3e1 --- /dev/null +++ b/src/Module/Contact.php @@ -0,0 +1,1136 @@ +page, 'aside')) { + $a->page['aside'] = ''; + } + + $contact_id = null; + $contact = null; + if ((($a->argc == 2) && intval($a->argv[1])) || (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations']))) { + $contact_id = intval($a->argv[1]); + $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); + + if (!DBA::isResult($contact)) { + $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => 0]); + } + + // Don't display contacts that are about to be deleted + if ($contact['network'] == Protocol::PHANTOM) { + $contact = false; + } + } + + if (DBA::isResult($contact)) { + if ($contact['self']) { + if (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations'])) { + goaway('profile/' . $contact['nick']); + } else { + goaway('profile/' . $contact['nick'] . '?tab=profile'); + } + } + + $a->data['contact'] = $contact; + + if (($a->data['contact']['network'] != "") && ($a->data['contact']['network'] != Protocol::DFRN)) { + $networkname = format_network_name($a->data['contact']['network'], $a->data['contact']['url']); + } else { + $networkname = ''; + } + + /// @TODO Add nice spaces + $vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"), [ + '$name' => htmlentities($a->data['contact']['name']), + '$photo' => $a->data['contact']['photo'], + '$url' => Contact::MagicLink($a->data['contact']['url']), + '$addr' => (($a->data['contact']['addr'] != "") ? ($a->data['contact']['addr']) : ""), + '$network_name' => $networkname, + '$network' => L10n::t('Network:'), + '$account_type' => Contact::getAccountType($a->data['contact']) + ]); + + $findpeople_widget = ''; + $follow_widget = ''; + $networks_widget = ''; + } else { + $vcard_widget = ''; + $networks_widget = Widget::networks('contacts', $nets); + if (isset($_GET['add'])) { + $follow_widget = Widget::follow($_GET['add']); + } else { + $follow_widget = Widget::follow(); + } + + $findpeople_widget = Widget::findPeople(); + } + + if ($contact['uid'] != 0) { + $groups_widget = Group::sidebarWidget('contacts', 'group', 'full', 'everyone', $contact_id); + } else { + $groups_widget = null; + } + + $a->page['aside'] .= replace_macros(get_markup_template("contacts-widget-sidebar.tpl"), [ + '$vcard_widget' => $vcard_widget, + '$findpeople_widget' => $findpeople_widget, + '$follow_widget' => $follow_widget, + '$groups_widget' => $groups_widget, + '$networks_widget' => $networks_widget + ]); + + $base = System::baseUrl(); + $tpl = get_markup_template("contacts-head.tpl"); + $a->page['htmlhead'] .= replace_macros($tpl, [ + '$baseurl' => System::baseUrl(true), + '$base' => $base + ]); + } + + private static function batchActions(App $a) + { + if (empty($_POST['contact_batch']) || !is_array($_POST['contact_batch'])) { + return; + } + + $contacts_id = $_POST['contact_batch']; + + $orig_records = q("SELECT * FROM `contact` WHERE `id` IN (%s) AND `uid` = %d AND `self` = 0", + implode(",", $contacts_id), + intval(local_user()) + ); + + $count_actions = 0; + foreach ($orig_records as $orig_record) { + $contact_id = $orig_record['id']; + if (x($_POST, 'contacts_batch_update')) { + self::updateContactFromPoll($contact_id); + $count_actions++; + } + if (x($_POST, 'contacts_batch_block')) { + self::blockContact($contact_id); + $count_actions++; + } + if (x($_POST, 'contacts_batch_ignore')) { + self::ignoreContact($contact_id); + $count_actions++; + } + if (x($_POST, 'contacts_batch_archive')) { + $r = self::archiveContact($contact_id, $orig_record); + if ($r) { + $count_actions++; + } + } + if (x($_POST, 'contacts_batch_drop')) { + self::dropContact($orig_record); + $count_actions++; + } + } + if ($count_actions > 0) { + info(L10n::tt("%d contact edited.", "%d contacts edited.", $count_actions)); + } + + goaway('contacts'); + } + + public static function post() + { + $a = self::getApp(); + + if (!local_user()) { + return; + } + + if ($a->argv[1] === "batch") { + self::batchActions($a); + return; + } + + $contact_id = intval($a->argv[1]); + if (!$contact_id) { + return; + } + + if (!DBA::exists('contact', ['id' => $contact_id, 'uid' => local_user()])) { + notice(L10n::t('Could not access contact record.') . EOL); + goaway('contacts'); + return; // NOTREACHED + } + + Addon::callHooks('contact_edit_post', $_POST); + + $profile_id = intval(defaults($_POST, 'profile-assign', 0)); + if ($profile_id) { + if (!DBA::exists('profile', ['id' => $profile_id, 'uid' => local_user()])) { + notice(L10n::t('Could not locate selected profile.') . EOL); + return; + } + } + + $hidden = intval($_POST['hidden']); + + $notify = intval($_POST['notify']); + + $fetch_further_information = intval(defaults($_POST, 'fetch_further_information', 0)); + + $ffi_keyword_blacklist = escape_tags(trim(defaults($_POST, 'ffi_keyword_blacklist', ''))); + + $priority = intval(defaults($_POST, 'poll', 0)); + if ($priority > 5 || $priority < 0) { + $priority = 0; + } + + $info = escape_tags(trim($_POST['info'])); + + $r = q("UPDATE `contact` SET `profile-id` = %d, `priority` = %d , `info` = '%s', + `hidden` = %d, `notify_new_posts` = %d, `fetch_further_information` = %d, + `ffi_keyword_blacklist` = '%s' WHERE `id` = %d AND `uid` = %d", + intval($profile_id), + intval($priority), + DBA::escape($info), + intval($hidden), + intval($notify), + intval($fetch_further_information), + DBA::escape($ffi_keyword_blacklist), + intval($contact_id), + intval(local_user()) + ); + if (DBA::isResult($r)) { + info(L10n::t('Contact updated.') . EOL); + } else { + notice(L10n::t('Failed to update contact record.') . EOL); + } + + $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); + if (DBA::isResult($contact)) { + $a->data['contact'] = $contact; + } + + return; + } + + /* contact actions */ + + private static function updateContactFromPoll($contact_id) + { + $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()]); + if (!DBA::isResult($contact)) { + return; + } + + $uid = $contact["uid"]; + + if ($contact["network"] == Protocol::OSTATUS) { + $result = Contact::createFromProbe($uid, $contact["url"], false, $contact["network"]); + + if ($result['success']) { + q("UPDATE `contact` SET `subhub` = 1 WHERE `id` = %d", intval($contact_id)); + } + } else { + // pull feed and consume it, which should subscribe to the hub. + Worker::add(PRIORITY_HIGH, "OnePoll", $contact_id, "force"); + } + } + + private static function updateContactFromProbe($contact_id) + { + $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()]); + if (!DBA::isResult($contact)) { + return; + } + + $uid = $contact["uid"]; + + $data = Probe::uri($contact["url"], "", 0, false); + + // "Feed" or "Unknown" is mostly a sign of communication problems + if ((in_array($data["network"], [Protocol::FEED, Protocol::PHANTOM])) && ($data["network"] != $contact["network"])) { + return; + } + + $updatefields = ["name", "nick", "url", "addr", "batch", "notify", "poll", "request", "confirm", + "poco", "network", "alias"]; + $update = []; + + if ($data["network"] == Protocol::OSTATUS) { + $result = Contact::createFromProbe($uid, $data["url"], false); + + if ($result['success']) { + $update["subhub"] = true; + } + } + + foreach ($updatefields AS $field) { + if (isset($data[$field]) && ($data[$field] != "")) { + $update[$field] = $data[$field]; + } + } + + $update["nurl"] = normalise_link($data["url"]); + + $query = ""; + + if (isset($data["priority"]) && ($data["priority"] != 0)) { + $query = "`priority` = " . intval($data["priority"]); + } + + foreach ($update AS $key => $value) { + if ($query != "") { + $query .= ", "; + } + + $query .= "`" . $key . "` = '" . DBA::escape($value) . "'"; + } + + if ($query == "") { + return; + } + + $r = q("UPDATE `contact` SET $query WHERE `id` = %d AND `uid` = %d", + intval($contact_id), + intval(local_user()) + ); + + // Update the entry in the contact table + Contact::updateAvatar($data['photo'], local_user(), $contact_id, true); + + // Update the entry in the gcontact table + GContact::updateFromProbe($data["url"]); + } + + private static function blockContact($contact_id) + { + $blocked = !Contact::isBlockedByUser($contact_id, local_user()); + Contact::setBlockedForUser($contact_id, local_user(), $blocked); + } + + private static function ignoreContact($contact_id) + { + $ignored = !Contact::isIgnoredByUser($contact_id, local_user()); + Contact::setIgnoredForUser($contact_id, local_user(), $ignored); + } + + private static function archiveContact($contact_id, $orig_record) + { + $archived = (($orig_record['archive']) ? 0 : 1); + $r = q("UPDATE `contact` SET `archive` = %d WHERE `id` = %d AND `uid` = %d", + intval($archived), + intval($contact_id), + intval(local_user()) + ); + return DBA::isResult($r); + } + + private static function dropContact($orig_record) + { + $a = get_app(); + + $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` + WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1", + intval($a->user['uid']) + ); + if (!DBA::isResult($r)) { + return; + } + + Contact::terminateFriendship($r[0], $orig_record, true); + Contact::remove($orig_record['id']); + } + + public static function content($update = 0) + { + $a = self::getApp(); + $sort_type = 0; + $o = ''; + Nav::setSelected('contacts'); + + if (!local_user()) { + notice(L10n::t('Permission denied.') . EOL); + return Login::form(); + } + + if ($a->argc == 3) { + $contact_id = intval($a->argv[1]); + if (!$contact_id) { + return; + } + + $cmd = $a->argv[2]; + + $orig_record = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => [0, local_user()], 'self' => false]); + if (!DBA::isResult($orig_record)) { + notice(L10n::t('Could not access contact record.') . EOL); + goaway('contacts'); + return; // NOTREACHED + } + + if ($cmd === 'update' && ($orig_record['uid'] != 0)) { + self::updateContactFromPoll($contact_id); + goaway('contacts/' . $contact_id); + // NOTREACHED + } + + if ($cmd === 'updateprofile' && ($orig_record['uid'] != 0)) { + self::updateContactFromProbe($contact_id); + goaway('crepair/' . $contact_id); + // NOTREACHED + } + + if ($cmd === 'block') { + self::blockContact($contact_id); + + $blocked = Contact::isBlockedByUser($contact_id, local_user()); + info(($blocked ? L10n::t('Contact has been blocked') : L10n::t('Contact has been unblocked')) . EOL); + + goaway('contacts/' . $contact_id); + return; // NOTREACHED + } + + if ($cmd === 'ignore') { + self::ignoreContact($contact_id); + + $ignored = Contact::isIgnoredByUser($contact_id, local_user()); + info(($ignored ? L10n::t('Contact has been ignored') : L10n::t('Contact has been unignored')) . EOL); + + goaway('contacts/' . $contact_id); + return; // NOTREACHED + } + + if ($cmd === 'archive' && ($orig_record['uid'] != 0)) { + $r = self::archiveContact($contact_id, $orig_record); + if ($r) { + $archived = (($orig_record['archive']) ? 0 : 1); + info((($archived) ? L10n::t('Contact has been archived') : L10n::t('Contact has been unarchived')) . EOL); + } + + goaway('contacts/' . $contact_id); + return; // NOTREACHED + } + + if ($cmd === 'drop' && ($orig_record['uid'] != 0)) { + // Check if we should do HTML-based delete confirmation + if (x($_REQUEST, 'confirm')) { + // can't take arguments in its "action" parameter + // so add any arguments as hidden inputs + $query = explode_querystring($a->query_string); + $inputs = []; + foreach ($query['args'] as $arg) { + if (strpos($arg, 'confirm=') === false) { + $arg_parts = explode('=', $arg); + $inputs[] = ['name' => $arg_parts[0], 'value' => $arg_parts[1]]; + } + } + + $a->page['aside'] = ''; + + return replace_macros(get_markup_template('contact_drop_confirm.tpl'), [ + '$header' => L10n::t('Drop contact'), + '$contact' => self::getContactTemplateVars($orig_record), + '$method' => 'get', + '$message' => L10n::t('Do you really want to delete this contact?'), + '$extra_inputs' => $inputs, + '$confirm' => L10n::t('Yes'), + '$confirm_url' => $query['base'], + '$confirm_name' => 'confirmed', + '$cancel' => L10n::t('Cancel'), + ]); + } + // Now check how the user responded to the confirmation query + if (x($_REQUEST, 'canceled')) { + goaway('contacts'); + } + + self::dropContact($orig_record); + info(L10n::t('Contact has been removed.') . EOL); + + goaway('contacts'); + return; // NOTREACHED + } + if ($cmd === 'posts') { + return self::getPostsHTML($a, $contact_id); + } + if ($cmd === 'conversations') { + return self::getConversationsHMTL($a, $contact_id, $update); + } + } + + $_SESSION['return_url'] = $a->query_string; + + if ((x($a->data, 'contact')) && (is_array($a->data['contact']))) { + $contact_id = $a->data['contact']['id']; + $contact = $a->data['contact']; + + $a->page['htmlhead'] .= replace_macros(get_markup_template('contact_head.tpl'), [ + '$baseurl' => System::baseUrl(true), + ]); + + $contact['blocked'] = Contact::isBlockedByUser($contact['id'], local_user()); + $contact['readonly'] = Contact::isIgnoredByUser($contact['id'], local_user()); + + $dir_icon = ''; + $relation_text = ''; + switch ($contact['rel']) { + case Contact::FRIEND: + $dir_icon = 'images/lrarrow.gif'; + $relation_text = L10n::t('You are mutual friends with %s'); + break; + + case Contact::FOLLOWER; + $dir_icon = 'images/larrow.gif'; + $relation_text = L10n::t('You are sharing with %s'); + break; + + case Contact::SHARING; + $dir_icon = 'images/rarrow.gif'; + $relation_text = L10n::t('%s is sharing with you'); + break; + + default: + break; + } + + if ($contact['uid'] == 0) { + $relation_text = ''; + } + + if (!in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])) { + $relation_text = ""; + } + + $relation_text = sprintf($relation_text, htmlentities($contact['name'])); + + $url = Contact::magicLink($contact['url']); + if (strpos($url, 'redir/') === 0) { + $sparkle = ' class="sparkle" '; + } else { + $sparkle = ''; + } + + $insecure = L10n::t('Private communications are not available for this contact.'); + + $last_update = (($contact['last-update'] <= NULL_DATE) ? L10n::t('Never') : DateTimeFormat::local($contact['last-update'], 'D, j M Y, g:i A')); + + if ($contact['last-update'] > NULL_DATE) { + $last_update .= ' ' . (($contact['last-update'] <= $contact['success_update']) ? L10n::t("\x28Update was successful\x29") : L10n::t("\x28Update was not successful\x29")); + } + $lblsuggest = (($contact['network'] === Protocol::DFRN) ? L10n::t('Suggest friends') : ''); + + $poll_enabled = in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]); + + $nettype = L10n::t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact["url"])); + + // tabs + $tab_str = self::getTabsHTML($a, $contact, 3); + + $lost_contact = (($contact['archive'] && $contact['term-date'] > NULL_DATE && $contact['term-date'] < DateTimeFormat::utcNow()) ? L10n::t('Communications lost with this contact!') : ''); + + $fetch_further_information = null; + if ($contact['network'] == Protocol::FEED) { + $fetch_further_information = [ + 'fetch_further_information', + L10n::t('Fetch further information for feeds'), + $contact['fetch_further_information'], + L10n::t("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."), + ['0' => L10n::t('Disabled'), + '1' => L10n::t('Fetch information'), + '3' => L10n::t('Fetch keywords'), + '2' => L10n::t('Fetch information and keywords') + ] + ]; + } + + $poll_interval = null; + if (in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) { + $poll_interval = ContactSelector::pollInterval($contact['priority'], (!$poll_enabled)); + } + + $profile_select = null; + if ($contact['network'] == Protocol::DFRN) { + $profile_select = ContactSelector::profileAssign($contact['profile-id'], (($contact['network'] !== Protocol::DFRN) ? true : false)); + } + + /// @todo Only show the following link with DFRN when the remote version supports it + $follow = ''; + $follow_text = ''; + if (in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) { + if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { + $follow = System::baseUrl(true) . "/unfollow?url=" . urlencode($contact["url"]); + $follow_text = L10n::t("Disconnect/Unfollow"); + } + } else { + $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]); + $follow_text = L10n::t("Connect/Follow"); + } + + // Load contactact related actions like hide, suggest, delete and others + $contact_actions = self::getContactActions($contact); + + if ($contact['uid'] != 0) { + $lbl_vis1 = L10n::t('Profile Visibility'); + $lbl_info1 = L10n::t('Contact Information / Notes'); + $contact_settings_label = L10n::t('Contact Settings'); + } else { + $lbl_vis1 = null; + $lbl_info1 = null; + $contact_settings_label = null; + } + + $tpl = get_markup_template("contact_edit.tpl"); + $o .= replace_macros($tpl, [ + '$header' => L10n::t("Contact"), + '$tab_str' => $tab_str, + '$submit' => L10n::t('Submit'), + '$lbl_vis1' => $lbl_vis1, + '$lbl_vis2' => L10n::t('Please choose the profile you would like to display to %s when viewing your profile securely.', $contact['name']), + '$lbl_info1' => $lbl_info1, + '$lbl_info2' => L10n::t('Their personal note'), + '$reason' => trim(notags($contact['reason'])), + '$infedit' => L10n::t('Edit contact notes'), + '$common_link' => 'common/loc/' . local_user() . '/' . $contact['id'], + '$relation_text' => $relation_text, + '$visit' => L10n::t('Visit %s\'s profile [%s]', $contact['name'], $contact['url']), + '$blockunblock' => L10n::t('Block/Unblock contact'), + '$ignorecont' => L10n::t('Ignore contact'), + '$lblcrepair' => L10n::t("Repair URL settings"), + '$lblrecent' => L10n::t('View conversations'), + '$lblsuggest' => $lblsuggest, + '$nettype' => $nettype, + '$poll_interval' => $poll_interval, + '$poll_enabled' => $poll_enabled, + '$lastupdtext' => L10n::t('Last update:'), + '$lost_contact' => $lost_contact, + '$updpub' => L10n::t('Update public posts'), + '$last_update' => $last_update, + '$udnow' => L10n::t('Update now'), + '$follow' => $follow, + '$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' => (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') : ''), + '$hidden' => ['hidden', L10n::t('Hide this contact from others'), ($contact['hidden'] == 1), L10n::t('Replies/likes to your public posts may 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, + '$ffi_keyword_blacklist' => $contact['ffi_keyword_blacklist'], + '$ffi_keyword_blacklist' => ['ffi_keyword_blacklist', L10n::t('Blacklisted keywords'), $contact['ffi_keyword_blacklist'], L10n::t('Comma separated list of keywords that should not be converted to hashtags, when "Fetch information and keywords" is selected')], + '$photo' => $contact['photo'], + '$name' => htmlentities($contact['name']), + '$dir_icon' => $dir_icon, + '$sparkle' => $sparkle, + '$url' => $url, + '$profileurllabel' => L10n::t('Profile URL'), + '$profileurl' => $contact['url'], + '$account_type' => Contact::getAccountType($contact), + '$location' => BBCode::convert($contact["location"]), + '$location_label' => L10n::t("Location:"), + '$xmpp' => BBCode::convert($contact["xmpp"]), + '$xmpp_label' => L10n::t("XMPP:"), + '$about' => BBCode::convert($contact["about"], false), + '$about_label' => L10n::t("About:"), + '$keywords' => $contact["keywords"], + '$keywords_label' => L10n::t("Tags:"), + '$contact_action_button' => L10n::t("Actions"), + '$contact_actions' => $contact_actions, + '$contact_status' => L10n::t("Status"), + '$contact_settings_label' => $contact_settings_label, + '$contact_profile_label' => L10n::t("Profile"), + ]); + + $arr = ['contact' => $contact, 'output' => $o]; + + Addon::callHooks('contact_edit', $arr); + + return $arr['output']; + } + + $blocked = false; + $hidden = false; + $ignored = false; + $archived = false; + $all = false; + + if (($a->argc == 2) && ($a->argv[1] === 'all')) { + $sql_extra = ''; + $all = true; + } elseif (($a->argc == 2) && ($a->argv[1] === 'blocked')) { + $sql_extra = " AND `blocked` = 1 "; + $blocked = true; + } elseif (($a->argc == 2) && ($a->argv[1] === 'hidden')) { + $sql_extra = " AND `hidden` = 1 "; + $hidden = true; + } elseif (($a->argc == 2) && ($a->argv[1] === 'ignored')) { + $sql_extra = " AND `readonly` = 1 "; + $ignored = true; + } elseif (($a->argc == 2) && ($a->argv[1] === 'archived')) { + $sql_extra = " AND `archive` = 1 "; + $archived = true; + } else { + $sql_extra = " AND `blocked` = 0 "; + } + + $sql_extra .= sprintf(" AND `network` != '%s' ", Protocol::PHANTOM); + + $search = x($_GET, 'search') ? notags(trim($_GET['search'])) : ''; + $nets = x($_GET, 'nets' ) ? notags(trim($_GET['nets'])) : ''; + + $tabs = [ + [ + 'label' => L10n::t('Suggestions'), + 'url' => 'suggest', + 'sel' => '', + 'title' => L10n::t('Suggest potential friends'), + 'id' => 'suggestions-tab', + 'accesskey' => 'g', + ], + [ + 'label' => L10n::t('All Contacts'), + 'url' => 'contacts/all', + 'sel' => ($all) ? 'active' : '', + 'title' => L10n::t('Show all contacts'), + 'id' => 'showall-tab', + 'accesskey' => 'l', + ], + [ + 'label' => L10n::t('Unblocked'), + 'url' => 'contacts', + 'sel' => ((!$all) && (!$blocked) && (!$hidden) && (!$search) && (!$nets) && (!$ignored) && (!$archived)) ? 'active' : '', + 'title' => L10n::t('Only show unblocked contacts'), + 'id' => 'showunblocked-tab', + 'accesskey' => 'o', + ], + [ + 'label' => L10n::t('Blocked'), + 'url' => 'contacts/blocked', + 'sel' => ($blocked) ? 'active' : '', + 'title' => L10n::t('Only show blocked contacts'), + 'id' => 'showblocked-tab', + 'accesskey' => 'b', + ], + [ + 'label' => L10n::t('Ignored'), + 'url' => 'contacts/ignored', + 'sel' => ($ignored) ? 'active' : '', + 'title' => L10n::t('Only show ignored contacts'), + 'id' => 'showignored-tab', + 'accesskey' => 'i', + ], + [ + 'label' => L10n::t('Archived'), + 'url' => 'contacts/archived', + 'sel' => ($archived) ? 'active' : '', + 'title' => L10n::t('Only show archived contacts'), + 'id' => 'showarchived-tab', + 'accesskey' => 'y', + ], + [ + 'label' => L10n::t('Hidden'), + 'url' => 'contacts/hidden', + 'sel' => ($hidden) ? 'active' : '', + 'title' => L10n::t('Only show hidden contacts'), + 'id' => 'showhidden-tab', + 'accesskey' => 'h', + ], + ]; + + $tab_tpl = get_markup_template('common_tabs.tpl'); + $t = replace_macros($tab_tpl, ['$tabs' => $tabs]); + + $total = 0; + $searching = false; + $search_hdr = null; + if ($search) { + $searching = true; + $search_hdr = $search; + $search_txt = DBA::escape(protect_sprintf(preg_quote($search))); + $sql_extra .= " AND (name REGEXP '$search_txt' OR url REGEXP '$search_txt' OR nick REGEXP '$search_txt') "; + } + + if ($nets) { + $sql_extra .= sprintf(" AND network = '%s' ", DBA::escape($nets)); + } + + $sql_extra2 = ((($sort_type > 0) && ($sort_type <= Contact::FRIEND)) ? sprintf(" AND `rel` = %d ", intval($sort_type)) : ''); + + $r = q("SELECT COUNT(*) AS `total` FROM `contact` + WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 ", + intval($_SESSION['uid']) + ); + if (DBA::isResult($r)) { + $a->setPagerTotal($r[0]['total']); + $total = $r[0]['total']; + } + + $sql_extra3 = Widget::unavailableNetworks(); + + $contacts = []; + + $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 $sql_extra3 ORDER BY `name` ASC LIMIT %d , %d ", + intval($_SESSION['uid']), + intval($a->pager['start']), + intval($a->pager['itemspage']) + ); + if (DBA::isResult($r)) { + foreach ($r as $rr) { + $rr['blocked'] = Contact::isBlockedByUser($rr['id'], local_user()); + $rr['readonly'] = Contact::isIgnoredByUser($rr['id'], local_user()); + $contacts[] = self::getContactTemplateVars($rr); + } + } + + $tpl = get_markup_template("contacts-template.tpl"); + $o .= replace_macros($tpl, [ + '$baseurl' => System::baseUrl(), + '$header' => L10n::t('Contacts') . (($nets) ? ' - ' . ContactSelector::networkToName($nets) : ''), + '$tabs' => $t, + '$total' => $total, + '$search' => $search_hdr, + '$desc' => L10n::t('Search your contacts'), + '$finding' => $searching ? L10n::t('Results for: %s', $search) : "", + '$submit' => L10n::t('Find'), + '$cmd' => $a->cmd, + '$contacts' => $contacts, + '$contact_drop_confirm' => L10n::t('Do you really want to delete this contact?'), + 'multiselect' => 1, + '$batch_actions' => [ + 'contacts_batch_update' => L10n::t('Update'), + 'contacts_batch_block' => L10n::t('Block') . "/" . L10n::t("Unblock"), + "contacts_batch_ignore" => L10n::t('Ignore') . "/" . L10n::t("Unignore"), + "contacts_batch_archive" => L10n::t('Archive') . "/" . L10n::t("Unarchive"), + "contacts_batch_drop" => L10n::t('Delete'), + ], + '$h_batch_actions' => L10n::t('Batch Actions'), + '$paginate' => paginate($a), + ]); + + return $o; + } + + /** + * @brief List of pages for the Contact TabBar + * + * Available Pages are 'Status', 'Profile', 'Contacts' and 'Common Friends' + * + * @param App $a + * @param array $contact The contact array + * @param int $active_tab 1 if tab should be marked as active + * + * @return string + */ + public static function getTabsHTML($a, $contact, $active_tab) + { + // tabs + $tabs = [ + [ + 'label' => L10n::t('Status'), + 'url' => "contacts/" . $contact['id'] . "/conversations", + 'sel' => (($active_tab == 1) ? 'active' : ''), + 'title' => L10n::t('Conversations started by this contact'), + 'id' => 'status-tab', + 'accesskey' => 'm', + ], + [ + 'label' => L10n::t('Posts and Comments'), + 'url' => "contacts/" . $contact['id'] . "/posts", + 'sel' => (($active_tab == 2) ? 'active' : ''), + 'title' => L10n::t('Status Messages and Posts'), + 'id' => 'posts-tab', + 'accesskey' => 'p', + ], + [ + 'label' => L10n::t('Profile'), + 'url' => "contacts/" . $contact['id'], + 'sel' => (($active_tab == 3) ? 'active' : ''), + 'title' => L10n::t('Profile Details'), + 'id' => 'profile-tab', + 'accesskey' => 'o', + ] + ]; + + // Show this tab only if there is visible friend list + $x = GContact::countAllFriends(local_user(), $contact['id']); + if ($x) { + $tabs[] = ['label' => L10n::t('Contacts'), + 'url' => "allfriends/" . $contact['id'], + 'sel' => (($active_tab == 4) ? 'active' : ''), + 'title' => L10n::t('View all contacts'), + 'id' => 'allfriends-tab', + 'accesskey' => 't']; + } + + // Show this tab only if there is visible common friend list + $common = GContact::countCommonFriends(local_user(), $contact['id']); + if ($common) { + $tabs[] = ['label' => L10n::t('Common Friends'), + 'url' => "common/loc/" . local_user() . "/" . $contact['id'], + 'sel' => (($active_tab == 5) ? 'active' : ''), + 'title' => L10n::t('View all common friends'), + 'id' => 'common-loc-tab', + 'accesskey' => 'd' + ]; + } + + if (!empty($contact['uid'])) { + $tabs[] = ['label' => L10n::t('Advanced'), + 'url' => 'crepair/' . $contact['id'], + 'sel' => (($active_tab == 6) ? 'active' : ''), + 'title' => L10n::t('Advanced Contact Settings'), + 'id' => 'advanced-tab', + 'accesskey' => 'r' + ]; + } + + $tab_tpl = get_markup_template('common_tabs.tpl'); + $tab_str = replace_macros($tab_tpl, ['$tabs' => $tabs]); + + return $tab_str; + } + + private static function getConversationsHMTL($a, $contact_id, $update) + { + $o = ''; + + if (!$update) { + // We need the editor here to be able to reshare an item. + if (local_user()) { + $x = [ + 'is_owner' => true, + 'allow_location' => $a->user['allow_location'], + 'default_location' => $a->user['default-location'], + 'nickname' => $a->user['nickname'], + 'lockstate' => (is_array($a->user) && (strlen($a->user['allow_cid']) || strlen($a->user['allow_gid']) || strlen($a->user['deny_cid']) || strlen($a->user['deny_gid'])) ? 'lock' : 'unlock'), + 'acl' => ACL::getFullSelectorHTML($a->user, true), + 'bang' => '', + 'visitor' => 'block', + 'profile_uid' => local_user(), + ]; + $o = status_editor($a, $x, 0, true); + } + } + + $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); + + if (!$update) { + $o .= self::getTabsHTML($a, $contact, 1); + } + + if (DBA::isResult($contact)) { + $a->page['aside'] = ""; + + $profiledata = Contact::getDetailsByURL($contact["url"]); + + if (local_user()) { + if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { + $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]); + } + } + + Profile::load($a, "", 0, $profiledata, true); + $o .= Contact::getPostsFromUrl($contact["url"], true, $update); + } + + return $o; + } + + private static function getPostsHTML($a, $contact_id) + { + $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); + + $o = self::getTabsHTML($a, $contact, 2); + + if (DBA::isResult($contact)) { + $a->page['aside'] = ""; + + $profiledata = Contact::getDetailsByURL($contact["url"]); + + if (local_user()) { + if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { + $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]); + } + } + + Profile::load($a, "", 0, $profiledata, true); + $o .= Contact::getPostsFromUrl($contact["url"]); + } + + return $o; + } + + public static function getContactTemplateVars(array $rr) + { + $dir_icon = ''; + $alt_text = ''; + + switch ($rr['rel']) { + case Contact::FRIEND: + $dir_icon = 'images/lrarrow.gif'; + $alt_text = L10n::t('Mutual Friendship'); + break; + + case Contact::FOLLOWER; + $dir_icon = 'images/larrow.gif'; + $alt_text = L10n::t('is a fan of yours'); + break; + + case Contact::SHARING; + $dir_icon = 'images/rarrow.gif'; + $alt_text = L10n::t('you are a fan of'); + break; + + default: + break; + } + + $url = Contact::magicLink($rr['url']); + + if (strpos($url, 'redir/') === 0) { + $sparkle = ' class="sparkle" '; + } else { + $sparkle = ''; + } + + if ($rr['self']) { + $dir_icon = 'images/larrow.gif'; + $alt_text = L10n::t('This is you'); + $url = $rr['url']; + $sparkle = ''; + } + + return [ + 'img_hover' => L10n::t('Visit %s\'s profile [%s]', $rr['name'], $rr['url']), + 'edit_hover' => L10n::t('Edit contact'), + 'photo_menu' => Contact::photoMenu($rr), + 'id' => $rr['id'], + 'alt_text' => $alt_text, + 'dir_icon' => $dir_icon, + 'thumb' => ProxyUtils::proxifyUrl($rr['thumb'], false, ProxyUtils::SIZE_THUMB), + 'name' => htmlentities($rr['name']), + 'username' => htmlentities($rr['name']), + 'account_type' => Contact::getAccountType($rr), + 'sparkle' => $sparkle, + 'itemurl' => (($rr['addr'] != "") ? $rr['addr'] : $rr['url']), + 'url' => $url, + 'network' => ContactSelector::networkToName($rr['network'], $rr['url']), + 'nick' => htmlentities($rr['nick']), + ]; + } + + /** + * @brief Gives a array with actions which can performed to a given contact + * + * This includes actions like e.g. 'block', 'hide', 'archive', 'delete' and others + * + * @param array $contact Data about the Contact + * @return array with contact related actions + */ + private static function getContactActions($contact) + { + $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 + if ($contact['network'] === Protocol::DFRN) { + $contact_actions['suggest'] = [ + 'label' => L10n::t('Suggest friends'), + 'url' => 'fsuggest/' . $contact['id'], + 'title' => '', + 'sel' => '', + 'id' => 'suggest', + ]; + } + + if ($poll_enabled) { + $contact_actions['update'] = [ + 'label' => L10n::t('Update now'), + 'url' => 'contacts/' . $contact['id'] . '/update', + 'title' => '', + 'sel' => '', + 'id' => 'update', + ]; + } + + $contact_actions['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' : ''), + 'id' => 'toggle-block', + ]; + + $contact_actions['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' : ''), + 'id' => 'toggle-ignore', + ]; + + if ($contact['uid'] != 0) { + $contact_actions['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' : ''), + 'id' => 'toggle-archive', + ]; + + $contact_actions['delete'] = [ + 'label' => L10n::t('Delete'), + 'url' => 'contacts/' . $contact['id'] . '/drop', + 'title' => L10n::t('Delete contact'), + 'sel' => '', + 'id' => 'delete', + ]; + } + + return $contact_actions; + } +} diff --git a/view/theme/frio/theme.php b/view/theme/frio/theme.php index 98c1b8e7b3..79ec421d2b 100644 --- a/view/theme/frio/theme.php +++ b/view/theme/frio/theme.php @@ -16,8 +16,8 @@ use Friendica\Core\L10n; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBA; -use Friendica\Model\Profile; -use Friendica\Module\Contacts; +use Friendica\Model; +use Friendica\Module\Contact; $frio = 'view/theme/frio'; @@ -209,7 +209,7 @@ function frio_contact_photo_menu(App $a, &$args) function frio_remote_nav($a, &$nav) { // get the homelink from $_XSESSION - $homelink = Profile::getMyURL(); + $homelink = Model\Profile::getMyURL(); if (!$homelink) { $homelink = defaults($_SESSION, 'visitor_home', ''); } @@ -247,7 +247,7 @@ function frio_remote_nav($a, &$nav) } elseif (!local_user() && remote_user()) { $r = q("SELECT `name`, `nick`, `micro` AS `photo` FROM `contact` WHERE `id` = %d", intval(remote_user())); $nav['remote'] = L10n::t('Guest'); - } elseif (Profile::getMyURL()) { + } elseif (Model\Profile::getMyURL()) { $r = q("SELECT `name`, `nick`, `photo` FROM `gcontact` WHERE `addr` = '%s' AND `network` = 'dfrn'", DBA::escape($webbie)); @@ -333,7 +333,7 @@ function frio_acl_lookup(App $a, &$results) if (DBA::isResult($r)) { foreach ($r as $rr) { - $contacts[] = Contacts::getContactTemplateVars($rr); + $contacts[] = Model\Contact::getContactTemplateVars($rr); } } From bfa05156ca5096fe9db8ca4a66ca32ef4cbf0ca5 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Sat, 13 Oct 2018 13:29:56 +0200 Subject: [PATCH 361/428] change links from /contacts to /contact --- include/api.php | 2 +- mod/crepair.php | 2 - mod/dfrn_confirm.php | 4 +- mod/dfrn_request.php | 4 +- mod/group.php | 4 +- mod/newmember.php | 6 +- src/Content/Nav.php | 2 +- src/Model/Contact.php | 6 +- src/Module/Contact.php | 199 ++- src/Module/Contacts.php | 1136 ----------------- util/messages.po | 234 ++-- view/templates/contacts-template.tpl | 2 +- view/templates/crepair.tpl | 2 +- view/theme/frio/templates/contact_edit.tpl | 2 +- .../frio/templates/contacts-template.tpl | 2 +- view/theme/frio/templates/crepair.tpl | 2 +- view/theme/frio/theme.php | 6 +- 17 files changed, 232 insertions(+), 1383 deletions(-) delete mode 100644 src/Module/Contacts.php diff --git a/include/api.php b/include/api.php index 01cb93a3b8..ff763e9885 100644 --- a/include/api.php +++ b/include/api.php @@ -761,7 +761,7 @@ function api_get_user(App $a, $contact_id = null) 'statusnet_blocking' => false, 'notifications' => false, /// @TODO old way? - //'statusnet_profile_url' => System::baseUrl()."/contacts/".$uinfo[0]['cid'], + //'statusnet_profile_url' => System::baseUrl()."/contact/".$uinfo[0]['cid'], 'statusnet_profile_url' => $uinfo[0]['url'], 'uid' => intval($uinfo[0]['uid']), 'cid' => intval($uinfo[0]['cid']), diff --git a/mod/crepair.php b/mod/crepair.php index e5fb1e3347..14ed89afbc 100644 --- a/mod/crepair.php +++ b/mod/crepair.php @@ -11,8 +11,6 @@ use Friendica\Database\DBA; use Friendica\Model; use Friendica\Module\Contact; -require_once 'mod/contacts.php'; - function crepair_init(App $a) { if (!local_user()) { diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php index 969e2286c8..48ce3c6aa6 100644 --- a/mod/dfrn_confirm.php +++ b/mod/dfrn_confirm.php @@ -400,7 +400,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) // Let's send our user to the contact editor in case they want to // do anything special with this new friend. if ($handsfree === null) { - goaway(System::baseUrl() . '/contacts/' . intval($contact_id)); + goaway(System::baseUrl() . '/contact/' . intval($contact_id)); } else { return; } @@ -604,7 +604,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) 'to_name' => $combined['username'], 'to_email' => $combined['email'], 'uid' => $combined['uid'], - 'link' => System::baseUrl() . '/contacts/' . $dfrn_record, + 'link' => System::baseUrl() . '/contact/' . $dfrn_record, 'source_name' => ((strlen(stripslashes($combined['name']))) ? stripslashes($combined['name']) : L10n::t('[Name Withheld]')), 'source_link' => $combined['url'], 'source_photo' => $combined['photo'], diff --git a/mod/dfrn_request.php b/mod/dfrn_request.php index e611458281..67db2c6285 100644 --- a/mod/dfrn_request.php +++ b/mod/dfrn_request.php @@ -173,9 +173,9 @@ function dfrn_request_post(App $a) Contact::updateAvatar($photo, local_user(), $r[0]["id"], true); } - $forwardurl = System::baseUrl() . "/contacts/" . $r[0]['id']; + $forwardurl = System::baseUrl() . "/contact/" . $r[0]['id']; } else { - $forwardurl = System::baseUrl() . "/contacts"; + $forwardurl = System::baseUrl() . "/contact"; } // Allow the blocked remote notification to complete diff --git a/mod/group.php b/mod/group.php index ec4ee4da2b..962697c24f 100644 --- a/mod/group.php +++ b/mod/group.php @@ -54,7 +54,7 @@ function group_post(App $a) { ); if (!DBA::isResult($r)) { notice(L10n::t('Group not found.') . EOL); - goaway(System::baseUrl() . '/contacts'); + goaway(System::baseUrl() . '/contact'); return; // NOTREACHED } $group = $r[0]; @@ -181,7 +181,7 @@ function group_content(App $a) { if (!DBA::isResult($r)) { notice(L10n::t('Group not found.') . EOL); - goaway(System::baseUrl() . '/contacts'); + goaway(System::baseUrl() . '/contact'); } $group = $r[0]; diff --git a/mod/newmember.php b/mod/newmember.php index b3bf310d5b..cd59cc780c 100644 --- a/mod/newmember.php +++ b/mod/newmember.php @@ -36,13 +36,13 @@ function newmember_content(App $a) $o .= '
  • ' . '' . L10n::t('Importing Emails') . '
    ' . L10n::t('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') . '
  • ' . EOL; } - $o .= '
  • ' . '' . L10n::t('Go to Your Contacts Page') . '
    ' . L10n::t('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 Add New Contact dialog.') . '
  • ' . EOL; + $o .= '
  • ' . '' . L10n::t('Go to Your Contacts Page') . '
    ' . L10n::t('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 Add New Contact dialog.') . '
  • ' . EOL; $o .= '
  • ' . '' . L10n::t("Go to Your Site's Directory") . '
    ' . L10n::t('The Directory page lets you find other people in this network or other federated sites. Look for a Connect or Follow link on their profile page. Provide your own Identity Address if requested.') . '
  • ' . EOL; - $o .= '
  • ' . '' . L10n::t('Finding New People') . '
    ' . L10n::t("On the side panel of the Contacts page are several tools to find new friends. We can match people by interest, look up people by name or interest, and provide suggestions based on network relationships. On a brand new site, friend suggestions will usually begin to be populated within 24 hours.") . '
  • ' . EOL; + $o .= '
  • ' . '' . L10n::t('Finding New People') . '
    ' . L10n::t("On the side panel of the Contacts page are several tools to find new friends. We can match people by interest, look up people by name or interest, and provide suggestions based on network relationships. On a brand new site, friend suggestions will usually begin to be populated within 24 hours.") . '
  • ' . EOL; $o .= ''; $o .= '

    ' . L10n::t('Groups') . '

    '; $o .= '
      '; - $o .= '
    • ' . '' . L10n::t('Group Your Contacts') . '
      ' . L10n::t('Once you have made some friends, organize them into private conversation groups from the sidebar of your Contacts page and then you can interact with each group privately on your Network page.') . '
    • ' . EOL; + $o .= '
    • ' . '' . L10n::t('Group Your Contacts') . '
      ' . L10n::t('Once you have made some friends, organize them into private conversation groups from the sidebar of your Contacts page and then you can interact with each group privately on your Network page.') . '
    • ' . EOL; if (Config::get('system', 'newuser_private')) { $o .= '
    • ' . '' . L10n::t("Why Aren't My Posts Public?") . '
      ' . L10n::t("Friendica respects your privacy. By default, your posts will only show up to people you've added as friends. For more information, see the help section from the link above.") . '
    • ' . EOL; diff --git a/src/Content/Nav.php b/src/Content/Nav.php index 7a1a149a2f..4f6f4ae0b9 100644 --- a/src/Content/Nav.php +++ b/src/Content/Nav.php @@ -210,7 +210,7 @@ class Nav $nav['profiles'] = ['profiles', L10n::t('Profiles'), '', L10n::t('Manage/Edit Profiles')]; } - $nav['contacts'] = ['contacts', L10n::t('Contacts'), '', L10n::t('Manage/edit friends and contacts')]; + $nav['contacts'] = ['contact', L10n::t('Contacts'), '', L10n::t('Manage/edit friends and contacts')]; } // Show the link to the admin configuration page if user is admin diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 23c31d0b17..1dd84e0037 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -923,12 +923,12 @@ class Contact extends BaseObject $poke_link = System::baseUrl() . '/poke/?f=&c=' . $contact['id']; } - $contact_url = System::baseUrl() . '/contacts/' . $contact['id']; + $contact_url = System::baseUrl() . '/contact/' . $contact['id']; - $posts_link = System::baseUrl() . '/contacts/' . $contact['id'] . '/conversations'; + $posts_link = System::baseUrl() . '/contact/' . $contact['id'] . '/conversations'; if (!$contact['self']) { - $contact_drop_link = System::baseUrl() . '/contacts/' . $contact['id'] . '/drop?confirm=1'; + $contact_drop_link = System::baseUrl() . '/contact/' . $contact['id'] . '/drop?confirm=1'; } /** diff --git a/src/Module/Contact.php b/src/Module/Contact.php index eb21b3b3e1..07b7c907da 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -14,10 +14,7 @@ use Friendica\Core\Protocol; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBA; -use Friendica\Model\Contact; -use Friendica\Model\GContact; -use Friendica\Model\Group; -use Friendica\Model\Profile; +use Friendica\Model; use Friendica\Network\Probe; use Friendica\Util\DateTimeFormat; use Friendica\Util\Proxy as ProxyUtils; @@ -85,11 +82,11 @@ class Contact extends BaseModule $vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"), [ '$name' => htmlentities($a->data['contact']['name']), '$photo' => $a->data['contact']['photo'], - '$url' => Contact::MagicLink($a->data['contact']['url']), + '$url' => Model\Contact::MagicLink($a->data['contact']['url']), '$addr' => (($a->data['contact']['addr'] != "") ? ($a->data['contact']['addr']) : ""), '$network_name' => $networkname, '$network' => L10n::t('Network:'), - '$account_type' => Contact::getAccountType($a->data['contact']) + '$account_type' => Model\Contact::getAccountType($a->data['contact']) ]); $findpeople_widget = ''; @@ -108,7 +105,7 @@ class Contact extends BaseModule } if ($contact['uid'] != 0) { - $groups_widget = Group::sidebarWidget('contacts', 'group', 'full', 'everyone', $contact_id); + $groups_widget = Model\Group::sidebarWidget('contacts', 'group', 'full', 'everyone', $contact_id); } else { $groups_widget = null; } @@ -121,7 +118,7 @@ class Contact extends BaseModule '$networks_widget' => $networks_widget ]); - $base = System::baseUrl(); + $base = $a->getBaseURL(); $tpl = get_markup_template("contacts-head.tpl"); $a->page['htmlhead'] .= replace_macros($tpl, [ '$baseurl' => System::baseUrl(true), @@ -137,33 +134,31 @@ class Contact extends BaseModule $contacts_id = $_POST['contact_batch']; - $orig_records = q("SELECT * FROM `contact` WHERE `id` IN (%s) AND `uid` = %d AND `self` = 0", - implode(",", $contacts_id), - intval(local_user()) - ); - + $stmt = DBA::select('contact', ['id'], ['id' => $contacts_id, 'id' => local_user(), 'self' => false]); + $orig_records = DBA::toArray($stmt); + $count_actions = 0; foreach ($orig_records as $orig_record) { $contact_id = $orig_record['id']; - if (x($_POST, 'contacts_batch_update')) { + if (defaults($_POST, 'contacts_batch_update')) { self::updateContactFromPoll($contact_id); $count_actions++; } - if (x($_POST, 'contacts_batch_block')) { + if (defaults($_POST, 'contacts_batch_block')) { self::blockContact($contact_id); $count_actions++; } - if (x($_POST, 'contacts_batch_ignore')) { + if (defaults($_POST, 'contacts_batch_ignore')) { self::ignoreContact($contact_id); $count_actions++; } - if (x($_POST, 'contacts_batch_archive')) { + if (defaults($_POST, 'contacts_batch_archive')) { $r = self::archiveContact($contact_id, $orig_record); if ($r) { $count_actions++; } } - if (x($_POST, 'contacts_batch_drop')) { + if (defaults($_POST, 'contacts_batch_drop')) { self::dropContact($orig_record); $count_actions++; } @@ -172,7 +167,7 @@ class Contact extends BaseModule info(L10n::tt("%d contact edited.", "%d contacts edited.", $count_actions)); } - goaway('contacts'); + goaway('contact'); } public static function post() @@ -209,9 +204,9 @@ class Contact extends BaseModule } } - $hidden = intval($_POST['hidden']); + $hidden = defaults($_POST['hidden']); - $notify = intval($_POST['notify']); + $notify = defaults($_POST['notify']); $fetch_further_information = intval(defaults($_POST, 'fetch_further_information', 0)); @@ -224,19 +219,16 @@ class Contact extends BaseModule $info = escape_tags(trim($_POST['info'])); - $r = q("UPDATE `contact` SET `profile-id` = %d, `priority` = %d , `info` = '%s', - `hidden` = %d, `notify_new_posts` = %d, `fetch_further_information` = %d, - `ffi_keyword_blacklist` = '%s' WHERE `id` = %d AND `uid` = %d", - intval($profile_id), - intval($priority), - DBA::escape($info), - intval($hidden), - intval($notify), - intval($fetch_further_information), - DBA::escape($ffi_keyword_blacklist), - intval($contact_id), - intval(local_user()) - ); + $r = DBA::update('contact', + ['profile-id' => $profile_id, + 'priority' => $priority, + 'info' => $info, + 'hidden' => $hidden, + 'notify_new_posts' => $notify, + 'fetch_further_information' => $fetch_further_information, + 'ffi_keyword_blacklist' => $ffi_keyword_blacklist], + ['id' => $contact_id, 'uid' => local_user()]); + if (DBA::isResult($r)) { info(L10n::t('Contact updated.') . EOL); } else { @@ -263,10 +255,10 @@ class Contact extends BaseModule $uid = $contact["uid"]; if ($contact["network"] == Protocol::OSTATUS) { - $result = Contact::createFromProbe($uid, $contact["url"], false, $contact["network"]); + $result = Model\Contact::createFromProbe($uid, $contact["url"], false, $contact["network"]); if ($result['success']) { - q("UPDATE `contact` SET `subhub` = 1 WHERE `id` = %d", intval($contact_id)); + DBA::update('contact', ['subhub' => 1], ['id' => $contact_id]); } } else { // pull feed and consume it, which should subscribe to the hub. @@ -295,7 +287,7 @@ class Contact extends BaseModule $update = []; if ($data["network"] == Protocol::OSTATUS) { - $result = Contact::createFromProbe($uid, $data["url"], false); + $result = Model\Contact::createFromProbe($uid, $data["url"], false); if ($result['success']) { $update["subhub"] = true; @@ -313,7 +305,7 @@ class Contact extends BaseModule $query = ""; if (isset($data["priority"]) && ($data["priority"] != 0)) { - $query = "`priority` = " . intval($data["priority"]); + $query = "'priority' => '" . intval($data["priority"]) . "'"; } foreach ($update AS $key => $value) { @@ -321,45 +313,39 @@ class Contact extends BaseModule $query .= ", "; } - $query .= "`" . $key . "` = '" . DBA::escape($value) . "'"; + $query .= "'" . $key . "' => '" . DBA::escape($value) . "'"; } if ($query == "") { return; } - $r = q("UPDATE `contact` SET $query WHERE `id` = %d AND `uid` = %d", - intval($contact_id), - intval(local_user()) - ); + $r = DBA::update('contact', $query, ['id' => $contact_id, 'uid' => local_user()]); // Update the entry in the contact table - Contact::updateAvatar($data['photo'], local_user(), $contact_id, true); + Model\Contact::updateAvatar($data['photo'], local_user(), $contact_id, true); // Update the entry in the gcontact table - GContact::updateFromProbe($data["url"]); + Model\GContact::updateFromProbe($data["url"]); } private static function blockContact($contact_id) { - $blocked = !Contact::isBlockedByUser($contact_id, local_user()); - Contact::setBlockedForUser($contact_id, local_user(), $blocked); + $blocked = !Model\Contact::isBlockedByUser($contact_id, local_user()); + Model\Contact::setBlockedForUser($contact_id, local_user(), $blocked); } private static function ignoreContact($contact_id) { - $ignored = !Contact::isIgnoredByUser($contact_id, local_user()); - Contact::setIgnoredForUser($contact_id, local_user(), $ignored); + $ignored = !Model\Contact::isIgnoredByUser($contact_id, local_user()); + Model\Contact::setIgnoredForUser($contact_id, local_user(), $ignored); } private static function archiveContact($contact_id, $orig_record) { $archived = (($orig_record['archive']) ? 0 : 1); - $r = q("UPDATE `contact` SET `archive` = %d WHERE `id` = %d AND `uid` = %d", - intval($archived), - intval($contact_id), - intval(local_user()) - ); + $r = DBA::update('contact', ['archive' => $archived], ['id' => $contact_id, 'uid' => local_user()]); + return DBA::isResult($r); } @@ -375,8 +361,8 @@ class Contact extends BaseModule return; } - Contact::terminateFriendship($r[0], $orig_record, true); - Contact::remove($orig_record['id']); + Model\Contact::terminateFriendship($r[0], $orig_record, true); + Model\Contact::remove($orig_record['id']); } public static function content($update = 0) @@ -421,7 +407,7 @@ class Contact extends BaseModule if ($cmd === 'block') { self::blockContact($contact_id); - $blocked = Contact::isBlockedByUser($contact_id, local_user()); + $blocked = Model\Contact::isBlockedByUser($contact_id, local_user()); info(($blocked ? L10n::t('Contact has been blocked') : L10n::t('Contact has been unblocked')) . EOL); goaway('contacts/' . $contact_id); @@ -431,7 +417,7 @@ class Contact extends BaseModule if ($cmd === 'ignore') { self::ignoreContact($contact_id); - $ignored = Contact::isIgnoredByUser($contact_id, local_user()); + $ignored = Model\Contact::isIgnoredByUser($contact_id, local_user()); info(($ignored ? L10n::t('Contact has been ignored') : L10n::t('Contact has been unignored')) . EOL); goaway('contacts/' . $contact_id); @@ -451,7 +437,7 @@ class Contact extends BaseModule if ($cmd === 'drop' && ($orig_record['uid'] != 0)) { // Check if we should do HTML-based delete confirmation - if (x($_REQUEST, 'confirm')) { + if (defaults($_REQUEST, 'confirm')) { // can't take arguments in its "action" parameter // so add any arguments as hidden inputs $query = explode_querystring($a->query_string); @@ -478,7 +464,7 @@ class Contact extends BaseModule ]); } // Now check how the user responded to the confirmation query - if (x($_REQUEST, 'canceled')) { + if (defaults($_REQUEST, 'canceled')) { goaway('contacts'); } @@ -498,31 +484,31 @@ class Contact extends BaseModule $_SESSION['return_url'] = $a->query_string; - if ((x($a->data, 'contact')) && (is_array($a->data['contact']))) { + if ((defaults($a->data, 'contact')) && (is_array($a->data['contact']))) { $contact_id = $a->data['contact']['id']; $contact = $a->data['contact']; $a->page['htmlhead'] .= replace_macros(get_markup_template('contact_head.tpl'), [ - '$baseurl' => System::baseUrl(true), + '$baseurl' => $a->getBaseURL(true), ]); - $contact['blocked'] = Contact::isBlockedByUser($contact['id'], local_user()); - $contact['readonly'] = Contact::isIgnoredByUser($contact['id'], local_user()); + $contact['blocked'] = Model\Contact::isBlockedByUser($contact['id'], local_user()); + $contact['readonly'] = Model\Contact::isIgnoredByUser($contact['id'], local_user()); $dir_icon = ''; $relation_text = ''; switch ($contact['rel']) { - case Contact::FRIEND: + case Model\Contact::FRIEND: $dir_icon = 'images/lrarrow.gif'; $relation_text = L10n::t('You are mutual friends with %s'); break; - case Contact::FOLLOWER; + case Model\Contact::FOLLOWER; $dir_icon = 'images/larrow.gif'; $relation_text = L10n::t('You are sharing with %s'); break; - case Contact::SHARING; + case Model\Contact::SHARING; $dir_icon = 'images/rarrow.gif'; $relation_text = L10n::t('%s is sharing with you'); break; @@ -541,7 +527,7 @@ class Contact extends BaseModule $relation_text = sprintf($relation_text, htmlentities($contact['name'])); - $url = Contact::magicLink($contact['url']); + $url = Model\Contact::magicLink($contact['url']); if (strpos($url, 'redir/') === 0) { $sparkle = ' class="sparkle" '; } else { @@ -594,13 +580,13 @@ class Contact extends BaseModule /// @todo Only show the following link with DFRN when the remote version supports it $follow = ''; $follow_text = ''; - if (in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) { + if (in_array($contact['rel'], [Model\Contact::FRIEND, Model\Contact::SHARING])) { if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { - $follow = System::baseUrl(true) . "/unfollow?url=" . urlencode($contact["url"]); + $follow = $a->getBaseURL(true) . "/unfollow?url=" . urlencode($contact["url"]); $follow_text = L10n::t("Disconnect/Unfollow"); } } else { - $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]); + $follow = $a->getBaseURL(true) . "/follow?url=" . urlencode($contact["url"]); $follow_text = L10n::t("Connect/Follow"); } @@ -669,7 +655,7 @@ class Contact extends BaseModule '$url' => $url, '$profileurllabel' => L10n::t('Profile URL'), '$profileurl' => $contact['url'], - '$account_type' => Contact::getAccountType($contact), + '$account_type' => Model\Contact::getAccountType($contact), '$location' => BBCode::convert($contact["location"]), '$location_label' => L10n::t("Location:"), '$xmpp' => BBCode::convert($contact["xmpp"]), @@ -719,8 +705,8 @@ class Contact extends BaseModule $sql_extra .= sprintf(" AND `network` != '%s' ", Protocol::PHANTOM); - $search = x($_GET, 'search') ? notags(trim($_GET['search'])) : ''; - $nets = x($_GET, 'nets' ) ? notags(trim($_GET['nets'])) : ''; + $search = defaults($_GET, 'search') ? notags(trim($_GET['search'])) : ''; + $nets = defaults($_GET, 'nets' ) ? notags(trim($_GET['nets'])) : ''; $tabs = [ [ @@ -733,7 +719,7 @@ class Contact extends BaseModule ], [ 'label' => L10n::t('All Contacts'), - 'url' => 'contacts/all', + 'url' => 'contact/all', 'sel' => ($all) ? 'active' : '', 'title' => L10n::t('Show all contacts'), 'id' => 'showall-tab', @@ -741,7 +727,7 @@ class Contact extends BaseModule ], [ 'label' => L10n::t('Unblocked'), - 'url' => 'contacts', + 'url' => 'contact', 'sel' => ((!$all) && (!$blocked) && (!$hidden) && (!$search) && (!$nets) && (!$ignored) && (!$archived)) ? 'active' : '', 'title' => L10n::t('Only show unblocked contacts'), 'id' => 'showunblocked-tab', @@ -749,7 +735,7 @@ class Contact extends BaseModule ], [ 'label' => L10n::t('Blocked'), - 'url' => 'contacts/blocked', + 'url' => 'contact/blocked', 'sel' => ($blocked) ? 'active' : '', 'title' => L10n::t('Only show blocked contacts'), 'id' => 'showblocked-tab', @@ -757,7 +743,7 @@ class Contact extends BaseModule ], [ 'label' => L10n::t('Ignored'), - 'url' => 'contacts/ignored', + 'url' => 'contact/ignored', 'sel' => ($ignored) ? 'active' : '', 'title' => L10n::t('Only show ignored contacts'), 'id' => 'showignored-tab', @@ -765,7 +751,7 @@ class Contact extends BaseModule ], [ 'label' => L10n::t('Archived'), - 'url' => 'contacts/archived', + 'url' => 'contact/archived', 'sel' => ($archived) ? 'active' : '', 'title' => L10n::t('Only show archived contacts'), 'id' => 'showarchived-tab', @@ -773,7 +759,7 @@ class Contact extends BaseModule ], [ 'label' => L10n::t('Hidden'), - 'url' => 'contacts/hidden', + 'url' => 'contact/hidden', 'sel' => ($hidden) ? 'active' : '', 'title' => L10n::t('Only show hidden contacts'), 'id' => 'showhidden-tab', @@ -798,7 +784,7 @@ class Contact extends BaseModule $sql_extra .= sprintf(" AND network = '%s' ", DBA::escape($nets)); } - $sql_extra2 = ((($sort_type > 0) && ($sort_type <= Contact::FRIEND)) ? sprintf(" AND `rel` = %d ", intval($sort_type)) : ''); + $sql_extra2 = ((($sort_type > 0) && ($sort_type <= Model\Contact::FRIEND)) ? sprintf(" AND `rel` = %d ", intval($sort_type)) : ''); $r = q("SELECT COUNT(*) AS `total` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 ", @@ -820,8 +806,8 @@ class Contact extends BaseModule ); if (DBA::isResult($r)) { foreach ($r as $rr) { - $rr['blocked'] = Contact::isBlockedByUser($rr['id'], local_user()); - $rr['readonly'] = Contact::isIgnoredByUser($rr['id'], local_user()); + $rr['blocked'] = Model\Contact::isBlockedByUser($rr['id'], local_user()); + $rr['readonly'] = Model\Contact::isIgnoredByUser($rr['id'], local_user()); $contacts[] = self::getContactTemplateVars($rr); } } @@ -863,7 +849,8 @@ class Contact extends BaseModule * @param array $contact The contact array * @param int $active_tab 1 if tab should be marked as active * - * @return string + * @return string | HTML string of the contact page tabs buttons. + */ public static function getTabsHTML($a, $contact, $active_tab) { @@ -871,7 +858,7 @@ class Contact extends BaseModule $tabs = [ [ 'label' => L10n::t('Status'), - 'url' => "contacts/" . $contact['id'] . "/conversations", + 'url' => "contact/" . $contact['id'] . "/conversations", 'sel' => (($active_tab == 1) ? 'active' : ''), 'title' => L10n::t('Conversations started by this contact'), 'id' => 'status-tab', @@ -879,7 +866,7 @@ class Contact extends BaseModule ], [ 'label' => L10n::t('Posts and Comments'), - 'url' => "contacts/" . $contact['id'] . "/posts", + 'url' => "contact/" . $contact['id'] . "/posts", 'sel' => (($active_tab == 2) ? 'active' : ''), 'title' => L10n::t('Status Messages and Posts'), 'id' => 'posts-tab', @@ -887,7 +874,7 @@ class Contact extends BaseModule ], [ 'label' => L10n::t('Profile'), - 'url' => "contacts/" . $contact['id'], + 'url' => "contact/" . $contact['id'], 'sel' => (($active_tab == 3) ? 'active' : ''), 'title' => L10n::t('Profile Details'), 'id' => 'profile-tab', @@ -896,7 +883,7 @@ class Contact extends BaseModule ]; // Show this tab only if there is visible friend list - $x = GContact::countAllFriends(local_user(), $contact['id']); + $x = Model\GContact::countAllFriends(local_user(), $contact['id']); if ($x) { $tabs[] = ['label' => L10n::t('Contacts'), 'url' => "allfriends/" . $contact['id'], @@ -907,7 +894,7 @@ class Contact extends BaseModule } // Show this tab only if there is visible common friend list - $common = GContact::countCommonFriends(local_user(), $contact['id']); + $common = Model\GContact::countCommonFriends(local_user(), $contact['id']); if ($common) { $tabs[] = ['label' => L10n::t('Common Friends'), 'url' => "common/loc/" . local_user() . "/" . $contact['id'], @@ -965,7 +952,7 @@ class Contact extends BaseModule if (DBA::isResult($contact)) { $a->page['aside'] = ""; - $profiledata = Contact::getDetailsByURL($contact["url"]); + $profiledata = Model\Contact::getDetailsByURL($contact["url"]); if (local_user()) { if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { @@ -973,8 +960,8 @@ class Contact extends BaseModule } } - Profile::load($a, "", 0, $profiledata, true); - $o .= Contact::getPostsFromUrl($contact["url"], true, $update); + Model\Profile::load($a, "", 0, $profiledata, true); + $o .= Model\Contact::getPostsFromUrl($contact["url"], true, $update); } return $o; @@ -989,7 +976,7 @@ class Contact extends BaseModule if (DBA::isResult($contact)) { $a->page['aside'] = ""; - $profiledata = Contact::getDetailsByURL($contact["url"]); + $profiledata = Model\Contact::getDetailsByURL($contact["url"]); if (local_user()) { if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { @@ -997,8 +984,8 @@ class Contact extends BaseModule } } - Profile::load($a, "", 0, $profiledata, true); - $o .= Contact::getPostsFromUrl($contact["url"]); + Model\Profile::load($a, "", 0, $profiledata, true); + $o .= Model\Contact::getPostsFromUrl($contact["url"]); } return $o; @@ -1010,17 +997,17 @@ class Contact extends BaseModule $alt_text = ''; switch ($rr['rel']) { - case Contact::FRIEND: + case Model\Contact::FRIEND: $dir_icon = 'images/lrarrow.gif'; $alt_text = L10n::t('Mutual Friendship'); break; - case Contact::FOLLOWER; + case Model\Contact::FOLLOWER; $dir_icon = 'images/larrow.gif'; $alt_text = L10n::t('is a fan of yours'); break; - case Contact::SHARING; + case Model\Contact::SHARING; $dir_icon = 'images/rarrow.gif'; $alt_text = L10n::t('you are a fan of'); break; @@ -1029,7 +1016,7 @@ class Contact extends BaseModule break; } - $url = Contact::magicLink($rr['url']); + $url = Model\Contact::magicLink($rr['url']); if (strpos($url, 'redir/') === 0) { $sparkle = ' class="sparkle" '; @@ -1047,14 +1034,14 @@ class Contact extends BaseModule return [ 'img_hover' => L10n::t('Visit %s\'s profile [%s]', $rr['name'], $rr['url']), 'edit_hover' => L10n::t('Edit contact'), - 'photo_menu' => Contact::photoMenu($rr), + 'photo_menu' => Model\Contact::photoMenu($rr), 'id' => $rr['id'], 'alt_text' => $alt_text, 'dir_icon' => $dir_icon, 'thumb' => ProxyUtils::proxifyUrl($rr['thumb'], false, ProxyUtils::SIZE_THUMB), 'name' => htmlentities($rr['name']), 'username' => htmlentities($rr['name']), - 'account_type' => Contact::getAccountType($rr), + 'account_type' => Model\Contact::getAccountType($rr), 'sparkle' => $sparkle, 'itemurl' => (($rr['addr'] != "") ? $rr['addr'] : $rr['url']), 'url' => $url, @@ -1090,7 +1077,7 @@ class Contact extends BaseModule if ($poll_enabled) { $contact_actions['update'] = [ 'label' => L10n::t('Update now'), - 'url' => 'contacts/' . $contact['id'] . '/update', + 'url' => 'contact/' . $contact['id'] . '/update', 'title' => '', 'sel' => '', 'id' => 'update', @@ -1099,7 +1086,7 @@ class Contact extends BaseModule $contact_actions['block'] = [ 'label' => (intval($contact['blocked']) ? L10n::t('Unblock') : L10n::t('Block')), - 'url' => 'contacts/' . $contact['id'] . '/block', + 'url' => 'contact/' . $contact['id'] . '/block', 'title' => L10n::t('Toggle Blocked status'), 'sel' => (intval($contact['blocked']) ? 'active' : ''), 'id' => 'toggle-block', @@ -1107,7 +1094,7 @@ class Contact extends BaseModule $contact_actions['ignore'] = [ 'label' => (intval($contact['readonly']) ? L10n::t('Unignore') : L10n::t('Ignore')), - 'url' => 'contacts/' . $contact['id'] . '/ignore', + 'url' => 'contact/' . $contact['id'] . '/ignore', 'title' => L10n::t('Toggle Ignored status'), 'sel' => (intval($contact['readonly']) ? 'active' : ''), 'id' => 'toggle-ignore', @@ -1116,7 +1103,7 @@ class Contact extends BaseModule if ($contact['uid'] != 0) { $contact_actions['archive'] = [ 'label' => (intval($contact['archive']) ? L10n::t('Unarchive') : L10n::t('Archive')), - 'url' => 'contacts/' . $contact['id'] . '/archive', + 'url' => 'contact/' . $contact['id'] . '/archive', 'title' => L10n::t('Toggle Archive status'), 'sel' => (intval($contact['archive']) ? 'active' : ''), 'id' => 'toggle-archive', @@ -1124,7 +1111,7 @@ class Contact extends BaseModule $contact_actions['delete'] = [ 'label' => L10n::t('Delete'), - 'url' => 'contacts/' . $contact['id'] . '/drop', + 'url' => 'contact/' . $contact['id'] . '/drop', 'title' => L10n::t('Delete contact'), 'sel' => '', 'id' => 'delete', diff --git a/src/Module/Contacts.php b/src/Module/Contacts.php deleted file mode 100644 index eb21b3b3e1..0000000000 --- a/src/Module/Contacts.php +++ /dev/null @@ -1,1136 +0,0 @@ -page, 'aside')) { - $a->page['aside'] = ''; - } - - $contact_id = null; - $contact = null; - if ((($a->argc == 2) && intval($a->argv[1])) || (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations']))) { - $contact_id = intval($a->argv[1]); - $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); - - if (!DBA::isResult($contact)) { - $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => 0]); - } - - // Don't display contacts that are about to be deleted - if ($contact['network'] == Protocol::PHANTOM) { - $contact = false; - } - } - - if (DBA::isResult($contact)) { - if ($contact['self']) { - if (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations'])) { - goaway('profile/' . $contact['nick']); - } else { - goaway('profile/' . $contact['nick'] . '?tab=profile'); - } - } - - $a->data['contact'] = $contact; - - if (($a->data['contact']['network'] != "") && ($a->data['contact']['network'] != Protocol::DFRN)) { - $networkname = format_network_name($a->data['contact']['network'], $a->data['contact']['url']); - } else { - $networkname = ''; - } - - /// @TODO Add nice spaces - $vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"), [ - '$name' => htmlentities($a->data['contact']['name']), - '$photo' => $a->data['contact']['photo'], - '$url' => Contact::MagicLink($a->data['contact']['url']), - '$addr' => (($a->data['contact']['addr'] != "") ? ($a->data['contact']['addr']) : ""), - '$network_name' => $networkname, - '$network' => L10n::t('Network:'), - '$account_type' => Contact::getAccountType($a->data['contact']) - ]); - - $findpeople_widget = ''; - $follow_widget = ''; - $networks_widget = ''; - } else { - $vcard_widget = ''; - $networks_widget = Widget::networks('contacts', $nets); - if (isset($_GET['add'])) { - $follow_widget = Widget::follow($_GET['add']); - } else { - $follow_widget = Widget::follow(); - } - - $findpeople_widget = Widget::findPeople(); - } - - if ($contact['uid'] != 0) { - $groups_widget = Group::sidebarWidget('contacts', 'group', 'full', 'everyone', $contact_id); - } else { - $groups_widget = null; - } - - $a->page['aside'] .= replace_macros(get_markup_template("contacts-widget-sidebar.tpl"), [ - '$vcard_widget' => $vcard_widget, - '$findpeople_widget' => $findpeople_widget, - '$follow_widget' => $follow_widget, - '$groups_widget' => $groups_widget, - '$networks_widget' => $networks_widget - ]); - - $base = System::baseUrl(); - $tpl = get_markup_template("contacts-head.tpl"); - $a->page['htmlhead'] .= replace_macros($tpl, [ - '$baseurl' => System::baseUrl(true), - '$base' => $base - ]); - } - - private static function batchActions(App $a) - { - if (empty($_POST['contact_batch']) || !is_array($_POST['contact_batch'])) { - return; - } - - $contacts_id = $_POST['contact_batch']; - - $orig_records = q("SELECT * FROM `contact` WHERE `id` IN (%s) AND `uid` = %d AND `self` = 0", - implode(",", $contacts_id), - intval(local_user()) - ); - - $count_actions = 0; - foreach ($orig_records as $orig_record) { - $contact_id = $orig_record['id']; - if (x($_POST, 'contacts_batch_update')) { - self::updateContactFromPoll($contact_id); - $count_actions++; - } - if (x($_POST, 'contacts_batch_block')) { - self::blockContact($contact_id); - $count_actions++; - } - if (x($_POST, 'contacts_batch_ignore')) { - self::ignoreContact($contact_id); - $count_actions++; - } - if (x($_POST, 'contacts_batch_archive')) { - $r = self::archiveContact($contact_id, $orig_record); - if ($r) { - $count_actions++; - } - } - if (x($_POST, 'contacts_batch_drop')) { - self::dropContact($orig_record); - $count_actions++; - } - } - if ($count_actions > 0) { - info(L10n::tt("%d contact edited.", "%d contacts edited.", $count_actions)); - } - - goaway('contacts'); - } - - public static function post() - { - $a = self::getApp(); - - if (!local_user()) { - return; - } - - if ($a->argv[1] === "batch") { - self::batchActions($a); - return; - } - - $contact_id = intval($a->argv[1]); - if (!$contact_id) { - return; - } - - if (!DBA::exists('contact', ['id' => $contact_id, 'uid' => local_user()])) { - notice(L10n::t('Could not access contact record.') . EOL); - goaway('contacts'); - return; // NOTREACHED - } - - Addon::callHooks('contact_edit_post', $_POST); - - $profile_id = intval(defaults($_POST, 'profile-assign', 0)); - if ($profile_id) { - if (!DBA::exists('profile', ['id' => $profile_id, 'uid' => local_user()])) { - notice(L10n::t('Could not locate selected profile.') . EOL); - return; - } - } - - $hidden = intval($_POST['hidden']); - - $notify = intval($_POST['notify']); - - $fetch_further_information = intval(defaults($_POST, 'fetch_further_information', 0)); - - $ffi_keyword_blacklist = escape_tags(trim(defaults($_POST, 'ffi_keyword_blacklist', ''))); - - $priority = intval(defaults($_POST, 'poll', 0)); - if ($priority > 5 || $priority < 0) { - $priority = 0; - } - - $info = escape_tags(trim($_POST['info'])); - - $r = q("UPDATE `contact` SET `profile-id` = %d, `priority` = %d , `info` = '%s', - `hidden` = %d, `notify_new_posts` = %d, `fetch_further_information` = %d, - `ffi_keyword_blacklist` = '%s' WHERE `id` = %d AND `uid` = %d", - intval($profile_id), - intval($priority), - DBA::escape($info), - intval($hidden), - intval($notify), - intval($fetch_further_information), - DBA::escape($ffi_keyword_blacklist), - intval($contact_id), - intval(local_user()) - ); - if (DBA::isResult($r)) { - info(L10n::t('Contact updated.') . EOL); - } else { - notice(L10n::t('Failed to update contact record.') . EOL); - } - - $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); - if (DBA::isResult($contact)) { - $a->data['contact'] = $contact; - } - - return; - } - - /* contact actions */ - - private static function updateContactFromPoll($contact_id) - { - $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()]); - if (!DBA::isResult($contact)) { - return; - } - - $uid = $contact["uid"]; - - if ($contact["network"] == Protocol::OSTATUS) { - $result = Contact::createFromProbe($uid, $contact["url"], false, $contact["network"]); - - if ($result['success']) { - q("UPDATE `contact` SET `subhub` = 1 WHERE `id` = %d", intval($contact_id)); - } - } else { - // pull feed and consume it, which should subscribe to the hub. - Worker::add(PRIORITY_HIGH, "OnePoll", $contact_id, "force"); - } - } - - private static function updateContactFromProbe($contact_id) - { - $contact = DBA::selectFirst('contact', ['uid', 'url', 'network'], ['id' => $contact_id, 'uid' => local_user()]); - if (!DBA::isResult($contact)) { - return; - } - - $uid = $contact["uid"]; - - $data = Probe::uri($contact["url"], "", 0, false); - - // "Feed" or "Unknown" is mostly a sign of communication problems - if ((in_array($data["network"], [Protocol::FEED, Protocol::PHANTOM])) && ($data["network"] != $contact["network"])) { - return; - } - - $updatefields = ["name", "nick", "url", "addr", "batch", "notify", "poll", "request", "confirm", - "poco", "network", "alias"]; - $update = []; - - if ($data["network"] == Protocol::OSTATUS) { - $result = Contact::createFromProbe($uid, $data["url"], false); - - if ($result['success']) { - $update["subhub"] = true; - } - } - - foreach ($updatefields AS $field) { - if (isset($data[$field]) && ($data[$field] != "")) { - $update[$field] = $data[$field]; - } - } - - $update["nurl"] = normalise_link($data["url"]); - - $query = ""; - - if (isset($data["priority"]) && ($data["priority"] != 0)) { - $query = "`priority` = " . intval($data["priority"]); - } - - foreach ($update AS $key => $value) { - if ($query != "") { - $query .= ", "; - } - - $query .= "`" . $key . "` = '" . DBA::escape($value) . "'"; - } - - if ($query == "") { - return; - } - - $r = q("UPDATE `contact` SET $query WHERE `id` = %d AND `uid` = %d", - intval($contact_id), - intval(local_user()) - ); - - // Update the entry in the contact table - Contact::updateAvatar($data['photo'], local_user(), $contact_id, true); - - // Update the entry in the gcontact table - GContact::updateFromProbe($data["url"]); - } - - private static function blockContact($contact_id) - { - $blocked = !Contact::isBlockedByUser($contact_id, local_user()); - Contact::setBlockedForUser($contact_id, local_user(), $blocked); - } - - private static function ignoreContact($contact_id) - { - $ignored = !Contact::isIgnoredByUser($contact_id, local_user()); - Contact::setIgnoredForUser($contact_id, local_user(), $ignored); - } - - private static function archiveContact($contact_id, $orig_record) - { - $archived = (($orig_record['archive']) ? 0 : 1); - $r = q("UPDATE `contact` SET `archive` = %d WHERE `id` = %d AND `uid` = %d", - intval($archived), - intval($contact_id), - intval(local_user()) - ); - return DBA::isResult($r); - } - - private static function dropContact($orig_record) - { - $a = get_app(); - - $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` - WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1", - intval($a->user['uid']) - ); - if (!DBA::isResult($r)) { - return; - } - - Contact::terminateFriendship($r[0], $orig_record, true); - Contact::remove($orig_record['id']); - } - - public static function content($update = 0) - { - $a = self::getApp(); - $sort_type = 0; - $o = ''; - Nav::setSelected('contacts'); - - if (!local_user()) { - notice(L10n::t('Permission denied.') . EOL); - return Login::form(); - } - - if ($a->argc == 3) { - $contact_id = intval($a->argv[1]); - if (!$contact_id) { - return; - } - - $cmd = $a->argv[2]; - - $orig_record = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => [0, local_user()], 'self' => false]); - if (!DBA::isResult($orig_record)) { - notice(L10n::t('Could not access contact record.') . EOL); - goaway('contacts'); - return; // NOTREACHED - } - - if ($cmd === 'update' && ($orig_record['uid'] != 0)) { - self::updateContactFromPoll($contact_id); - goaway('contacts/' . $contact_id); - // NOTREACHED - } - - if ($cmd === 'updateprofile' && ($orig_record['uid'] != 0)) { - self::updateContactFromProbe($contact_id); - goaway('crepair/' . $contact_id); - // NOTREACHED - } - - if ($cmd === 'block') { - self::blockContact($contact_id); - - $blocked = Contact::isBlockedByUser($contact_id, local_user()); - info(($blocked ? L10n::t('Contact has been blocked') : L10n::t('Contact has been unblocked')) . EOL); - - goaway('contacts/' . $contact_id); - return; // NOTREACHED - } - - if ($cmd === 'ignore') { - self::ignoreContact($contact_id); - - $ignored = Contact::isIgnoredByUser($contact_id, local_user()); - info(($ignored ? L10n::t('Contact has been ignored') : L10n::t('Contact has been unignored')) . EOL); - - goaway('contacts/' . $contact_id); - return; // NOTREACHED - } - - if ($cmd === 'archive' && ($orig_record['uid'] != 0)) { - $r = self::archiveContact($contact_id, $orig_record); - if ($r) { - $archived = (($orig_record['archive']) ? 0 : 1); - info((($archived) ? L10n::t('Contact has been archived') : L10n::t('Contact has been unarchived')) . EOL); - } - - goaway('contacts/' . $contact_id); - return; // NOTREACHED - } - - if ($cmd === 'drop' && ($orig_record['uid'] != 0)) { - // Check if we should do HTML-based delete confirmation - if (x($_REQUEST, 'confirm')) { - // can't take arguments in its "action" parameter - // so add any arguments as hidden inputs - $query = explode_querystring($a->query_string); - $inputs = []; - foreach ($query['args'] as $arg) { - if (strpos($arg, 'confirm=') === false) { - $arg_parts = explode('=', $arg); - $inputs[] = ['name' => $arg_parts[0], 'value' => $arg_parts[1]]; - } - } - - $a->page['aside'] = ''; - - return replace_macros(get_markup_template('contact_drop_confirm.tpl'), [ - '$header' => L10n::t('Drop contact'), - '$contact' => self::getContactTemplateVars($orig_record), - '$method' => 'get', - '$message' => L10n::t('Do you really want to delete this contact?'), - '$extra_inputs' => $inputs, - '$confirm' => L10n::t('Yes'), - '$confirm_url' => $query['base'], - '$confirm_name' => 'confirmed', - '$cancel' => L10n::t('Cancel'), - ]); - } - // Now check how the user responded to the confirmation query - if (x($_REQUEST, 'canceled')) { - goaway('contacts'); - } - - self::dropContact($orig_record); - info(L10n::t('Contact has been removed.') . EOL); - - goaway('contacts'); - return; // NOTREACHED - } - if ($cmd === 'posts') { - return self::getPostsHTML($a, $contact_id); - } - if ($cmd === 'conversations') { - return self::getConversationsHMTL($a, $contact_id, $update); - } - } - - $_SESSION['return_url'] = $a->query_string; - - if ((x($a->data, 'contact')) && (is_array($a->data['contact']))) { - $contact_id = $a->data['contact']['id']; - $contact = $a->data['contact']; - - $a->page['htmlhead'] .= replace_macros(get_markup_template('contact_head.tpl'), [ - '$baseurl' => System::baseUrl(true), - ]); - - $contact['blocked'] = Contact::isBlockedByUser($contact['id'], local_user()); - $contact['readonly'] = Contact::isIgnoredByUser($contact['id'], local_user()); - - $dir_icon = ''; - $relation_text = ''; - switch ($contact['rel']) { - case Contact::FRIEND: - $dir_icon = 'images/lrarrow.gif'; - $relation_text = L10n::t('You are mutual friends with %s'); - break; - - case Contact::FOLLOWER; - $dir_icon = 'images/larrow.gif'; - $relation_text = L10n::t('You are sharing with %s'); - break; - - case Contact::SHARING; - $dir_icon = 'images/rarrow.gif'; - $relation_text = L10n::t('%s is sharing with you'); - break; - - default: - break; - } - - if ($contact['uid'] == 0) { - $relation_text = ''; - } - - if (!in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])) { - $relation_text = ""; - } - - $relation_text = sprintf($relation_text, htmlentities($contact['name'])); - - $url = Contact::magicLink($contact['url']); - if (strpos($url, 'redir/') === 0) { - $sparkle = ' class="sparkle" '; - } else { - $sparkle = ''; - } - - $insecure = L10n::t('Private communications are not available for this contact.'); - - $last_update = (($contact['last-update'] <= NULL_DATE) ? L10n::t('Never') : DateTimeFormat::local($contact['last-update'], 'D, j M Y, g:i A')); - - if ($contact['last-update'] > NULL_DATE) { - $last_update .= ' ' . (($contact['last-update'] <= $contact['success_update']) ? L10n::t("\x28Update was successful\x29") : L10n::t("\x28Update was not successful\x29")); - } - $lblsuggest = (($contact['network'] === Protocol::DFRN) ? L10n::t('Suggest friends') : ''); - - $poll_enabled = in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]); - - $nettype = L10n::t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact["url"])); - - // tabs - $tab_str = self::getTabsHTML($a, $contact, 3); - - $lost_contact = (($contact['archive'] && $contact['term-date'] > NULL_DATE && $contact['term-date'] < DateTimeFormat::utcNow()) ? L10n::t('Communications lost with this contact!') : ''); - - $fetch_further_information = null; - if ($contact['network'] == Protocol::FEED) { - $fetch_further_information = [ - 'fetch_further_information', - L10n::t('Fetch further information for feeds'), - $contact['fetch_further_information'], - L10n::t("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."), - ['0' => L10n::t('Disabled'), - '1' => L10n::t('Fetch information'), - '3' => L10n::t('Fetch keywords'), - '2' => L10n::t('Fetch information and keywords') - ] - ]; - } - - $poll_interval = null; - if (in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) { - $poll_interval = ContactSelector::pollInterval($contact['priority'], (!$poll_enabled)); - } - - $profile_select = null; - if ($contact['network'] == Protocol::DFRN) { - $profile_select = ContactSelector::profileAssign($contact['profile-id'], (($contact['network'] !== Protocol::DFRN) ? true : false)); - } - - /// @todo Only show the following link with DFRN when the remote version supports it - $follow = ''; - $follow_text = ''; - if (in_array($contact['rel'], [Contact::FRIEND, Contact::SHARING])) { - if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { - $follow = System::baseUrl(true) . "/unfollow?url=" . urlencode($contact["url"]); - $follow_text = L10n::t("Disconnect/Unfollow"); - } - } else { - $follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]); - $follow_text = L10n::t("Connect/Follow"); - } - - // Load contactact related actions like hide, suggest, delete and others - $contact_actions = self::getContactActions($contact); - - if ($contact['uid'] != 0) { - $lbl_vis1 = L10n::t('Profile Visibility'); - $lbl_info1 = L10n::t('Contact Information / Notes'); - $contact_settings_label = L10n::t('Contact Settings'); - } else { - $lbl_vis1 = null; - $lbl_info1 = null; - $contact_settings_label = null; - } - - $tpl = get_markup_template("contact_edit.tpl"); - $o .= replace_macros($tpl, [ - '$header' => L10n::t("Contact"), - '$tab_str' => $tab_str, - '$submit' => L10n::t('Submit'), - '$lbl_vis1' => $lbl_vis1, - '$lbl_vis2' => L10n::t('Please choose the profile you would like to display to %s when viewing your profile securely.', $contact['name']), - '$lbl_info1' => $lbl_info1, - '$lbl_info2' => L10n::t('Their personal note'), - '$reason' => trim(notags($contact['reason'])), - '$infedit' => L10n::t('Edit contact notes'), - '$common_link' => 'common/loc/' . local_user() . '/' . $contact['id'], - '$relation_text' => $relation_text, - '$visit' => L10n::t('Visit %s\'s profile [%s]', $contact['name'], $contact['url']), - '$blockunblock' => L10n::t('Block/Unblock contact'), - '$ignorecont' => L10n::t('Ignore contact'), - '$lblcrepair' => L10n::t("Repair URL settings"), - '$lblrecent' => L10n::t('View conversations'), - '$lblsuggest' => $lblsuggest, - '$nettype' => $nettype, - '$poll_interval' => $poll_interval, - '$poll_enabled' => $poll_enabled, - '$lastupdtext' => L10n::t('Last update:'), - '$lost_contact' => $lost_contact, - '$updpub' => L10n::t('Update public posts'), - '$last_update' => $last_update, - '$udnow' => L10n::t('Update now'), - '$follow' => $follow, - '$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' => (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') : ''), - '$hidden' => ['hidden', L10n::t('Hide this contact from others'), ($contact['hidden'] == 1), L10n::t('Replies/likes to your public posts may 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, - '$ffi_keyword_blacklist' => $contact['ffi_keyword_blacklist'], - '$ffi_keyword_blacklist' => ['ffi_keyword_blacklist', L10n::t('Blacklisted keywords'), $contact['ffi_keyword_blacklist'], L10n::t('Comma separated list of keywords that should not be converted to hashtags, when "Fetch information and keywords" is selected')], - '$photo' => $contact['photo'], - '$name' => htmlentities($contact['name']), - '$dir_icon' => $dir_icon, - '$sparkle' => $sparkle, - '$url' => $url, - '$profileurllabel' => L10n::t('Profile URL'), - '$profileurl' => $contact['url'], - '$account_type' => Contact::getAccountType($contact), - '$location' => BBCode::convert($contact["location"]), - '$location_label' => L10n::t("Location:"), - '$xmpp' => BBCode::convert($contact["xmpp"]), - '$xmpp_label' => L10n::t("XMPP:"), - '$about' => BBCode::convert($contact["about"], false), - '$about_label' => L10n::t("About:"), - '$keywords' => $contact["keywords"], - '$keywords_label' => L10n::t("Tags:"), - '$contact_action_button' => L10n::t("Actions"), - '$contact_actions' => $contact_actions, - '$contact_status' => L10n::t("Status"), - '$contact_settings_label' => $contact_settings_label, - '$contact_profile_label' => L10n::t("Profile"), - ]); - - $arr = ['contact' => $contact, 'output' => $o]; - - Addon::callHooks('contact_edit', $arr); - - return $arr['output']; - } - - $blocked = false; - $hidden = false; - $ignored = false; - $archived = false; - $all = false; - - if (($a->argc == 2) && ($a->argv[1] === 'all')) { - $sql_extra = ''; - $all = true; - } elseif (($a->argc == 2) && ($a->argv[1] === 'blocked')) { - $sql_extra = " AND `blocked` = 1 "; - $blocked = true; - } elseif (($a->argc == 2) && ($a->argv[1] === 'hidden')) { - $sql_extra = " AND `hidden` = 1 "; - $hidden = true; - } elseif (($a->argc == 2) && ($a->argv[1] === 'ignored')) { - $sql_extra = " AND `readonly` = 1 "; - $ignored = true; - } elseif (($a->argc == 2) && ($a->argv[1] === 'archived')) { - $sql_extra = " AND `archive` = 1 "; - $archived = true; - } else { - $sql_extra = " AND `blocked` = 0 "; - } - - $sql_extra .= sprintf(" AND `network` != '%s' ", Protocol::PHANTOM); - - $search = x($_GET, 'search') ? notags(trim($_GET['search'])) : ''; - $nets = x($_GET, 'nets' ) ? notags(trim($_GET['nets'])) : ''; - - $tabs = [ - [ - 'label' => L10n::t('Suggestions'), - 'url' => 'suggest', - 'sel' => '', - 'title' => L10n::t('Suggest potential friends'), - 'id' => 'suggestions-tab', - 'accesskey' => 'g', - ], - [ - 'label' => L10n::t('All Contacts'), - 'url' => 'contacts/all', - 'sel' => ($all) ? 'active' : '', - 'title' => L10n::t('Show all contacts'), - 'id' => 'showall-tab', - 'accesskey' => 'l', - ], - [ - 'label' => L10n::t('Unblocked'), - 'url' => 'contacts', - 'sel' => ((!$all) && (!$blocked) && (!$hidden) && (!$search) && (!$nets) && (!$ignored) && (!$archived)) ? 'active' : '', - 'title' => L10n::t('Only show unblocked contacts'), - 'id' => 'showunblocked-tab', - 'accesskey' => 'o', - ], - [ - 'label' => L10n::t('Blocked'), - 'url' => 'contacts/blocked', - 'sel' => ($blocked) ? 'active' : '', - 'title' => L10n::t('Only show blocked contacts'), - 'id' => 'showblocked-tab', - 'accesskey' => 'b', - ], - [ - 'label' => L10n::t('Ignored'), - 'url' => 'contacts/ignored', - 'sel' => ($ignored) ? 'active' : '', - 'title' => L10n::t('Only show ignored contacts'), - 'id' => 'showignored-tab', - 'accesskey' => 'i', - ], - [ - 'label' => L10n::t('Archived'), - 'url' => 'contacts/archived', - 'sel' => ($archived) ? 'active' : '', - 'title' => L10n::t('Only show archived contacts'), - 'id' => 'showarchived-tab', - 'accesskey' => 'y', - ], - [ - 'label' => L10n::t('Hidden'), - 'url' => 'contacts/hidden', - 'sel' => ($hidden) ? 'active' : '', - 'title' => L10n::t('Only show hidden contacts'), - 'id' => 'showhidden-tab', - 'accesskey' => 'h', - ], - ]; - - $tab_tpl = get_markup_template('common_tabs.tpl'); - $t = replace_macros($tab_tpl, ['$tabs' => $tabs]); - - $total = 0; - $searching = false; - $search_hdr = null; - if ($search) { - $searching = true; - $search_hdr = $search; - $search_txt = DBA::escape(protect_sprintf(preg_quote($search))); - $sql_extra .= " AND (name REGEXP '$search_txt' OR url REGEXP '$search_txt' OR nick REGEXP '$search_txt') "; - } - - if ($nets) { - $sql_extra .= sprintf(" AND network = '%s' ", DBA::escape($nets)); - } - - $sql_extra2 = ((($sort_type > 0) && ($sort_type <= Contact::FRIEND)) ? sprintf(" AND `rel` = %d ", intval($sort_type)) : ''); - - $r = q("SELECT COUNT(*) AS `total` FROM `contact` - WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 ", - intval($_SESSION['uid']) - ); - if (DBA::isResult($r)) { - $a->setPagerTotal($r[0]['total']); - $total = $r[0]['total']; - } - - $sql_extra3 = Widget::unavailableNetworks(); - - $contacts = []; - - $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 $sql_extra3 ORDER BY `name` ASC LIMIT %d , %d ", - intval($_SESSION['uid']), - intval($a->pager['start']), - intval($a->pager['itemspage']) - ); - if (DBA::isResult($r)) { - foreach ($r as $rr) { - $rr['blocked'] = Contact::isBlockedByUser($rr['id'], local_user()); - $rr['readonly'] = Contact::isIgnoredByUser($rr['id'], local_user()); - $contacts[] = self::getContactTemplateVars($rr); - } - } - - $tpl = get_markup_template("contacts-template.tpl"); - $o .= replace_macros($tpl, [ - '$baseurl' => System::baseUrl(), - '$header' => L10n::t('Contacts') . (($nets) ? ' - ' . ContactSelector::networkToName($nets) : ''), - '$tabs' => $t, - '$total' => $total, - '$search' => $search_hdr, - '$desc' => L10n::t('Search your contacts'), - '$finding' => $searching ? L10n::t('Results for: %s', $search) : "", - '$submit' => L10n::t('Find'), - '$cmd' => $a->cmd, - '$contacts' => $contacts, - '$contact_drop_confirm' => L10n::t('Do you really want to delete this contact?'), - 'multiselect' => 1, - '$batch_actions' => [ - 'contacts_batch_update' => L10n::t('Update'), - 'contacts_batch_block' => L10n::t('Block') . "/" . L10n::t("Unblock"), - "contacts_batch_ignore" => L10n::t('Ignore') . "/" . L10n::t("Unignore"), - "contacts_batch_archive" => L10n::t('Archive') . "/" . L10n::t("Unarchive"), - "contacts_batch_drop" => L10n::t('Delete'), - ], - '$h_batch_actions' => L10n::t('Batch Actions'), - '$paginate' => paginate($a), - ]); - - return $o; - } - - /** - * @brief List of pages for the Contact TabBar - * - * Available Pages are 'Status', 'Profile', 'Contacts' and 'Common Friends' - * - * @param App $a - * @param array $contact The contact array - * @param int $active_tab 1 if tab should be marked as active - * - * @return string - */ - public static function getTabsHTML($a, $contact, $active_tab) - { - // tabs - $tabs = [ - [ - 'label' => L10n::t('Status'), - 'url' => "contacts/" . $contact['id'] . "/conversations", - 'sel' => (($active_tab == 1) ? 'active' : ''), - 'title' => L10n::t('Conversations started by this contact'), - 'id' => 'status-tab', - 'accesskey' => 'm', - ], - [ - 'label' => L10n::t('Posts and Comments'), - 'url' => "contacts/" . $contact['id'] . "/posts", - 'sel' => (($active_tab == 2) ? 'active' : ''), - 'title' => L10n::t('Status Messages and Posts'), - 'id' => 'posts-tab', - 'accesskey' => 'p', - ], - [ - 'label' => L10n::t('Profile'), - 'url' => "contacts/" . $contact['id'], - 'sel' => (($active_tab == 3) ? 'active' : ''), - 'title' => L10n::t('Profile Details'), - 'id' => 'profile-tab', - 'accesskey' => 'o', - ] - ]; - - // Show this tab only if there is visible friend list - $x = GContact::countAllFriends(local_user(), $contact['id']); - if ($x) { - $tabs[] = ['label' => L10n::t('Contacts'), - 'url' => "allfriends/" . $contact['id'], - 'sel' => (($active_tab == 4) ? 'active' : ''), - 'title' => L10n::t('View all contacts'), - 'id' => 'allfriends-tab', - 'accesskey' => 't']; - } - - // Show this tab only if there is visible common friend list - $common = GContact::countCommonFriends(local_user(), $contact['id']); - if ($common) { - $tabs[] = ['label' => L10n::t('Common Friends'), - 'url' => "common/loc/" . local_user() . "/" . $contact['id'], - 'sel' => (($active_tab == 5) ? 'active' : ''), - 'title' => L10n::t('View all common friends'), - 'id' => 'common-loc-tab', - 'accesskey' => 'd' - ]; - } - - if (!empty($contact['uid'])) { - $tabs[] = ['label' => L10n::t('Advanced'), - 'url' => 'crepair/' . $contact['id'], - 'sel' => (($active_tab == 6) ? 'active' : ''), - 'title' => L10n::t('Advanced Contact Settings'), - 'id' => 'advanced-tab', - 'accesskey' => 'r' - ]; - } - - $tab_tpl = get_markup_template('common_tabs.tpl'); - $tab_str = replace_macros($tab_tpl, ['$tabs' => $tabs]); - - return $tab_str; - } - - private static function getConversationsHMTL($a, $contact_id, $update) - { - $o = ''; - - if (!$update) { - // We need the editor here to be able to reshare an item. - if (local_user()) { - $x = [ - 'is_owner' => true, - 'allow_location' => $a->user['allow_location'], - 'default_location' => $a->user['default-location'], - 'nickname' => $a->user['nickname'], - 'lockstate' => (is_array($a->user) && (strlen($a->user['allow_cid']) || strlen($a->user['allow_gid']) || strlen($a->user['deny_cid']) || strlen($a->user['deny_gid'])) ? 'lock' : 'unlock'), - 'acl' => ACL::getFullSelectorHTML($a->user, true), - 'bang' => '', - 'visitor' => 'block', - 'profile_uid' => local_user(), - ]; - $o = status_editor($a, $x, 0, true); - } - } - - $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); - - if (!$update) { - $o .= self::getTabsHTML($a, $contact, 1); - } - - if (DBA::isResult($contact)) { - $a->page['aside'] = ""; - - $profiledata = Contact::getDetailsByURL($contact["url"]); - - if (local_user()) { - if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { - $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]); - } - } - - Profile::load($a, "", 0, $profiledata, true); - $o .= Contact::getPostsFromUrl($contact["url"], true, $update); - } - - return $o; - } - - private static function getPostsHTML($a, $contact_id) - { - $contact = DBA::selectFirst('contact', ['uid', 'url', 'id'], ['id' => $contact_id]); - - $o = self::getTabsHTML($a, $contact, 2); - - if (DBA::isResult($contact)) { - $a->page['aside'] = ""; - - $profiledata = Contact::getDetailsByURL($contact["url"]); - - if (local_user()) { - if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { - $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]); - } - } - - Profile::load($a, "", 0, $profiledata, true); - $o .= Contact::getPostsFromUrl($contact["url"]); - } - - return $o; - } - - public static function getContactTemplateVars(array $rr) - { - $dir_icon = ''; - $alt_text = ''; - - switch ($rr['rel']) { - case Contact::FRIEND: - $dir_icon = 'images/lrarrow.gif'; - $alt_text = L10n::t('Mutual Friendship'); - break; - - case Contact::FOLLOWER; - $dir_icon = 'images/larrow.gif'; - $alt_text = L10n::t('is a fan of yours'); - break; - - case Contact::SHARING; - $dir_icon = 'images/rarrow.gif'; - $alt_text = L10n::t('you are a fan of'); - break; - - default: - break; - } - - $url = Contact::magicLink($rr['url']); - - if (strpos($url, 'redir/') === 0) { - $sparkle = ' class="sparkle" '; - } else { - $sparkle = ''; - } - - if ($rr['self']) { - $dir_icon = 'images/larrow.gif'; - $alt_text = L10n::t('This is you'); - $url = $rr['url']; - $sparkle = ''; - } - - return [ - 'img_hover' => L10n::t('Visit %s\'s profile [%s]', $rr['name'], $rr['url']), - 'edit_hover' => L10n::t('Edit contact'), - 'photo_menu' => Contact::photoMenu($rr), - 'id' => $rr['id'], - 'alt_text' => $alt_text, - 'dir_icon' => $dir_icon, - 'thumb' => ProxyUtils::proxifyUrl($rr['thumb'], false, ProxyUtils::SIZE_THUMB), - 'name' => htmlentities($rr['name']), - 'username' => htmlentities($rr['name']), - 'account_type' => Contact::getAccountType($rr), - 'sparkle' => $sparkle, - 'itemurl' => (($rr['addr'] != "") ? $rr['addr'] : $rr['url']), - 'url' => $url, - 'network' => ContactSelector::networkToName($rr['network'], $rr['url']), - 'nick' => htmlentities($rr['nick']), - ]; - } - - /** - * @brief Gives a array with actions which can performed to a given contact - * - * This includes actions like e.g. 'block', 'hide', 'archive', 'delete' and others - * - * @param array $contact Data about the Contact - * @return array with contact related actions - */ - private static function getContactActions($contact) - { - $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 - if ($contact['network'] === Protocol::DFRN) { - $contact_actions['suggest'] = [ - 'label' => L10n::t('Suggest friends'), - 'url' => 'fsuggest/' . $contact['id'], - 'title' => '', - 'sel' => '', - 'id' => 'suggest', - ]; - } - - if ($poll_enabled) { - $contact_actions['update'] = [ - 'label' => L10n::t('Update now'), - 'url' => 'contacts/' . $contact['id'] . '/update', - 'title' => '', - 'sel' => '', - 'id' => 'update', - ]; - } - - $contact_actions['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' : ''), - 'id' => 'toggle-block', - ]; - - $contact_actions['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' : ''), - 'id' => 'toggle-ignore', - ]; - - if ($contact['uid'] != 0) { - $contact_actions['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' : ''), - 'id' => 'toggle-archive', - ]; - - $contact_actions['delete'] = [ - 'label' => L10n::t('Delete'), - 'url' => 'contacts/' . $contact['id'] . '/drop', - 'title' => L10n::t('Delete contact'), - 'sel' => '', - 'id' => 'delete', - ]; - } - - return $contact_actions; - } -} diff --git a/util/messages.po b/util/messages.po index c27fb25627..6365f6cc0d 100644 --- a/util/messages.po +++ b/util/messages.po @@ -51,7 +51,7 @@ msgstr "" #: mod/profile_photo.php:198 mod/wall_attach.php:80 mod/wall_attach.php:83 #: 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:387 mod/events.php:195 mod/follow.php:54 mod/follow.php:118 +#: mod/contact.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:1067 @@ -94,7 +94,7 @@ msgstr "" #: view/theme/vier/config.php:119 view/theme/frio/config.php:118 #: 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:631 mod/events.php:560 +#: mod/fsuggest.php:114 mod/contact.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 @@ -186,7 +186,7 @@ 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:611 mod/follow.php:143 +#: mod/allfriends.php:76 mod/contact.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:845 +#: view/theme/vier/theme.php:201 mod/directory.php:214 mod/contact.php:845 #: src/Content/Widget.php:63 msgid "Find" msgstr "" @@ -320,7 +320,7 @@ msgstr "" msgid "End this session" msgstr "" -#: view/theme/frio/theme.php:269 mod/contacts.php:690 mod/contacts.php:880 +#: view/theme/frio/theme.php:269 mod/contact.php:690 mod/contact.php:880 #: src/Model/Profile.php:888 src/Content/Nav.php:100 msgid "Status" msgstr "" @@ -331,7 +331,7 @@ msgid "Your posts and conversations" msgstr "" #: view/theme/frio/theme.php:270 mod/newmember.php:24 mod/profperm.php:116 -#: mod/contacts.php:692 mod/contacts.php:896 src/Model/Profile.php:730 +#: mod/contact.php:692 mod/contact.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 "" @@ -400,7 +400,7 @@ msgid "Account settings" msgstr "" #: view/theme/frio/theme.php:280 include/text.php:906 mod/viewcontacts.php:125 -#: mod/contacts.php:839 mod/contacts.php:908 src/Model/Profile.php:967 +#: mod/contact.php:839 mod/contact.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 "" @@ -475,7 +475,7 @@ msgstr "" #: 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:471 mod/follow.php:150 mod/profiles.php:541 +#: mod/api.php:110 mod/contact.php:471 mod/follow.php:150 mod/profiles.php:541 #: mod/profiles.php:544 mod/profiles.php:566 msgid "Yes" msgstr "" @@ -483,7 +483,7 @@ msgstr "" #: 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:146 mod/contacts.php:474 +#: mod/dfrn_request.php:655 mod/editpost.php:146 mod/contact.php:474 #: mod/follow.php:161 mod/fbrowser.php:104 mod/fbrowser.php:135 #: mod/photos.php:255 mod/photos.php:327 msgid "Cancel" @@ -586,7 +586,7 @@ msgid "Select" msgstr "" #: include/conversation.php:627 mod/settings.php:736 mod/admin.php:1906 -#: mod/contacts.php:855 mod/contacts.php:1133 mod/photos.php:1567 +#: mod/contact.php:855 mod/contact.php:1133 mod/photos.php:1567 msgid "Delete" msgstr "" @@ -2014,7 +2014,7 @@ msgstr "" msgid "Only logged in users are permitted to perform a probing." msgstr "" -#: mod/directory.php:151 mod/notifications.php:248 mod/contacts.php:681 +#: mod/directory.php:151 mod/notifications.php:248 mod/contact.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:" @@ -2033,7 +2033,7 @@ msgstr "" msgid "Homepage:" msgstr "" -#: mod/directory.php:159 mod/notifications.php:250 mod/contacts.php:685 +#: mod/directory.php:159 mod/notifications.php:250 mod/contact.php:685 #: src/Model/Profile.php:436 src/Model/Profile.php:806 msgid "About:" msgstr "" @@ -2114,7 +2114,7 @@ msgstr "" msgid "Missing some important data!" msgstr "" -#: mod/settings.php:176 mod/settings.php:701 mod/contacts.php:851 +#: mod/settings.php:176 mod/settings.php:701 mod/contact.php:851 msgid "Update" msgstr "" @@ -3006,7 +3006,7 @@ msgstr "" msgid "Items tagged with: %s" msgstr "" -#: mod/search.php:248 mod/contacts.php:844 +#: mod/search.php:248 mod/contact.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:919 +#: mod/common.php:142 mod/contact.php:919 msgid "Common Friends" msgstr "" @@ -3177,7 +3177,7 @@ msgstr "" msgid "Members" msgstr "" -#: mod/group.php:246 mod/contacts.php:742 +#: mod/group.php:246 mod/contact.php:742 msgid "All Contacts" msgstr "" @@ -3301,7 +3301,7 @@ msgstr "" msgid "No contacts." msgstr "" -#: mod/viewcontacts.php:106 mod/contacts.php:640 mod/contacts.php:1055 +#: mod/viewcontacts.php:106 mod/contact.php:640 mod/contact.php:1055 #, php-format msgid "Visit %s's profile [%s]" msgstr "" @@ -3318,7 +3318,7 @@ msgstr "" msgid "Contact unfollowed" msgstr "" -#: mod/unfollow.php:113 mod/contacts.php:607 +#: mod/unfollow.php:113 mod/contact.php:607 msgid "Disconnect/Unfollow" msgstr "" @@ -3331,11 +3331,11 @@ 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 +#: mod/admin.php:500 mod/admin.php:510 mod/contact.php:677 mod/follow.php:166 msgid "Profile URL" msgstr "" -#: mod/unfollow.php:145 mod/contacts.php:891 mod/follow.php:189 +#: mod/unfollow.php:145 mod/contact.php:891 mod/follow.php:189 #: src/Model/Profile.php:891 msgid "Status Messages and Posts" msgstr "" @@ -3472,7 +3472,7 @@ msgid "Discard" msgstr "" #: mod/notifications.php:57 mod/notifications.php:181 mod/notifications.php:266 -#: mod/contacts.php:659 mod/contacts.php:853 mod/contacts.php:1116 +#: mod/contact.php:659 mod/contact.php:853 mod/contact.php:1116 msgid "Ignore" msgstr "" @@ -3520,7 +3520,7 @@ msgstr "" msgid "Suggested by:" msgstr "" -#: mod/notifications.php:176 mod/notifications.php:255 mod/contacts.php:667 +#: mod/notifications.php:176 mod/notifications.php:255 mod/contact.php:667 msgid "Hide this contact from others" msgstr "" @@ -3577,12 +3577,12 @@ msgstr "" msgid "Subscriber" msgstr "" -#: mod/notifications.php:252 mod/contacts.php:687 mod/follow.php:177 +#: mod/notifications.php:252 mod/contact.php:687 mod/follow.php:177 #: src/Model/Profile.php:794 msgid "Tags:" msgstr "" -#: mod/notifications.php:261 mod/contacts.php:81 src/Model/Profile.php:533 +#: mod/notifications.php:261 mod/contact.php:81 src/Model/Profile.php:533 msgid "Network:" msgstr "" @@ -4500,13 +4500,13 @@ msgstr "" msgid "select none" msgstr "" -#: mod/admin.php:494 mod/admin.php:1907 mod/contacts.php:658 -#: mod/contacts.php:852 mod/contacts.php:1108 +#: mod/admin.php:494 mod/admin.php:1907 mod/contact.php:658 +#: mod/contact.php:852 mod/contact.php:1108 msgid "Block" msgstr "" -#: mod/admin.php:495 mod/admin.php:1909 mod/contacts.php:658 -#: mod/contacts.php:852 mod/contacts.php:1108 +#: mod/admin.php:495 mod/admin.php:1909 mod/contact.php:658 +#: mod/contact.php:852 mod/contact.php:1108 msgid "Unblock" msgstr "" @@ -4769,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:583 +#: mod/contact.php:583 msgid "Disabled" msgstr "" @@ -4849,7 +4849,7 @@ msgstr "" msgid "Policies" msgstr "" -#: mod/admin.php:1431 mod/contacts.php:929 mod/events.php:562 +#: mod/admin.php:1431 mod/contact.php:929 mod/events.php:562 #: src/Model/Profile.php:865 msgid "Advanced" msgstr "" @@ -6143,7 +6143,7 @@ msgstr "" msgid "Disallowed profile URL." msgstr "" -#: mod/dfrn_request.php:412 mod/contacts.php:241 +#: mod/dfrn_request.php:412 mod/contact.php:241 msgid "Failed to update contact record." msgstr "" @@ -6552,364 +6552,364 @@ msgstr "" msgid "No friends to display." msgstr "" -#: mod/contacts.php:168 +#: mod/contact.php:168 #, php-format msgid "%d contact edited." msgid_plural "%d contacts edited." msgstr[0] "" msgstr[1] "" -#: mod/contacts.php:195 mod/contacts.php:401 +#: mod/contact.php:195 mod/contact.php:401 msgid "Could not access contact record." msgstr "" -#: mod/contacts.php:205 +#: mod/contact.php:205 msgid "Could not locate selected profile." msgstr "" -#: mod/contacts.php:239 +#: mod/contact.php:239 msgid "Contact updated." msgstr "" -#: mod/contacts.php:422 +#: mod/contact.php:422 msgid "Contact has been blocked" msgstr "" -#: mod/contacts.php:422 +#: mod/contact.php:422 msgid "Contact has been unblocked" msgstr "" -#: mod/contacts.php:432 +#: mod/contact.php:432 msgid "Contact has been ignored" msgstr "" -#: mod/contacts.php:432 +#: mod/contact.php:432 msgid "Contact has been unignored" msgstr "" -#: mod/contacts.php:442 +#: mod/contact.php:442 msgid "Contact has been archived" msgstr "" -#: mod/contacts.php:442 +#: mod/contact.php:442 msgid "Contact has been unarchived" msgstr "" -#: mod/contacts.php:466 +#: mod/contact.php:466 msgid "Drop contact" msgstr "" -#: mod/contacts.php:469 mod/contacts.php:848 +#: mod/contact.php:469 mod/contact.php:848 msgid "Do you really want to delete this contact?" msgstr "" -#: mod/contacts.php:487 +#: mod/contact.php:487 msgid "Contact has been removed." msgstr "" -#: mod/contacts.php:524 +#: mod/contact.php:524 #, php-format msgid "You are mutual friends with %s" msgstr "" -#: mod/contacts.php:529 +#: mod/contact.php:529 #, php-format msgid "You are sharing with %s" msgstr "" -#: mod/contacts.php:534 +#: mod/contact.php:534 #, php-format msgid "%s is sharing with you" msgstr "" -#: mod/contacts.php:558 +#: mod/contact.php:558 msgid "Private communications are not available for this contact." msgstr "" -#: mod/contacts.php:560 +#: mod/contact.php:560 msgid "Never" msgstr "" -#: mod/contacts.php:563 +#: mod/contact.php:563 msgid "(Update was successful)" msgstr "" -#: mod/contacts.php:563 +#: mod/contact.php:563 msgid "(Update was not successful)" msgstr "" -#: mod/contacts.php:565 mod/contacts.php:1089 +#: mod/contact.php:565 mod/contact.php:1089 msgid "Suggest friends" msgstr "" -#: mod/contacts.php:569 +#: mod/contact.php:569 #, php-format msgid "Network type: %s" msgstr "" -#: mod/contacts.php:574 +#: mod/contact.php:574 msgid "Communications lost with this contact!" msgstr "" -#: mod/contacts.php:580 +#: mod/contact.php:580 msgid "Fetch further information for feeds" msgstr "" -#: mod/contacts.php:582 +#: mod/contact.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:584 +#: mod/contact.php:584 msgid "Fetch information" msgstr "" -#: mod/contacts.php:585 +#: mod/contact.php:585 msgid "Fetch keywords" msgstr "" -#: mod/contacts.php:586 +#: mod/contact.php:586 msgid "Fetch information and keywords" msgstr "" -#: mod/contacts.php:618 +#: mod/contact.php:618 msgid "Profile Visibility" msgstr "" -#: mod/contacts.php:619 +#: mod/contact.php:619 msgid "Contact Information / Notes" msgstr "" -#: mod/contacts.php:620 +#: mod/contact.php:620 msgid "Contact Settings" msgstr "" -#: mod/contacts.php:629 +#: mod/contact.php:629 msgid "Contact" msgstr "" -#: mod/contacts.php:633 +#: mod/contact.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:635 +#: mod/contact.php:635 msgid "Their personal note" msgstr "" -#: mod/contacts.php:637 +#: mod/contact.php:637 msgid "Edit contact notes" msgstr "" -#: mod/contacts.php:641 +#: mod/contact.php:641 msgid "Block/Unblock contact" msgstr "" -#: mod/contacts.php:642 +#: mod/contact.php:642 msgid "Ignore contact" msgstr "" -#: mod/contacts.php:643 +#: mod/contact.php:643 msgid "Repair URL settings" msgstr "" -#: mod/contacts.php:644 +#: mod/contact.php:644 msgid "View conversations" msgstr "" -#: mod/contacts.php:649 +#: mod/contact.php:649 msgid "Last update:" msgstr "" -#: mod/contacts.php:651 +#: mod/contact.php:651 msgid "Update public posts" msgstr "" -#: mod/contacts.php:653 mod/contacts.php:1099 +#: mod/contact.php:653 mod/contact.php:1099 msgid "Update now" msgstr "" -#: mod/contacts.php:659 mod/contacts.php:853 mod/contacts.php:1116 +#: mod/contact.php:659 mod/contact.php:853 mod/contact.php:1116 msgid "Unignore" msgstr "" -#: mod/contacts.php:663 +#: mod/contact.php:663 msgid "Currently blocked" msgstr "" -#: mod/contacts.php:664 +#: mod/contact.php:664 msgid "Currently ignored" msgstr "" -#: mod/contacts.php:665 +#: mod/contact.php:665 msgid "Currently archived" msgstr "" -#: mod/contacts.php:666 +#: mod/contact.php:666 msgid "Awaiting connection acknowledge" msgstr "" -#: mod/contacts.php:667 +#: mod/contact.php:667 msgid "" "Replies/likes to your public posts may still be visible" msgstr "" -#: mod/contacts.php:668 +#: mod/contact.php:668 msgid "Notification for new posts" msgstr "" -#: mod/contacts.php:668 +#: mod/contact.php:668 msgid "Send a notification of every new post of this contact" msgstr "" -#: mod/contacts.php:671 +#: mod/contact.php:671 msgid "Blacklisted keywords" msgstr "" -#: mod/contacts.php:671 +#: mod/contact.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:683 src/Model/Profile.php:437 +#: mod/contact.php:683 src/Model/Profile.php:437 msgid "XMPP:" msgstr "" -#: mod/contacts.php:688 +#: mod/contact.php:688 msgid "Actions" msgstr "" -#: mod/contacts.php:734 +#: mod/contact.php:734 msgid "Suggestions" msgstr "" -#: mod/contacts.php:737 +#: mod/contact.php:737 msgid "Suggest potential friends" msgstr "" -#: mod/contacts.php:745 +#: mod/contact.php:745 msgid "Show all contacts" msgstr "" -#: mod/contacts.php:750 +#: mod/contact.php:750 msgid "Unblocked" msgstr "" -#: mod/contacts.php:753 +#: mod/contact.php:753 msgid "Only show unblocked contacts" msgstr "" -#: mod/contacts.php:758 +#: mod/contact.php:758 msgid "Blocked" msgstr "" -#: mod/contacts.php:761 +#: mod/contact.php:761 msgid "Only show blocked contacts" msgstr "" -#: mod/contacts.php:766 +#: mod/contact.php:766 msgid "Ignored" msgstr "" -#: mod/contacts.php:769 +#: mod/contact.php:769 msgid "Only show ignored contacts" msgstr "" -#: mod/contacts.php:774 +#: mod/contact.php:774 msgid "Archived" msgstr "" -#: mod/contacts.php:777 +#: mod/contact.php:777 msgid "Only show archived contacts" msgstr "" -#: mod/contacts.php:782 +#: mod/contact.php:782 msgid "Hidden" msgstr "" -#: mod/contacts.php:785 +#: mod/contact.php:785 msgid "Only show hidden contacts" msgstr "" -#: mod/contacts.php:843 +#: mod/contact.php:843 msgid "Search your contacts" msgstr "" -#: mod/contacts.php:854 mod/contacts.php:1125 +#: mod/contact.php:854 mod/contact.php:1125 msgid "Archive" msgstr "" -#: mod/contacts.php:854 mod/contacts.php:1125 +#: mod/contact.php:854 mod/contact.php:1125 msgid "Unarchive" msgstr "" -#: mod/contacts.php:857 +#: mod/contact.php:857 msgid "Batch Actions" msgstr "" -#: mod/contacts.php:883 +#: mod/contact.php:883 msgid "Conversations started by this contact" msgstr "" -#: mod/contacts.php:888 +#: mod/contact.php:888 msgid "Posts and Comments" msgstr "" -#: mod/contacts.php:899 src/Model/Profile.php:899 +#: mod/contact.php:899 src/Model/Profile.php:899 msgid "Profile Details" msgstr "" -#: mod/contacts.php:911 +#: mod/contact.php:911 msgid "View all contacts" msgstr "" -#: mod/contacts.php:922 +#: mod/contact.php:922 msgid "View all common friends" msgstr "" -#: mod/contacts.php:932 +#: mod/contact.php:932 msgid "Advanced Contact Settings" msgstr "" -#: mod/contacts.php:1022 +#: mod/contact.php:1022 msgid "Mutual Friendship" msgstr "" -#: mod/contacts.php:1027 +#: mod/contact.php:1027 msgid "is a fan of yours" msgstr "" -#: mod/contacts.php:1032 +#: mod/contact.php:1032 msgid "you are a fan of" msgstr "" -#: mod/contacts.php:1049 mod/photos.php:1496 mod/photos.php:1535 +#: mod/contact.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:1056 +#: mod/contact.php:1056 msgid "Edit contact" msgstr "" -#: mod/contacts.php:1110 +#: mod/contact.php:1110 msgid "Toggle Blocked status" msgstr "" -#: mod/contacts.php:1118 +#: mod/contact.php:1118 msgid "Toggle Ignored status" msgstr "" -#: mod/contacts.php:1127 +#: mod/contact.php:1127 msgid "Toggle Archive status" msgstr "" -#: mod/contacts.php:1135 +#: mod/contact.php:1135 msgid "Delete contact" msgstr "" diff --git a/view/templates/contacts-template.tpl b/view/templates/contacts-template.tpl index bec295924e..d85fcfb5af 100644 --- a/view/templates/contacts-template.tpl +++ b/view/templates/contacts-template.tpl @@ -14,7 +14,7 @@ {{$tabs}} - + {{foreach $contacts as $contact}} {{include file="contact_template.tpl"}} {{/foreach}} diff --git a/view/templates/crepair.tpl b/view/templates/crepair.tpl index ba04073b60..72528bd261 100644 --- a/view/templates/crepair.tpl +++ b/view/templates/crepair.tpl @@ -15,7 +15,7 @@
      {{if $update_profile}} - {{$udprofilenow}} + {{$udprofilenow}} {{/if}}
      diff --git a/view/theme/frio/templates/contact_edit.tpl b/view/theme/frio/templates/contact_edit.tpl index 3db3fde032..4c12948dce 100644 --- a/view/theme/frio/templates/contact_edit.tpl +++ b/view/theme/frio/templates/contact_edit.tpl @@ -45,7 +45,7 @@ {{if $poll_enabled}}
    • {{$lastupdtext}} {{$last_update}}
      {{if $poll_interval}} - + {{$updpub}} {{$poll_interval}}
    • diff --git a/view/theme/frio/templates/contacts-template.tpl b/view/theme/frio/templates/contacts-template.tpl index 6f64224015..705e377ed3 100644 --- a/view/theme/frio/templates/contacts-template.tpl +++ b/view/theme/frio/templates/contacts-template.tpl @@ -28,7 +28,7 @@
      {{* we need the form container to make batch actions work *}} -
      + {{* we put here a hidden input element. This is needed to transmit the batch actions with javascript*}} diff --git a/view/theme/frio/templates/crepair.tpl b/view/theme/frio/templates/crepair.tpl index 22605bb7a5..3d45c6ddca 100644 --- a/view/theme/frio/templates/crepair.tpl +++ b/view/theme/frio/templates/crepair.tpl @@ -17,7 +17,7 @@
      {{if $update_profile}} - {{$udprofilenow}} + {{$udprofilenow}} {{/if}}
      diff --git a/view/theme/frio/theme.php b/view/theme/frio/theme.php index 79ec421d2b..58904911c1 100644 --- a/view/theme/frio/theme.php +++ b/view/theme/frio/theme.php @@ -278,7 +278,7 @@ function frio_remote_nav($a, &$nav) $nav['events'] = [$server_url . '/events', L10n::t('Events'), '', L10n::t('Events and Calendar')]; $nav['messages'] = [$server_url . '/message', L10n::t('Messages'), '', L10n::t('Private mail')]; $nav['settings'] = [$server_url . '/settings', L10n::t('Settings'), '', L10n::t('Account settings')]; - $nav['contacts'] = [$server_url . '/contacts', L10n::t('Contacts'), '', L10n::t('Manage/edit friends and contacts')]; + $nav['contacts'] = [$server_url . '/contact', L10n::t('Contacts'), '', L10n::t('Manage/edit friends and contacts')]; $nav['sitename'] = Config::get('config', 'sitename'); } } @@ -287,7 +287,7 @@ function frio_remote_nav($a, &$nav) * @brief: Search for contacts * * This function search for a users contacts. The code is copied from contact search - * in /mod/contacts.php. With this function the contacts will permitted to acl_lookup() + * in /src/Module/Contact.php. With this function the contacts will permitted to acl_lookup() * and can grabbed as json. For this we use the type="r". This is usful to to let js * grab the contact data. * We use this to give the data to textcomplete and have a filter function at the @@ -301,7 +301,7 @@ function frio_acl_lookup(App $a, &$results) $nets = x($_GET, 'nets') ? notags(trim($_GET['nets'])) : ''; // we introduce a new search type, r should do the same query like it's - // done in /mod/contacts for connections + // done in /src/Module/Contact.php for connections if ($results['type'] !== 'r') { return; } From d23386f9b2a556eb852da7e03a7f0002ce6b24d3 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 13 Oct 2018 13:17:10 +0000 Subject: [PATCH 362/428] Catching error when compacting doesn't work --- src/Util/JsonLD.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Util/JsonLD.php b/src/Util/JsonLD.php index cf23276d75..5380c3c542 100644 --- a/src/Util/JsonLD.php +++ b/src/Util/JsonLD.php @@ -92,7 +92,14 @@ class JsonLD $jsonobj = json_decode(json_encode($json, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); - $compacted = jsonld_compact($jsonobj, $context); + + 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); } From c32ac7f194a31ecd4a2eb750351abfc4c44fcf80 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Mon, 8 Oct 2018 02:15:27 +0200 Subject: [PATCH 363/428] Install Class to methods - Bugfixing Install checks (worked not as expected) - Changed static methods from Install to class functions - Added tests --- mod/install.php | 27 +- src/Core/Console/AutomaticInstallation.php | 46 ++- src/Core/Install.php | 361 +++++++++++------- .../AutomaticInstallationConsoleTest.php | 16 +- tests/src/Core/Console/ConsoleTest.php | 1 - tests/src/Core/InstallTest.php | 306 +++++++++++++++ 6 files changed, 588 insertions(+), 169 deletions(-) create mode 100644 tests/src/Core/InstallTest.php diff --git a/mod/install.php b/mod/install.php index 97677344a0..5a0794b354 100644 --- a/mod/install.php +++ b/mod/install.php @@ -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; @@ -69,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; @@ -145,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; @@ -189,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, @@ -227,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'), diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index 9cdb8a0ae2..2bfd1a7be1 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -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 @@ -77,6 +76,8 @@ HELP; $a = BaseObject::getApp(); + $install = new Install(); + // if a config file is set, $config_file = $this->getOption(['f', 'file']); @@ -105,21 +106,22 @@ HELP; $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') : ''); $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') : ''); + $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() ); } @@ -129,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 !== '') { @@ -154,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"); @@ -177,28 +182,26 @@ HELP; } /** - * @param App $app - * @return array + * @param Install $install the Installer instance */ - private function runBasicChecks($app) + private function runBasicChecks($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; } /** @@ -206,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/Install.php b/src/Core/Install.php index 3ba683a56f..15983b719f 100644 --- a/src/Core/Install.php +++ b/src/Core/Install.php @@ -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 { + /** + * @var array the check outcomes + */ + private $checks; + + /** + * Returns all checks made + * + * @return array the checks + */ + public function getChecks() + { + return $this->checks; + } + + /** + * Resets all checks + */ + public function resetChecks() + { + $this->checks = []; + } + + /** + * Install constructor. + * + */ + public function __construct() + { + $this->checks = []; + } + /** * Checks the current installation environment. There are optional and mandatory checks. * - * @param string $phpath Optional path to the PHP binary (Default is 'php') + * @param string $basepath The basepath of Friendica + * @param string $baseurl The baseurl of Friendica + * @param string $phpath Optional path to the PHP binary * - * @return array First element is a list of all checks and their results, - * the second element is a list of passed checks + * @return bool if the check succeed */ - public static function check($phpath = 'php') + public function checkAll($basepath, $baseurl, $phpath = null) { - $checks = []; + $returnVal = true; - self::checkFunctions($checks); + if (isset($phpath)) { + if (!$this->checkPHP($phpath)) { + $returnVal = false; + } + } - self::checkImagick($checks); + if (!$this->checkFunctions()) { + $returnVal = false; + } - self::checkLocalIni($checks); + if (!$this->checkImagick()) { + $returnVal = false; + } - self::checkSmarty3($checks); + if (!$this->checkLocalIni()) { + $returnVal = false; + } - self::checkKeys($checks); + if (!$this->checkSmarty3()) { + $returnVal = false; + } - self::checkPHP($phpath, $checks); + if (!$this->checkKeys()) { + $returnVal = false; + } - self::checkHtAccess($checks); + if (!$this->checkHtAccess($basepath, $baseurl)) { + $returnVal = false; + } - $checkspassed = array_reduce($checks, - function ($v, $c) { - if (!empty($c['require'])) { - $v = $v && $c['status']; - } - return $v; - }, - true); - - 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->getBasePath() . 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?" ($phpath)":""), $passed, false, $help); + self::addCheck(L10n::t('Command line PHP') . ($passed ? " ($phppath)" : ""), $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: ') . "$result"; } - self::addCheck($checks, L10n::t('PHP cli binary'), $passed2, true, $help); + self::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); + + self::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; } - self::addCheck($checks, L10n::t('Generate encryption keys'), $res, true, $help); + $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; + } + $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.'); + $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; + } } - 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.'); - } - - $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); + self::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,17 +444,19 @@ 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')) { - $fetchResult = Network::fetchUrlFull(System::baseUrl() . "/install/testrewrite"); + $fetchResult = Network::fetchUrlFull($basepath . "/install/testrewrite"); - $url = normalise_link(System::baseUrl() . "/install/testrewrite"); + $url = normalise_link($baseurl . "/install/testrewrite"); if ($fetchResult->getBody() != "ok") { $fetchResult = Network::fetchUrlFull($url); } @@ -360,11 +469,14 @@ class Install extends BaseObject $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; } } diff --git a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php index f83edd88da..290d3ed042 100644 --- a/tests/src/Core/Console/AutomaticInstallationConsoleTest.php +++ b/tests/src/Core/Console/AutomaticInstallationConsoleTest.php @@ -219,7 +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', 'url_path', '/friendica'); + $this->assertConfig('system', 'urlpath', '/friendica'); } /** @@ -265,14 +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', 'url_path', '/friendica'); + $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']); @@ -304,7 +308,7 @@ Options -d|--dbdata The name of the mysql/mariadb database (env MYSQL_DATABASE) -U|--dbuser The username of the mysql/mariadb database login (env MYSQL_USER or MYSQL_USERNAME) -P|--dbpass The password of the mysql/mariadb database login (env MYSQL_PASSWORD) - -b|--urlpath The URL path of Friendica - f.e. '/friendica' (env FRIENDICA_URL_PATH) + -u|--urlpath The URL path of Friendica - f.e. '/friendica' (env FRIENDICA_URL_PATH) -b|--phppath The path of the PHP binary (env FRIENDICA_PHP_PATH) -A|--admin The admin email address of Friendica (env FRIENDICA_ADMIN_MAIL) -T|--tz The timezone of Friendica (env FRIENDICA_TZ) diff --git a/tests/src/Core/Console/ConsoleTest.php b/tests/src/Core/Console/ConsoleTest.php index 40f864e3b9..75f339e8f5 100644 --- a/tests/src/Core/Console/ConsoleTest.php +++ b/tests/src/Core/Console/ConsoleTest.php @@ -50,7 +50,6 @@ abstract class ConsoleTest extends TestCase } public function execute($args) { - DBA::disconnect(); $this->app->reload(); array_unshift($args, $this->getExecutablePath()); diff --git a/tests/src/Core/InstallTest.php b/tests/src/Core/InstallTest.php new file mode 100644 index 0000000000..da92a0e0fb --- /dev/null +++ b/tests/src/Core/InstallTest.php @@ -0,0 +1,306 @@ +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()); +} From 508032cf9a01eeb4e2347db16d52b65ad3a32ed3 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 13 Oct 2018 18:32:14 +0200 Subject: [PATCH 364/428] Move Module AcctLink --- mod/acctlink.php | 16 ---------------- src/Module/AcctLink.php | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 16 deletions(-) delete mode 100644 mod/acctlink.php create mode 100644 src/Module/AcctLink.php diff --git a/mod/acctlink.php b/mod/acctlink.php deleted file mode 100644 index fb8cfd400f..0000000000 --- a/mod/acctlink.php +++ /dev/null @@ -1,16 +0,0 @@ - Date: Sat, 13 Oct 2018 16:41:29 +0000 Subject: [PATCH 365/428] AP: Announce will now work --- index.php | 2 +- src/Protocol/ActivityPub/Transmitter.php | 29 +++++++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/index.php b/index.php index dc3dc80f60..6ab405c632 100644 --- a/index.php +++ b/index.php @@ -46,7 +46,7 @@ if ($a->isMaxProcessesReached() || $a->isMaxLoadReached()) { System::httpExit(503, ['title' => 'Error 503 - Service Temporarily Unavailable', 'description' => 'System is currently overloaded. Please try again later.']); } -if (strstr($a->query_string, '.well-known/host-meta') and ($a->query_string != '.well-known/host-meta')) { +if (strstr($a->query_string, '.well-known/host-meta') && ($a->query_string != '.well-known/host-meta')) { System::httpExit(404); } diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 96c069e589..3fc5900afa 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -22,8 +22,11 @@ use Friendica\Model\Profile; use Friendica\Core\Config; use Friendica\Object\Image; use Friendica\Protocol\ActivityPub; +use Friendica\Protocol\Diaspora; use Friendica\Core\Cache; +require_once 'include/api.php'; + /** * @brief ActivityPub Transmitter Protocol class * @@ -37,7 +40,6 @@ use Friendica\Core\Cache; * - Event * * Complicated object types: - * - Announce * - Undo Announce * * General: @@ -467,7 +469,9 @@ class Transmitter */ private static function getTypeOfItem($item) { - if ($item['verb'] == ACTIVITY_POST) { + if (!empty(Diaspora::isReshare($item['body'], false))) { + $type = 'Announce'; + } elseif ($item['verb'] == ACTIVITY_POST) { if ($item['created'] == $item['edited']) { $type = 'Create'; } else { @@ -558,8 +562,10 @@ class Transmitter $data = array_merge($data, self::createPermissionBlockForItem($item)); - if (in_array($data['type'], ['Create', 'Update', 'Announce', 'Delete'])) { + 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 { @@ -805,6 +811,23 @@ class Transmitter 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 * From 2c541afd47f775c92c4050fb1f04a17187167f8f Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 13 Oct 2018 18:57:31 +0200 Subject: [PATCH 366/428] Moved functions out of boot.php into class - z_root() => $a->getBaseURL() - absurl() => removed because no usage - is_ajax() => $a->isAjax() - current_load() => System::currentLoad() - argc() => $a->argc - argv($x) => $a->getArgumentValue($x) --- boot.php | 78 --------------------------------------------- mod/admin.php | 8 ++--- mod/help.php | 4 +-- mod/item.php | 4 +-- mod/viewsrc.php | 2 +- src/App.php | 37 ++++++++++++++++++++- src/Core/System.php | 21 +++++++++++- src/Core/Worker.php | 2 +- 8 files changed, 66 insertions(+), 90 deletions(-) diff --git a/boot.php b/boot.php index 64741b1762..435de0923c 100644 --- a/boot.php +++ b/boot.php @@ -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. * @@ -1175,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 * diff --git a/mod/admin.php b/mod/admin.php index 372210c403..ade6b0cad1 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -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 ''; @@ -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->argv[1] === 'features')) { $arr = []; $features = Feature::get(false); diff --git a/mod/help.php b/mod/help.php index 5db74c15e8..53118544fb 100644 --- a/mod/help.php +++ b/mod/help.php @@ -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; diff --git a/mod/item.php b/mod/item.php index 5a0658b020..053a00c977 100644 --- a/mod/item.php +++ b/mod/item.php @@ -876,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: [, 0 (no perm) | ] echo json_encode([intval($a->argv[2]), intval($o)]); killme(); diff --git a/mod/viewsrc.php b/mod/viewsrc.php index afdcaada22..7ed029aa78 100644 --- a/mod/viewsrc.php +++ b/mod/viewsrc.php @@ -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", '
      ', $item['body']); killme(); } else { diff --git a/src/App.php b/src/App.php index d763cfa43f..968f07b0c4 100644 --- a/src/App.php +++ b/src/App.php @@ -110,6 +110,11 @@ class App */ private $currentTheme; + /** + * @var bool check if request was an AJAX (xmlhttprequest) request + */ + private $isAjax; + /** * Register a stylesheet file path to be included in the tag of every page. * Inclusion is done in App->initHead(). @@ -322,6 +327,8 @@ class App $this->is_mobile = $mobile_detect->isMobile(); $this->is_tablet = $mobile_detect->isTablet(); + $this->isAjax = strtolower(defaults($_SERVER, 'HTTP_X_REQUESTED_WITH')) == 'xmlhttprequest'; + // Register template engines $this->registerTemplateEngine('Friendica\Render\FriendicaSmartyEngine'); } @@ -1221,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.'); @@ -1572,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/Core/System.php b/src/Core/System.php index cbffcdbef1..5b5fac82f0 100644 --- a/src/Core/System.php +++ b/src/Core/System.php @@ -216,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() @@ -232,6 +252,5 @@ class System extends BaseObject function get_cachefile($file, $writemode = true) function get_itemcachepath() function get_spoolpath() - function current_load() */ } diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 870a5dfb24..bf7e9f3bc8 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -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)); From 3f729df2585b65e41fa2037ca0e8fc79c3344533 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 13 Oct 2018 19:00:44 +0200 Subject: [PATCH 367/428] Renamed AcctLink to Acctlink --- src/Module/{AcctLink.php => Acctlink.php} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/Module/{AcctLink.php => Acctlink.php} (88%) diff --git a/src/Module/AcctLink.php b/src/Module/Acctlink.php similarity index 88% rename from src/Module/AcctLink.php rename to src/Module/Acctlink.php index 2ddc2785be..f14905277a 100644 --- a/src/Module/AcctLink.php +++ b/src/Module/Acctlink.php @@ -8,7 +8,7 @@ use Friendica\Network\Probe; /** * Redirects to another URL based on the parameter 'addr' */ -class AcctLink extends BaseModule +class Acctlink extends BaseModule { public static function content() { @@ -19,7 +19,7 @@ class AcctLink extends BaseModule if ($url) { goaway($url); - killme(); + exit(); } } } From 059bd1307f9590464975caa79b4b3815349dac7f Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 13 Oct 2018 19:05:54 +0200 Subject: [PATCH 368/428] rename argv to getArgumentValue --- mod/admin.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/admin.php b/mod/admin.php index ade6b0cad1..d0e8ab0e38 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -2536,7 +2536,7 @@ function admin_page_features_post(App $a) */ function admin_page_features(App $a) { - if (($a->argc > 1) && ($a->argv[1] === 'features')) { + if (($a->argc > 1) && ($a->getArgumentValue(1) === 'features')) { $arr = []; $features = Feature::get(false); From 4f7cb049fb43800f4860a8d28e8d9b5c5d6ad0f3 Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sat, 13 Oct 2018 19:10:46 +0200 Subject: [PATCH 369/428] isAjax bugfix --- src/App.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/App.php b/src/App.php index 968f07b0c4..97c193b3b7 100644 --- a/src/App.php +++ b/src/App.php @@ -327,7 +327,7 @@ class App $this->is_mobile = $mobile_detect->isMobile(); $this->is_tablet = $mobile_detect->isTablet(); - $this->isAjax = strtolower(defaults($_SERVER, 'HTTP_X_REQUESTED_WITH')) == 'xmlhttprequest'; + $this->isAjax = strtolower(defaults($_SERVER, 'HTTP_X_REQUESTED_WITH', '')) == 'xmlhttprequest'; // Register template engines $this->registerTemplateEngine('Friendica\Render\FriendicaSmartyEngine'); From efad4936b06f8ee0af950c67bba81ff1ec5dff30 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 13 Oct 2018 18:13:01 +0000 Subject: [PATCH 370/428] OStatus contacts are now automatically converted to AP --- boot.php | 2 +- config/dbstructure.json | 1 + database.sql | 3 ++- src/Model/Contact.php | 14 +++++++------- src/Protocol/ActivityPub/Processor.php | 3 +++ src/Protocol/ActivityPub/Receiver.php | 2 +- src/Worker/OnePoll.php | 12 ++++++++++++ 7 files changed, 27 insertions(+), 10 deletions(-) diff --git a/boot.php b/boot.php index 64741b1762..6be5f3aecb 100644 --- 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', 1284); +define('DB_UPDATE_VERSION', 1285); define('NEW_UPDATE_ROUTINE_VERSION', 1170); /** diff --git a/config/dbstructure.json b/config/dbstructure.json index 8f67686156..443f9bd755 100644 --- a/config/dbstructure.json +++ b/config/dbstructure.json @@ -192,6 +192,7 @@ "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": ""}, diff --git a/database.sql b/database.sql index a797c8df36..341ee5a858 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2018.12-dev (The Tazmans Flax-lily) --- DB_UPDATE_VERSION 1284 +-- DB_UPDATE_VERSION 1285 -- ------------------------------------------ @@ -189,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 '', diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 23c31d0b17..f1260c7c44 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -521,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); @@ -825,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) ); @@ -833,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) ); } @@ -1036,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); } @@ -1515,7 +1515,7 @@ class Contact extends BaseObject $ret = Probe::uri($contact["url"], $network); // If Probe::uri fails the network code will be different - if (($ret["network"] != $contact["network"]) && ($ret["network"] != $network)) { + if (($ret["network"] != $contact["network"]) && !in_array($ret["network"], [Protocol::ACTIVITYPUB, $network])) { return false; } diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 166530f472..bfc5e6d084 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -298,6 +298,9 @@ class Processor $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)) { diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index f54503708b..12edf3f06b 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -452,7 +452,7 @@ class Receiver * @param integer $uid User ID * @param string $url Profile URL */ - private static function switchContact($cid, $uid, $url) + public static function switchContact($cid, $uid, $url) { $profile = ActivityPub::probeProfile($url); if (empty($profile)) { diff --git a/src/Worker/OnePoll.php b/src/Worker/OnePoll.php index a68ad1336d..3c16af75f8 100644 --- a/src/Worker/OnePoll.php +++ b/src/Worker/OnePoll.php @@ -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 From 8b9aa80aadd5700387118883db19661c8ac4ebd3 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 13 Oct 2018 18:59:39 +0000 Subject: [PATCH 371/428] "to" is now used for mentions, "cc" for everything else --- src/Protocol/ActivityPub/Transmitter.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 3fc5900afa..f5765ccdd3 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -329,7 +329,7 @@ class Transmitter foreach ($terms as $term) { $profile = APContact::getByURL($term['url'], false); if (!empty($profile) && empty($contacts[$profile['url']])) { - $data['cc'][] = $profile['url']; + $data['to'][] = $profile['url']; $contacts[$profile['url']] = $profile['url']; } } @@ -381,11 +381,6 @@ class Transmitter } DBA::close($parents); - if (empty($data['to'])) { - $data['to'] = $data['cc']; - $data['cc'] = []; - } - return $data; } From f60468677e40374799d39506e37acb96d98ab2f1 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 13 Oct 2018 19:49:20 +0000 Subject: [PATCH 372/428] We now transmit location and application as well. --- src/Protocol/ActivityPub/Receiver.php | 4 ++ src/Protocol/ActivityPub/Transmitter.php | 48 ++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index f54503708b..773d45c83a 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -25,6 +25,10 @@ use Friendica\Util\DateTimeFormat; * - Event * - Undo Announce * + * Missing object fields: + * - Location + * - Generator + * * Check what this is meant to do: * - Add * - Block diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index f5765ccdd3..3c22f8f62b 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -24,6 +24,7 @@ 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'; @@ -32,10 +33,6 @@ require_once 'include/api.php'; * * To-Do: * - * Missing object fields: - * - service (App) - * - location - * * Missing object types: * - Event * @@ -600,6 +597,40 @@ class Transmitter 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 * @@ -801,6 +832,15 @@ class Transmitter $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; From aab4fa0c3121a777bd58c3350a13ebaaf1fd5457 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 13 Oct 2018 20:36:44 +0000 Subject: [PATCH 373/428] The instrument is now added, updating AP contacts is now enabled --- mod/crepair.php | 2 +- src/Protocol/ActivityPub/Transmitter.php | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/mod/crepair.php b/mod/crepair.php index 076c611db4..d8c6b35f5a 100644 --- a/mod/crepair.php +++ b/mod/crepair.php @@ -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); diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index 3c22f8f62b..b261e6060c 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -4,6 +4,7 @@ */ namespace Friendica\Protocol\ActivityPub; +use Friendica\BaseObject; use Friendica\Database\DBA; use Friendica\Core\System; use Friendica\Util\HTTPSignature; @@ -552,6 +553,8 @@ class Transmitter $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'])) { @@ -883,7 +886,7 @@ class Transmitter 'actor' => $owner['url'], 'object' => $suggestion['url'], 'content' => $suggestion['note'], - 'published' => DateTimeFormat::utc($suggestion['created'] . '+00:00', DateTimeFormat::ATOM), + 'instrument' => ['type' => 'Service', 'name' => BaseObject::getApp()->getUserAgent()], 'to' => [ActivityPub::PUBLIC_COLLECTION], 'cc' => []]; @@ -910,6 +913,7 @@ class Transmitter 'actor' => $owner['url'], 'object' => $owner['url'], 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), + 'instrument' => ['type' => 'Service', 'name' => BaseObject::getApp()->getUserAgent()], 'to' => [ActivityPub::PUBLIC_COLLECTION], 'cc' => []]; @@ -936,6 +940,7 @@ class Transmitter 'actor' => $owner['url'], 'object' => self::getProfile($uid), 'published' => DateTimeFormat::utcNow(DateTimeFormat::ATOM), + 'instrument' => ['type' => 'Service', 'name' => BaseObject::getApp()->getUserAgent()], 'to' => [$profile['followers']], 'cc' => []]; @@ -963,6 +968,7 @@ class Transmitter '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); @@ -990,6 +996,7 @@ class Transmitter '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); @@ -1017,6 +1024,7 @@ class Transmitter '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); @@ -1045,6 +1053,7 @@ class Transmitter '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); From e829e074fc227cbf56f01348d7a519e32f82e402 Mon Sep 17 00:00:00 2001 From: Michael Date: Sat, 13 Oct 2018 21:37:39 +0000 Subject: [PATCH 374/428] Location, coord and app are now processed as well --- src/Protocol/ActivityPub/Processor.php | 7 ++++++- src/Protocol/ActivityPub/Receiver.php | 26 ++++++++------------------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index 166530f472..d77a0277fb 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -212,8 +212,13 @@ class Processor $item['content-warning'] = HTML::toBBCode($activity['summary']); $item['body'] = self::convertMentions(HTML::toBBCode($activity['content'])); $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['service']; + $item['app'] = $activity['generator']; $item['plink'] = defaults($activity, 'alternate-url', $item['uri']); $item['diaspora_signed_text'] = defaults($activity, 'diaspora:comment', ''); diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 773d45c83a..cde197b0c4 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -25,10 +25,6 @@ use Friendica\Util\DateTimeFormat; * - Event * - Undo Announce * - * Missing object fields: - * - Location - * - Generator - * * Check what this is meant to do: * - Add * - Block @@ -517,24 +513,15 @@ class Receiver private static function addActivityFields($object_data, $activity) { if (!empty($activity['published']) && empty($object_data['published'])) { - $object_data['published'] = JsonLD::fetchElement($activity, 'published', '@value'); - } - - if (!empty($activity['updated']) && empty($object_data['updated'])) { - $object_data['updated'] = JsonLD::fetchElement($activity, 'updated', '@value'); + $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'); } - if (!empty($activity['inReplyTo']) && empty($object_data['parent-uri'])) { - $object_data['parent-uri'] = JsonLD::fetchElement($activity, 'inReplyTo'); - } + $object_data['service'] = JsonLD::fetchElement($activity, 'as:instrument', 'as:name', '@type', 'as:Service'); - if (!empty($activity['instrument'])) { - $object_data['service'] = JsonLD::fetchElement($activity, 'instrument', 'name', 'type', 'Service'); - } return $object_data; } @@ -700,10 +687,13 @@ class Receiver $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['service'] = JsonLD::fetchElement($object, 'instrument', 'name', 'type', 'Service'); // todo - $object_data['service'] = null; + $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 @@ -723,7 +713,7 @@ class Receiver // @context, type, actor, signature, mediaType, duration, replies, icon // Also missing: (Defined in the standard, but currently unused) - // audience, preview, endTime, startTime, generator, image + // audience, preview, endTime, startTime, image // Data in Notes: From 6be04a73e34cf39ba5ffbcba95d8f31ceb1961eb Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 14 Oct 2018 07:47:04 +0000 Subject: [PATCH 375/428] The outbox is now more complete / No more duplicates in the receiver array --- src/Protocol/ActivityPub/Transmitter.php | 33 +++++++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/Protocol/ActivityPub/Transmitter.php b/src/Protocol/ActivityPub/Transmitter.php index b261e6060c..9ddcc1d793 100644 --- a/src/Protocol/ActivityPub/Transmitter.php +++ b/src/Protocol/ActivityPub/Transmitter.php @@ -151,8 +151,8 @@ class Transmitter { $public_contact = Contact::getIdForURL($owner['url'], 0, true); - $condition = ['uid' => $owner['uid'], 'contact-id' => $owner['id'], 'author-id' => $public_contact, - 'wall' => true, 'private' => false, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT], + $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); @@ -329,6 +329,10 @@ class Transmitter 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 { @@ -342,6 +346,10 @@ class Transmitter $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]); + } } } @@ -354,7 +362,7 @@ class Transmitter } } - $parents = Item::select(['id', 'author-link', 'owner-link', 'gravity'], ['parent' => $item['parent']]); + $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']) { @@ -362,6 +370,15 @@ class Transmitter } $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']; @@ -379,7 +396,15 @@ class Transmitter } DBA::close($parents); - return $data; + 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']))]; } /** From 753f61f633d30a8d620098f54286ba0d812355ed Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 14 Oct 2018 10:31:11 +0200 Subject: [PATCH 376/428] FollowUp Acctlink move --- src/Module/Acctlink.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Module/Acctlink.php b/src/Module/Acctlink.php index f14905277a..29aa99140c 100644 --- a/src/Module/Acctlink.php +++ b/src/Module/Acctlink.php @@ -12,10 +12,10 @@ class Acctlink extends BaseModule { public static function content() { - $addr = defaults($_REQUEST, 'addr', false); + $addr = defaults($_GET, 'addr', false); if ($addr) { - $url = defaults(Probe::uri($addr), 'url', false); + $url = defaults(Probe::uri(trim($addr)), 'url', false); if ($url) { goaway($url); From 248c1b8074a9281d2d41bc1c26542017decb12ef Mon Sep 17 00:00:00 2001 From: Philipp Holzer Date: Sun, 14 Oct 2018 10:37:19 +0200 Subject: [PATCH 377/428] Type hinting & call bugfixing --- src/Core/Console/AutomaticInstallation.php | 2 +- src/Core/Install.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Core/Console/AutomaticInstallation.php b/src/Core/Console/AutomaticInstallation.php index 2bfd1a7be1..c4e542e762 100644 --- a/src/Core/Console/AutomaticInstallation.php +++ b/src/Core/Console/AutomaticInstallation.php @@ -184,7 +184,7 @@ HELP; /** * @param Install $install the Installer instance */ - private function runBasicChecks($install) + private function runBasicChecks(Install $install) { $install->resetChecks(); $install->checkFunctions(); diff --git a/src/Core/Install.php b/src/Core/Install.php index 15983b719f..daf90b9fff 100644 --- a/src/Core/Install.php +++ b/src/Core/Install.php @@ -190,7 +190,7 @@ class Install $phppath = ""; } - self::addCheck(L10n::t('Command line PHP') . ($passed ? " ($phppath)" : ""), $passed, false, $help); + $this->addCheck(L10n::t('Command line PHP') . ($passed ? " ($phppath)" : ""), $passed, false, $help); if ($passed) { $cmd = "$phppath -v"; @@ -202,7 +202,7 @@ class Install $help .= L10n::t("PHP executable is not the php cli binary \x28could be cgi-fgci version\x29") . EOL; $help .= L10n::t('Found PHP version: ') . "$result"; } - self::addCheck(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; @@ -221,7 +221,7 @@ class Install $this->phppath = $phppath; } - self::addCheck(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 @@ -408,7 +408,7 @@ class Install $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(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; From a769efae383ecfdffc86d754d9eca7537101fa48 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 07:43:44 -0400 Subject: [PATCH 378/428] Remove whitespace clearing around code tags - Normalize inline code blocks to --- src/Content/Text/BBCode.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 66f4190b28..c903ee6945 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -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("|(?!]*>)([^<]*)(?!]*>)|ism", - function ($match) use ($simple_html) { - $return = '' . $match[1] . ''; - // Use for Diaspora inline code blocks - if ($simple_html === 3) { - $return = '' . $match[1] . ''; - } - return $return; - } - , $text); - // Unhide all [noparse] contained bbtags unspacefying them // and triming the [noparse] tag. From f7c020af04426483f875b742599defab10926c7c Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 07:44:07 -0400 Subject: [PATCH 379/428] Add HTML result boxes to mod/babel --- mod/babel.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/mod/babel.php b/mod/babel.php index e5ae96be70..65287b9f2b 100644 --- a/mod/babel.php +++ b/mod/babel.php @@ -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'), From 0563a284381bb9dabf851731479f6293337617dd Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 08:58:27 -0400 Subject: [PATCH 380/428] Replace System::baseUrl() by App->getBaseURL() in mod/register - Remove redundant System::baseUrl() in goaway() calls - Add more generic Friendica\Model use statement - Allow empty path in goaway() --- boot.php | 2 +- mod/register.php | 40 ++++++++++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/boot.php b/boot.php index 435de0923c..2433143ddb 100644 --- a/boot.php +++ b/boot.php @@ -647,7 +647,7 @@ function killme() /** * @brief Redirect to another URL and terminate this process. */ -function goaway($path) +function goaway($path = '') { if (strstr(normalise_link($path), 'http://')) { $url = $path; diff --git a/mod/register.php b/mod/register.php index 454062d89b..2b3522234e 100644 --- a/mod/register.php +++ b/mod/register.php @@ -12,7 +12,7 @@ use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBA; -use Friendica\Model\User; +use Friendica\Model; use Friendica\Module\Tos; use Friendica\Util\DateTimeFormat; @@ -67,7 +67,7 @@ function register_post(App $a) $arr['language'] = L10n::getBrowserLanguage(); try { - $result = User::create($arr); + $result = Model\User::create($arr); } catch (Exception $e) { notice($e->getMessage()); return; @@ -76,7 +76,7 @@ function register_post(App $a) $user = $result['user']; if ($netpublish && intval(Config::get('config', 'register_policy')) !== REGISTER_APPROVE) { - $url = System::baseUrl() . '/profile/' . $user['nickname']; + $url = $a->getBaseUrl() . '/profile/' . $user['nickname']; Worker::add(PRIORITY_LOW, "Directory", $url); } @@ -92,12 +92,18 @@ function register_post(App $a) // Only send a password mail when the password wasn't manually provided if (!x($_POST, 'password1') || !x($_POST, 'confirm')) { - $res = User::sendRegisterOpenEmail( - $user['email'], Config::get('config', 'sitename'), System::baseUrl(), $user['username'], $result['password'], $user); + $res = Model\User::sendRegisterOpenEmail( + $user['email'], + Config::get('config', 'sitename'), + $a->getBaseUrl(), + $user['username'], + $result['password'], + $user + ); if ($res) { info(L10n::t('Registration successful. Please check your email for further instructions.') . EOL); - goaway(System::baseUrl()); + goaway(); } else { notice( L10n::t('Failed to send email message. Here your accout details:
      login: %s
      password: %s

      You can change your password after login.', @@ -108,12 +114,12 @@ function register_post(App $a) } } else { info(L10n::t('Registration successful.') . EOL); - goaway(System::baseUrl()); + goaway(); } } elseif (intval(Config::get('config', 'register_policy')) === REGISTER_APPROVE) { if (!strlen(Config::get('config', 'admin_email'))) { notice(L10n::t('Your registration can not be processed.') . EOL); - goaway(System::baseUrl()); + goaway(); } $hash = random_string(); @@ -146,9 +152,9 @@ function register_post(App $a) 'source_name' => $user['username'], 'source_mail' => $user['email'], 'source_nick' => $user['nickname'], - 'source_link' => System::baseUrl() . "/admin/users/", - 'link' => System::baseUrl() . "/admin/users/", - 'source_photo' => System::baseUrl() . "/photo/avatar/" . $user['uid'] . ".jpg", + 'source_link' => $a->getBaseUrl() . "/admin/users/", + 'link' => $a->getBaseUrl() . "/admin/users/", + 'source_photo' => $a->getBaseUrl() . "/photo/avatar/" . $user['uid'] . ".jpg", 'to_email' => $admin['email'], 'uid' => $admin['uid'], 'language' => $admin['language'] ? $admin['language'] : 'en', @@ -156,11 +162,17 @@ function register_post(App $a) ]); } // send notification to the user, that the registration is pending - User::sendRegisterPendingEmail( - $user['email'], Config::get('config', 'sitename'), $user['username']); + Model\User::sendRegisterPendingEmail( + $user['email'], + Config::get('config', 'sitename'), + $user['username'], + $a->getBaseURL(), + $user['nickname'], + $result['password'] + ); info(L10n::t('Your registration is pending approval by the site owner.') . EOL); - goaway(System::baseUrl()); + goaway(); } return; From f2bde919e5fe826fb32ab806b401667bd30ab23c Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 11:30:39 -0400 Subject: [PATCH 381/428] Fix ignored show_in_notification_page parameter in notification() --- include/enotify.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/enotify.php b/include/enotify.php index b184a6935e..882227e941 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -84,7 +84,7 @@ function notification($params) // with $params['show_in_notification_page'] == false, the notification isn't inserted into // the database, and an email is sent if applicable. // default, if not specified: true - $show_in_notification_page = ((x($params, 'show_in_notification_page')) ? $params['show_in_notification_page']:true); + $show_in_notification_page = isset($params['show_in_notification_page']) ? $params['show_in_notification_page'] : true; $additional_mail_header = ""; $additional_mail_header .= "Precedence: list\n"; From 7f143c3159615b4a10539447bcf250a5fca793a5 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 11:32:54 -0400 Subject: [PATCH 382/428] Fix various spelling mistakes --- mod/admin.php | 4 ++-- src/Database/DBA.php | 2 +- src/Model/User.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index d0e8ab0e38..7574e684ec 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -33,11 +33,11 @@ require_once 'include/items.php'; /** * @brief Process send data from the admin panels subpages * - * This function acts as relais for processing the data send from the subpages + * This function acts as relay for processing the data send from the subpages * of the admin panel. Depending on the 1st parameter of the url (argv[1]) * specialized functions are called to process the data from the subpages. * - * The function itself does not return anything, but the subsequencely function + * The function itself does not return anything, but the subsequently function * return the HTML for the pages of the admin panel. * * @param App $a diff --git a/src/Database/DBA.php b/src/Database/DBA.php index c33fa2152f..8fd117e5d2 100644 --- a/src/Database/DBA.php +++ b/src/Database/DBA.php @@ -821,7 +821,7 @@ class DBA * @param array $param parameter array * @param bool $on_duplicate_update Do an update on a duplicate entry * - * @return boolean was the insert successfull? + * @return boolean was the insert successful? */ public static function insert($table, $param, $on_duplicate_update = false) { diff --git a/src/Model/User.php b/src/Model/User.php index b8b694de87..b61014b8a8 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -644,7 +644,7 @@ class User } /** - * @brief Sends pending registration confiŕmation email + * @brief Sends pending registration confirmation email * * @param string $email * @param string $sitename From 123992384b9b5e65bc9c0ffecd9c557fdb3a29a8 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 11:34:34 -0400 Subject: [PATCH 383/428] Create Model\Register - Add Model\User::exists method --- src/Model/Register.php | 131 +++++++++++++++++++++++++++++++++++++++++ src/Model/User.php | 11 ++++ 2 files changed, 142 insertions(+) create mode 100644 src/Model/Register.php diff --git a/src/Model/Register.php b/src/Model/Register.php new file mode 100644 index 0000000000..e54db87a6b --- /dev/null +++ b/src/Model/Register.php @@ -0,0 +1,131 @@ + + */ +class Register +{ + /** + * Return the list of pending registrations + * + * @return array + */ + public static function getPending() + { + $stmt = DBA::p( + "SELECT `register`.*, `contact`.`name`, `user`.`email` + FROM `register` + INNER JOIN `contact` ON `register`.`uid` = `contact`.`uid` + INNER JOIN `user` ON `register`.`uid` = `user`.`uid`" + ); + + return DBA::toArray($stmt); + } + + /** + * Returns the pending registration count + * + * @return int + */ + public static function getPendingCount() + { + $register = DBA::fetchFirst( + "SELECT COUNT(*) AS `count` + FROM `register` + INNER JOIN `contact` ON `register`.`uid` = `contact`.`uid` AND `contact`.`self`" + ); + + return $register['count']; + } + + /** + * Returns the register record associated with the provided hash + * + * @param string $hash + * @return array + */ + public static function getByHash($hash) + { + return DBA::selectFirst('register', [], ['hash' => $hash]); + } + + /** + * Returns true if a register record exists with the provided hash + * + * @param string $hash + * @return boolean + */ + public static function existsByHash($hash) + { + return DBA::exists('register', ['hash' => $hash]); + } + + /** + * Creates a register record for an invitation and returns the auto-generated code for it + * + * @return string + */ + public static function createForInvitation() + { + $code = autoname(8) . srand(1000, 9999); + + $fields = [ + 'hash' => $code, + 'created' => DateTimeFormat::utcNow() + ]; + + DBA::insert('register', $fields); + + return $code; + } + + /** + * Creates a register record for approval and returns the success of the database insert + * Checks for the existence of the provided user id + * + * @param integer $uid The ID of the user needing approval + * @param string $language The registration language + * @param string $note An additional message from the user + * @return boolean + */ + public static function createForApproval($uid, $language, $note = '') + { + $hash = random_string(); + + if (!User::exists($uid)) { + return false; + } + + $fields = [ + 'hash' => $hash, + 'created' => DateTimeFormat::utcNow(), + 'uid' => $uid, + 'password' => '', // Obsolete, slated for deletion + 'language' => $language, + 'note' => $note + ]; + + return DBA::insert('register', $fields); + } + + /** + * Deletes a register record by the provided hash and returns the success of the database deletion + * + * @param string $hash + * @return boolean + */ + public static function deleteByHash($hash) + { + return DBA::delete('register', ['hash' => $hash]); + } +} diff --git a/src/Model/User.php b/src/Model/User.php index b61014b8a8..ddd6ce1ed6 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -31,6 +31,17 @@ require_once 'include/text.php'; */ class User { + /** + * Returns true if a user record exists with the provided id + * + * @param integer $uid + * @return boolean + */ + public static function exists($uid) + { + return DBA::exists('user', ['uid' => $uid]); + } + /** * @brief Returns the user id of a given profile url * From 540adaf829b4835bf99fa47e58520cf998defb88 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 11:57:28 -0400 Subject: [PATCH 384/428] Use Model\Register methods in modules - Update registration emails to avoid storing the plaintext password in the register table - Remove redundant sprintf() when used with L10n::t() - Remove redundant Systen::baseUrl() with goaway() --- mod/admin.php | 20 ++++++++------------ mod/invite.php | 7 +------ mod/ping.php | 6 +----- mod/register.php | 17 ++++------------- mod/regmod.php | 30 ++++++++++++----------------- src/Model/User.php | 47 ++++++++++++++++++++++++++++------------------ 6 files changed, 55 insertions(+), 72 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index 7574e684ec..6189c4cb77 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -18,13 +18,14 @@ use Friendica\Database\DBA; use Friendica\Database\DBStructure; use Friendica\Model\Contact; use Friendica\Model\Item; +use Friendica\Model\Register; use Friendica\Model\User; use Friendica\Module\Login; use Friendica\Module\Tos; use Friendica\Util\Arrays; use Friendica\Util\DateTimeFormat; -use Friendica\Util\Temporal; use Friendica\Util\Network; +use Friendica\Util\Temporal; require_once 'include/enotify.php'; require_once 'include/text.php'; @@ -895,8 +896,7 @@ function admin_page_summary(App $a) logger('accounts: ' . print_r($accounts, true), LOGGER_DATA); - $r = q("SELECT COUNT(`id`) AS `count` FROM `register`"); - $pending = $r[0]['count']; + $pending = Register::getPendingCount(); $r = q("SELECT COUNT(*) AS `total` FROM `queue` WHERE 1"); $queue = (($r) ? $r[0]['total'] : 0); @@ -912,10 +912,10 @@ function admin_page_summary(App $a) $r = q("SHOW variables LIKE 'max_allowed_packet'"); $max_allowed_packet = (($r) ? $r[0]['Value'] : 0); - $server_settings = ['label' => L10n::t('Server Settings'), - 'php' => ['upload_max_filesize' => ini_get('upload_max_filesize'), - 'post_max_size' => ini_get('post_max_size'), - 'memory_limit' => ini_get('memory_limit')], + $server_settings = ['label' => L10n::t('Server Settings'), + 'php' => ['upload_max_filesize' => ini_get('upload_max_filesize'), + 'post_max_size' => ini_get('post_max_size'), + 'memory_limit' => ini_get('memory_limit')], 'mysql' => ['max_allowed_packet' => $max_allowed_packet]]; $t = get_markup_template('admin/summary.tpl'); @@ -1792,11 +1792,7 @@ function admin_page_users(App $a) } /* get pending */ - $pending = q("SELECT `register`.*, `contact`.`name`, `user`.`email` - FROM `register` - INNER JOIN `contact` ON `register`.`uid` = `contact`.`uid` - INNER JOIN `user` ON `register`.`uid` = `user`.`uid`;"); - + $pending = Register::getPending(); /* get users */ $total = q("SELECT COUNT(*) AS `total` FROM `user` WHERE 1"); diff --git a/mod/invite.php b/mod/invite.php index 2a98d19ffc..7318b77ae9 100644 --- a/mod/invite.php +++ b/mod/invite.php @@ -58,14 +58,9 @@ function invite_post(App $a) } if ($invitation_only && ($invites_remaining || is_site_admin())) { - $code = autoname(8) . srand(1000, 9999); + $code = Friendica\Model\Register::createForInvitation(); $nmessage = str_replace('$invite_code', $code, $message); - $r = q("INSERT INTO `register` (`hash`,`created`) VALUES ('%s', '%s') ", - DBA::escape($code), - DBA::escape(DateTimeFormat::utcNow()) - ); - if (! is_site_admin()) { $invites_remaining --; if ($invites_remaining >= 0) { diff --git a/mod/ping.php b/mod/ping.php index ff0139f28f..5ea75727a1 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -202,11 +202,7 @@ function ping_init(App $a) $mail_count = count($mails); if (intval(Config::get('config', 'register_policy')) === REGISTER_APPROVE && is_site_admin()) { - $regs = q( - "SELECT `contact`.`name`, `contact`.`url`, `contact`.`micro`, `register`.`created` - FROM `contact` RIGHT JOIN `register` ON `register`.`uid` = `contact`.`uid` - WHERE `contact`.`self` = 1" - ); + $regs = Friendica\Model\Register::getPending(); if (DBA::isResult($regs)) { $register_count = count($regs); diff --git a/mod/register.php b/mod/register.php index 2b3522234e..79e9455cd5 100644 --- a/mod/register.php +++ b/mod/register.php @@ -11,10 +11,8 @@ use Friendica\Core\L10n; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Core\Worker; -use Friendica\Database\DBA; use Friendica\Model; use Friendica\Module\Tos; -use Friendica\Util\DateTimeFormat; require_once 'include/enotify.php'; @@ -86,7 +84,7 @@ function register_post(App $a) if (intval(Config::get('config', 'register_policy')) === REGISTER_OPEN) { if ($using_invites && $invite_id) { - q("delete * from register where hash = '%s' limit 1", DBA::escape($invite_id)); + Model\Register::deleteByHash($invite_id); PConfig::set($user['uid'], 'system', 'invites_remaining', $num_invites); } @@ -122,19 +120,11 @@ function register_post(App $a) goaway(); } - $hash = random_string(); - $r = q("INSERT INTO `register` ( `hash`, `created`, `uid`, `password`, `language`, `note` ) VALUES ( '%s', '%s', %d, '%s', '%s', '%s' ) ", - DBA::escape($hash), - DBA::escape(DateTimeFormat::utcNow()), - intval($user['uid']), - DBA::escape($result['password']), - DBA::escape(Config::get('system', 'language')), - DBA::escape($_POST['permonlybox']) - ); + Model\Register::createForApproval($user['uid'], Config::get('system', 'language'), $_POST['permonlybox']); // invite system if ($using_invites && $invite_id) { - q("DELETE * FROM `register` WHERE `hash` = '%s' LIMIT 1", DBA::escape($invite_id)); + Model\Register::deleteByHash($invite_id); PConfig::set($user['uid'], 'system', 'invites_remaining', $num_invites); } @@ -163,6 +153,7 @@ function register_post(App $a) } // send notification to the user, that the registration is pending Model\User::sendRegisterPendingEmail( + $user['uid'], $user['email'], Config::get('config', 'sitename'), $user['username'], diff --git a/mod/regmod.php b/mod/regmod.php index 11d8eee412..433a8f5e4e 100644 --- a/mod/regmod.php +++ b/mod/regmod.php @@ -9,6 +9,7 @@ use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBA; +use Friendica\Model\Register; use Friendica\Model\User; use Friendica\Module\Login; @@ -18,30 +19,24 @@ function user_allow($hash) { $a = get_app(); - $register = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", - DBA::escape($hash) - ); - + $register = Register::getByHash($hash); if (!DBA::isResult($register)) { return false; } $user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", - intval($register[0]['uid']) + intval($register['uid']) ); if (!DBA::isResult($user)) { killme(); } - $r = q("DELETE FROM `register` WHERE `hash` = '%s'", - DBA::escape($register[0]['hash']) - ); - + Register::deleteByHash($hash); $r = q("UPDATE `user` SET `blocked` = 0, `verified` = 1 WHERE `uid` = %d", - intval($register[0]['uid']) + intval($register['uid']) ); $r = q("SELECT * FROM `profile` WHERE `uid` = %d AND `is-default` = 1", @@ -54,14 +49,14 @@ function user_allow($hash) } } - L10n::pushLang($register[0]['language']); + L10n::pushLang($register['language']); $res = User::sendRegisterOpenEmail( $user[0]['email'], Config::get('config', 'sitename'), System::baseUrl(), $user[0]['username'], - $register[0]['password'], + 'Sent in a previous email', $user[0]); L10n::popLang(); @@ -77,20 +72,19 @@ function user_allow($hash) // allowed to have friends on this system function user_deny($hash) { - $register = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1", - DBA::escape($hash) - ); + $register = Register::getByHash($hash); if (!DBA::isResult($register)) { return false; } $user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", - intval($register[0]['uid']) + intval($register['uid']) ); - DBA::delete('user', ['uid' => $register[0]['uid']]); - DBA::delete('register', ['hash' => $register[0]['hash']]); + DBA::delete('user', ['uid' => $register['uid']]); + + Register::deleteByHash($register['hash']); notice(L10n::t('Registration revoked for %s', $user[0]['username']) . EOL); return true; diff --git a/src/Model/User.php b/src/Model/User.php index ddd6ce1ed6..2888410c7f 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -412,7 +412,7 @@ class User throw new Exception(L10n::t('An invitation is required.')); } - if (!DBA::exists('register', ['hash' => $invite_id])) { + if (!Register::existsByHash($invite_id)) { throw new Exception(L10n::t('Invitation could not be verified.')); } } @@ -660,22 +660,31 @@ class User * @param string $email * @param string $sitename * @param string $username + * @param string $password Plaintext password * @return NULL|boolean from notification() and email() inherited */ - public static function sendRegisterPendingEmail($email, $sitename, $username) + public static function sendRegisterPendingEmail($uid, $email, $sitename, $username, $siteurl, $nickname, $password) { $body = deindent(L10n::t(' Dear %1$s, Thank you for registering at %2$s. Your account is pending for approval by the administrator. - ')); - $body = sprintf($body, $username, $sitename); + Your login details are as follows: + + Site Location: %3$s + Login Name: %4$s + Password: %5$s + ', + $body, $username, $sitename, $siteurl, $nickname, $password + )); return notification([ - 'type' => SYSTEM_EMAIL, + 'type' => SYSTEM_EMAIL, + 'uid' => $uid, 'to_email' => $email, - 'subject'=> L10n::t('Registration at %s', $sitename), - 'body' => $body]); + 'subject' => L10n::t('Registration at %s', $sitename), + 'body' => $body + ]); } /** @@ -695,7 +704,9 @@ class User $preamble = deindent(L10n::t(' Dear %1$s, Thank you for registering at %2$s. Your account has been created. - ')); + ', + $preamble, $username, $sitename + )); $body = deindent(L10n::t(' The login details are as follows: @@ -722,19 +733,19 @@ class User If you ever want to delete your account, you can do so at %3$s/removeme - Thank you and welcome to %2$s.')); - - $preamble = sprintf($preamble, $username, $sitename); - $body = sprintf($body, $email, $sitename, $siteurl, $username, $password); + Thank you and welcome to %2$s.', + $body, $email, $sitename, $siteurl, $username, $password + )); return notification([ - 'uid' => $user['uid'], + 'uid' => $user['uid'], 'language' => $user['language'], - 'type' => SYSTEM_EMAIL, + 'type' => SYSTEM_EMAIL, 'to_email' => $email, - 'subject'=> L10n::t('Registration details for %s', $sitename), - 'preamble'=> $preamble, - 'body' => $body]); + 'subject' => L10n::t('Registration details for %s', $sitename), + 'preamble' => $preamble, + 'body' => $body + ]); } /** @@ -771,7 +782,7 @@ class User if ($uid == local_user()) { unset($_SESSION['authenticated']); unset($_SESSION['uid']); - goaway(System::baseUrl()); + goaway();; } } } From 37ad4a7d22b2141f63df3a097035b1a8f0dd5b30 Mon Sep 17 00:00:00 2001 From: Michael Date: Sun, 14 Oct 2018 17:57:44 +0000 Subject: [PATCH 385/428] ActivityPub: Rudimentary support for videos --- src/Protocol/ActivityPub/Processor.php | 5 +++++ src/Protocol/ActivityPub/Receiver.php | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Protocol/ActivityPub/Processor.php b/src/Protocol/ActivityPub/Processor.php index d77a0277fb..69b70249cc 100644 --- a/src/Protocol/ActivityPub/Processor.php +++ b/src/Protocol/ActivityPub/Processor.php @@ -211,6 +211,11 @@ class Processor $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'])) { diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index cde197b0c4..5a40306e61 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -698,10 +698,10 @@ class Receiver // Special treatment for Hubzilla links if (is_array($object_data['alternate-url'])) { - if (!empty($object['as: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'); - } else { - $object_data['alternate-url'] = null; } } From 5fd44020747d16fc90d902cfb89a2fca40d2d9ee Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Sun, 14 Oct 2018 20:03:22 +0200 Subject: [PATCH 386/428] code standards + fixing navigation links to /contact/... --- mod/allfriends.php | 6 +++--- mod/common.php | 22 +++++++++++----------- mod/crepair.php | 6 +++--- mod/dirfind.php | 8 ++++---- mod/group.php | 6 +++--- src/Module/Contact.php | 18 +++++++++--------- view/theme/frio/theme.php | 4 ++-- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/mod/allfriends.php b/mod/allfriends.php index aa5fb0a679..cee067e97a 100644 --- a/mod/allfriends.php +++ b/mod/allfriends.php @@ -8,8 +8,8 @@ use Friendica\Content\ContactSelector; use Friendica\Core\L10n; use Friendica\Core\System; use Friendica\Database\DBA; -use Friendica\Model;\ -use Friendica\Module\Contact; +use Friendica\Model; +use Friendica\Module; use Friendica\Util\Proxy as ProxyUtils; @@ -95,7 +95,7 @@ function allfriends_content(App $a) $entries[] = $entry; } - $tab_str = Contact::getTabsHTML($a, $contact, 4); + $tab_str = Module\Contact::getTabsHTML($a, $contact, 4); $tpl = get_markup_template('viewcontact_template.tpl'); diff --git a/mod/common.php b/mod/common.php index c011c6d38a..25a6aef17a 100644 --- a/mod/common.php +++ b/mod/common.php @@ -8,7 +8,7 @@ use Friendica\Content\ContactSelector; use Friendica\Core\L10n; use Friendica\Database\DBA; use Friendica\Model; -use Friendica\Module\Contact; +use Friendica\Module; use Friendica\Util\Proxy as ProxyUtils; @@ -41,7 +41,7 @@ function common_content(App $a) if (DBA::isResult($contact)) { $a->page['aside'] = ""; - Model\Profile::load($a, "", 0,Model\Contact::getDetailsByURL($contact["url"])); + Model\Profile::load($a, "", 0, Model\Contact::getDetailsByURL($contact["url"])); } } else { $contact = DBA::selectFirst('contact', ['name', 'url', 'photo', 'uid', 'id'], ['self' => true, 'uid' => $uid]); @@ -64,7 +64,7 @@ function common_content(App $a) return; } - if (!$cid &&Model\Profile::getMyURL()) { + if (!$cid && Model\Profile::getMyURL()) { $contact = DBA::selectFirst('contact', ['id'], ['nurl' => normalise_link(Model\Profile::getMyURL()), 'uid' => $uid]); if (DBA::isResult($contact)) { $cid = $contact['id']; @@ -81,9 +81,9 @@ function common_content(App $a) } if ($cid) { - $t =Model\GContact::countCommonFriends($uid, $cid); + $t = Model\GContact::countCommonFriends($uid, $cid); } else { - $t =Model\GContact::countCommonFriendsZcid($uid, $zcid); + $t = Model\GContact::countCommonFriendsZcid($uid, $zcid); } if ($t > 0) { @@ -94,9 +94,9 @@ function common_content(App $a) } if ($cid) { - $r =Model\GContact::commonFriends($uid, $cid, $a->pager['start'], $a->pager['itemspage']); + $r = Model\GContact::commonFriends($uid, $cid, $a->pager['start'], $a->pager['itemspage']); } else { - $r =Model\GContact::commonFriendsZcid($uid, $zcid, $a->pager['start'], $a->pager['itemspage']); + $r = Model\GContact::commonFriendsZcid($uid, $zcid, $a->pager['start'], $a->pager['itemspage']); } if (!DBA::isResult($r)) { @@ -108,13 +108,13 @@ function common_content(App $a) $entries = []; foreach ($r as $rr) { //get further details of the contact - $contact_details =Model\Contact::getDetailsByURL($rr['url'], $uid); + $contact_details = Model\Contact::getDetailsByURL($rr['url'], $uid); // $rr['id'] is needed to use contact_photo_menu() /// @TODO Adding '/" here avoids E_NOTICE on missing constants $rr['id'] = $rr['cid']; - $photo_menu =Model\Contact::photoMenu($rr); + $photo_menu = Model\Contact::photoMenu($rr); $entry = [ 'url' => $rr['url'], @@ -125,7 +125,7 @@ function common_content(App $a) 'details' => $contact_details['location'], 'tags' => $contact_details['keywords'], 'about' => $contact_details['about'], - 'account_type' =>Model\Contact::getAccountType($contact_details), + 'account_type' => Model\Contact::getAccountType($contact_details), 'network' => ContactSelector::networkToName($contact_details['network'], $contact_details['url']), 'photo_menu' => $photo_menu, 'id' => ++$id, @@ -136,7 +136,7 @@ function common_content(App $a) $title = ''; $tab_str = ''; if ($cmd === 'loc' && $cid && local_user() == $uid) { - $tab_str = Contact::getTabsHTML($a, $contact, 4); + $tab_str = Module\Contact::getTabsHTML($a, $contact, 4); } else { $title = L10n::t('Common Friends'); } diff --git a/mod/crepair.php b/mod/crepair.php index 14ed89afbc..c9050b3cce 100644 --- a/mod/crepair.php +++ b/mod/crepair.php @@ -9,7 +9,7 @@ use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Database\DBA; use Friendica\Model; -use Friendica\Module\Contact; +use Friendica\Module; function crepair_init(App $a) { @@ -28,7 +28,7 @@ function crepair_init(App $a) if (DBA::isResult($contact)) { $a->data['contact'] = $contact; - Profile::load($a, "", 0, Contact::getDetailsByURL($contact["url"])); + Profile::load($a, "", 0, Module\Contact::getDetailsByURL($contact["url"])); } } @@ -133,7 +133,7 @@ function crepair_content(App $a) $update_profile = in_array($contact['network'], [Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]); - $tab_str = Contact::getTabsHTML($a, $contact, 5); + $tab_str = Module\Contact::getTabsHTML($a, $contact, 5); $tpl = get_markup_template('crepair.tpl'); $o = replace_macros($tpl, [ diff --git a/mod/dirfind.php b/mod/dirfind.php index 8fcf98d402..ea5aae669a 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -13,7 +13,7 @@ use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\Model; -use Friendica\Module\Contact; +use Friendica\Module; use Friendica\Network\Probe; use Friendica\Protocol\PortableContact; use Friendica\Util\Network; @@ -209,8 +209,8 @@ function dirfind_content(App $a, $prefix = "") { $conntxt = ""; $contact = DBA::selectFirst('contact', [], ['id' => $jj->cid]); if (DBA::isResult($contact)) { - $photo_menu =Model\Contact::photoMenu($contact); - $details = Contact::getContactTemplateVars($contact); + $photo_menu = Model\Contact::photoMenu($contact); + $details = Module\Contact::getContactTemplateVars($contact); $alt_text = $details['alt_text']; } else { $photo_menu = []; @@ -226,7 +226,7 @@ function dirfind_content(App $a, $prefix = "") { $photo_menu = []; } - $photo_menu['profile'] = [L10n::t("View Profile"), Contact::magicLink($jj->url)]; + $photo_menu['profile'] = [L10n::t("View Profile"), Module\Contact::magicLink($jj->url)]; $photo_menu['follow'] = [L10n::t("Connect/Follow"), $connlnk]; } diff --git a/mod/group.php b/mod/group.php index 962697c24f..5bc188e50d 100644 --- a/mod/group.php +++ b/mod/group.php @@ -12,7 +12,7 @@ use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model; -use Friendica\Module\Contact; +use Friendica\Module; function group_init(App $a) { if (local_user()) { @@ -249,7 +249,7 @@ function group_content(App $a) { // Format the data of the group members foreach ($members as $member) { if ($member['url']) { - $entry = Contact::getContactTemplateVars($member); + $entry = Module\Contact::getContactTemplateVars($member); $entry['label'] = 'members'; $entry['photo_menu'] = ''; $entry['change_member'] = [ @@ -278,7 +278,7 @@ function group_content(App $a) { // Format the data of the contacts who aren't in the contact group foreach ($r as $member) { if (!in_array($member['id'], $preselected)) { - $entry = Contact::getContactTemplateVars($member); + $entry = Module\Contact::getContactTemplateVars($member); $entry['label'] = 'contacts'; if (!$nogroup) $entry['photo_menu'] = []; diff --git a/src/Module/Contact.php b/src/Module/Contact.php index 07b7c907da..ba06b7e0b3 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -190,7 +190,7 @@ class Contact extends BaseModule if (!DBA::exists('contact', ['id' => $contact_id, 'uid' => local_user()])) { notice(L10n::t('Could not access contact record.') . EOL); - goaway('contacts'); + goaway('contact'); return; // NOTREACHED } @@ -370,7 +370,7 @@ class Contact extends BaseModule $a = self::getApp(); $sort_type = 0; $o = ''; - Nav::setSelected('contacts'); + Nav::setSelected('contact'); if (!local_user()) { notice(L10n::t('Permission denied.') . EOL); @@ -388,13 +388,13 @@ class Contact extends BaseModule $orig_record = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => [0, local_user()], 'self' => false]); if (!DBA::isResult($orig_record)) { notice(L10n::t('Could not access contact record.') . EOL); - goaway('contacts'); + goaway('contact'); return; // NOTREACHED } if ($cmd === 'update' && ($orig_record['uid'] != 0)) { self::updateContactFromPoll($contact_id); - goaway('contacts/' . $contact_id); + goaway('contact/' . $contact_id); // NOTREACHED } @@ -410,7 +410,7 @@ class Contact extends BaseModule $blocked = Model\Contact::isBlockedByUser($contact_id, local_user()); info(($blocked ? L10n::t('Contact has been blocked') : L10n::t('Contact has been unblocked')) . EOL); - goaway('contacts/' . $contact_id); + goaway('contact/' . $contact_id); return; // NOTREACHED } @@ -420,7 +420,7 @@ class Contact extends BaseModule $ignored = Model\Contact::isIgnoredByUser($contact_id, local_user()); info(($ignored ? L10n::t('Contact has been ignored') : L10n::t('Contact has been unignored')) . EOL); - goaway('contacts/' . $contact_id); + goaway('contact/' . $contact_id); return; // NOTREACHED } @@ -431,7 +431,7 @@ class Contact extends BaseModule info((($archived) ? L10n::t('Contact has been archived') : L10n::t('Contact has been unarchived')) . EOL); } - goaway('contacts/' . $contact_id); + goaway('contact/' . $contact_id); return; // NOTREACHED } @@ -465,13 +465,13 @@ class Contact extends BaseModule } // Now check how the user responded to the confirmation query if (defaults($_REQUEST, 'canceled')) { - goaway('contacts'); + goaway('contact'); } self::dropContact($orig_record); info(L10n::t('Contact has been removed.') . EOL); - goaway('contacts'); + goaway('contact'); return; // NOTREACHED } if ($cmd === 'posts') { diff --git a/view/theme/frio/theme.php b/view/theme/frio/theme.php index 58904911c1..f46b42788f 100644 --- a/view/theme/frio/theme.php +++ b/view/theme/frio/theme.php @@ -17,7 +17,7 @@ use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model; -use Friendica\Module\Contact; +use Friendica\Module; $frio = 'view/theme/frio'; @@ -333,7 +333,7 @@ function frio_acl_lookup(App $a, &$results) if (DBA::isResult($r)) { foreach ($r as $rr) { - $contacts[] = Model\Contact::getContactTemplateVars($rr); + $contacts[] = Module\Contact::getContactTemplateVars($rr); } } From d54e56c659103e43647fab68bb740b24528ddf0c Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Sun, 14 Oct 2018 21:14:32 +0200 Subject: [PATCH 387/428] Fix batch action query + Fix Namespace import --- mod/crepair.php | 2 +- mod/dirfind.php | 2 +- src/Module/Contact.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mod/crepair.php b/mod/crepair.php index c9050b3cce..af9575ed6d 100644 --- a/mod/crepair.php +++ b/mod/crepair.php @@ -28,7 +28,7 @@ function crepair_init(App $a) if (DBA::isResult($contact)) { $a->data['contact'] = $contact; - Profile::load($a, "", 0, Module\Contact::getDetailsByURL($contact["url"])); + Model\Profile::load($a, "", 0, Model\Contact::getDetailsByURL($contact["url"])); } } diff --git a/mod/dirfind.php b/mod/dirfind.php index ea5aae669a..3e5aa83a72 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -226,7 +226,7 @@ function dirfind_content(App $a, $prefix = "") { $photo_menu = []; } - $photo_menu['profile'] = [L10n::t("View Profile"), Module\Contact::magicLink($jj->url)]; + $photo_menu['profile'] = [L10n::t("View Profile"), Model\Contact::magicLink($jj->url)]; $photo_menu['follow'] = [L10n::t("Connect/Follow"), $connlnk]; } diff --git a/src/Module/Contact.php b/src/Module/Contact.php index ba06b7e0b3..30ad60d4b7 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -134,7 +134,7 @@ class Contact extends BaseModule $contacts_id = $_POST['contact_batch']; - $stmt = DBA::select('contact', ['id'], ['id' => $contacts_id, 'id' => local_user(), 'self' => false]); + $stmt = DBA::select('contact', ['id'], ['id' => $contacts_id, 'uid' => local_user(), 'self' => false]); $orig_records = DBA::toArray($stmt); $count_actions = 0; From e41c59b1934e55178be75e9201b013e5ec7b9ba9 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Sun, 14 Oct 2018 21:38:38 +0200 Subject: [PATCH 388/428] Fix batch action choice - All Actions for one contact were taken before --- src/Module/Contact.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Module/Contact.php b/src/Module/Contact.php index 30ad60d4b7..db1675a7f8 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -140,25 +140,25 @@ class Contact extends BaseModule $count_actions = 0; foreach ($orig_records as $orig_record) { $contact_id = $orig_record['id']; - if (defaults($_POST, 'contacts_batch_update')) { + if (defaults($_POST, 'contacts_batch_update', '')) { self::updateContactFromPoll($contact_id); $count_actions++; } - if (defaults($_POST, 'contacts_batch_block')) { + if (defaults($_POST, 'contacts_batch_block', '')) { self::blockContact($contact_id); $count_actions++; } - if (defaults($_POST, 'contacts_batch_ignore')) { + if (defaults($_POST, 'contacts_batch_ignore', '')) { self::ignoreContact($contact_id); $count_actions++; } - if (defaults($_POST, 'contacts_batch_archive')) { + if (defaults($_POST, 'contacts_batch_archive', '')) { $r = self::archiveContact($contact_id, $orig_record); if ($r) { $count_actions++; } } - if (defaults($_POST, 'contacts_batch_drop')) { + if (defaults($_POST, 'contacts_batch_drop', '')) { self::dropContact($orig_record); $count_actions++; } From 3a95644848ecf3729df274dbd84b266283e9d204 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Sun, 14 Oct 2018 22:57:44 +0200 Subject: [PATCH 389/428] Add Support for relativeDateTime in future + update Admin user waiting for deleting table header --- mod/admin.php | 2 +- src/Util/Temporal.php | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/mod/admin.php b/mod/admin.php index d0e8ab0e38..b02db73bdd 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -1922,7 +1922,7 @@ function admin_page_users(App $a) '$h_users' => L10n::t('Users'), '$h_newuser' => L10n::t('New User'), - '$th_deleted' => [L10n::t('Name'), L10n::t('Email'), L10n::t('Register date'), L10n::t('Last login'), L10n::t('Last item'), L10n::t('Deleted since')], + '$th_deleted' => [L10n::t('Name'), L10n::t('Email'), L10n::t('Register date'), L10n::t('Last login'), L10n::t('Last item'), L10n::t('Delete in')], '$th_users' => $th_users, '$order_users' => $order, '$order_direction_users' => $order_direction, diff --git a/src/Util/Temporal.php b/src/Util/Temporal.php index 46bd8bba50..696721e458 100644 --- a/src/Util/Temporal.php +++ b/src/Util/Temporal.php @@ -294,12 +294,18 @@ class Temporal return L10n::t('never'); } + $isfuture = false; $etime = time() - $abs; - if ($etime < 1) { + if ($etime < 1 && $etime >= 0) { return L10n::t('less than a second ago'); } + if ($etime < 0){ + $etime = -$etime; + $isfuture = true; + } + $a = [12 * 30 * 24 * 60 * 60 => [L10n::t('year'), L10n::t('years')], 30 * 24 * 60 * 60 => [L10n::t('month'), L10n::t('months')], 7 * 24 * 60 * 60 => [L10n::t('week'), L10n::t('weeks')], @@ -315,7 +321,12 @@ class Temporal $r = round($d); // translators - e.g. 22 hours ago, 1 minute ago if (!$format) { - $format = L10n::t('%1$d %2$s ago'); + if($isfuture){ + $format = L10n::t('in %1$d %2$s'); + } + else { + $format = L10n::t('%1$d %2$s ago'); + } } return sprintf($format, $r, (($r == 1) ? $str[0] : $str[1])); From 756a4f111163195eb46442d86b915d6676aa0935 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 18:02:54 -0400 Subject: [PATCH 390/428] Fix remaining instances of "contacts" --- src/Model/Group.php | 4 ++-- src/Module/Contact.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Model/Group.php b/src/Model/Group.php index 71f7941189..e313842e41 100644 --- a/src/Model/Group.php +++ b/src/Model/Group.php @@ -349,7 +349,7 @@ class Group extends BaseObject * @param int $cid * @return string */ - public static function sidebarWidget($every = 'contacts', $each = 'group', $editmode = 'standard', $group_id = '', $cid = 0) + public static function sidebarWidget($every = 'contact', $each = 'group', $editmode = 'standard', $group_id = '', $cid = 0) { $o = ''; @@ -404,7 +404,7 @@ class Group extends BaseObject 'newgroup' => $editmode == 'extended' || $editmode == 'full' ? 1 : '', 'grouppage' => 'group/', '$edittext' => L10n::t('Edit group'), - '$ungrouped' => $every === 'contacts' ? L10n::t('Contacts not in any group') : '', + '$ungrouped' => $every === 'contact' ? L10n::t('Contacts not in any group') : '', '$ungrouped_selected' => (($group_id === 'none') ? 'group-selected' : ''), '$createtext' => L10n::t('Create a new group'), '$creategroup' => L10n::t('Group Name: '), diff --git a/src/Module/Contact.php b/src/Module/Contact.php index db1675a7f8..560e91560b 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -94,7 +94,7 @@ class Contact extends BaseModule $networks_widget = ''; } else { $vcard_widget = ''; - $networks_widget = Widget::networks('contacts', $nets); + $networks_widget = Widget::networks('contact', $nets); if (isset($_GET['add'])) { $follow_widget = Widget::follow($_GET['add']); } else { @@ -105,7 +105,7 @@ class Contact extends BaseModule } if ($contact['uid'] != 0) { - $groups_widget = Model\Group::sidebarWidget('contacts', 'group', 'full', 'everyone', $contact_id); + $groups_widget = Model\Group::sidebarWidget('contact', 'group', 'full', 'everyone', $contact_id); } else { $groups_widget = null; } From 57e8fb5cb176dfd551ea3ee8d975d1240bb0d1bf Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 18:17:22 -0400 Subject: [PATCH 391/428] Normalize uses of defaults() in Module\Contact - Remove uses without default value - Add relevant uses --- src/Module/Contact.php | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/Module/Contact.php b/src/Module/Contact.php index 560e91560b..93b05df659 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -83,7 +83,7 @@ class Contact extends BaseModule '$name' => htmlentities($a->data['contact']['name']), '$photo' => $a->data['contact']['photo'], '$url' => Model\Contact::MagicLink($a->data['contact']['url']), - '$addr' => (($a->data['contact']['addr'] != "") ? ($a->data['contact']['addr']) : ""), + '$addr' => defaults($contact, 'addr', ''), '$network_name' => $networkname, '$network' => L10n::t('Network:'), '$account_type' => Model\Contact::getAccountType($a->data['contact']) @@ -140,25 +140,24 @@ class Contact extends BaseModule $count_actions = 0; foreach ($orig_records as $orig_record) { $contact_id = $orig_record['id']; - if (defaults($_POST, 'contacts_batch_update', '')) { + if (!empty($_POST['contacts_batch_update'])) { self::updateContactFromPoll($contact_id); $count_actions++; } - if (defaults($_POST, 'contacts_batch_block', '')) { + if (!empty($_POST['contacts_batch_block'])) { self::blockContact($contact_id); $count_actions++; } - if (defaults($_POST, 'contacts_batch_ignore', '')) { + if (!empty($_POST['contacts_batch_ignore'])) { self::ignoreContact($contact_id); $count_actions++; } - if (defaults($_POST, 'contacts_batch_archive', '')) { - $r = self::archiveContact($contact_id, $orig_record); - if ($r) { - $count_actions++; - } + if (!empty($_POST['contacts_batch_archive']) + && self::archiveContact($contact_id, $orig_record) + ) { + $count_actions++; } - if (defaults($_POST, 'contacts_batch_drop', '')) { + if (!empty($_POST['contacts_batch_drop'])) { self::dropContact($orig_record); $count_actions++; } @@ -204,9 +203,9 @@ class Contact extends BaseModule } } - $hidden = defaults($_POST['hidden']); + $hidden = !empty($_POST['hidden']); - $notify = defaults($_POST['notify']); + $notify = !empty($_POST['notify']); $fetch_further_information = intval(defaults($_POST, 'fetch_further_information', 0)); @@ -437,8 +436,8 @@ class Contact extends BaseModule if ($cmd === 'drop' && ($orig_record['uid'] != 0)) { // Check if we should do HTML-based delete confirmation - if (defaults($_REQUEST, 'confirm')) { - // can't take arguments in its "action" parameter + if (!empty($_REQUEST['confirm'])) { + // can't take arguments in its 'action' parameter // so add any arguments as hidden inputs $query = explode_querystring($a->query_string); $inputs = []; @@ -464,7 +463,7 @@ class Contact extends BaseModule ]); } // Now check how the user responded to the confirmation query - if (defaults($_REQUEST, 'canceled')) { + if (!empty($_REQUEST['canceled'])) { goaway('contact'); } @@ -484,7 +483,7 @@ class Contact extends BaseModule $_SESSION['return_url'] = $a->query_string; - if ((defaults($a->data, 'contact')) && (is_array($a->data['contact']))) { + if (!empty($a->data['contact']) && is_array($a->data['contact'])) { $contact_id = $a->data['contact']['id']; $contact = $a->data['contact']; @@ -705,8 +704,8 @@ class Contact extends BaseModule $sql_extra .= sprintf(" AND `network` != '%s' ", Protocol::PHANTOM); - $search = defaults($_GET, 'search') ? notags(trim($_GET['search'])) : ''; - $nets = defaults($_GET, 'nets' ) ? notags(trim($_GET['nets'])) : ''; + $search = notags(trim(defaults($_GET, 'search', ''))); + $nets = notags(trim(defaults($_GET, 'nets' , ''))); $tabs = [ [ @@ -1043,7 +1042,7 @@ class Contact extends BaseModule 'username' => htmlentities($rr['name']), 'account_type' => Model\Contact::getAccountType($rr), 'sparkle' => $sparkle, - 'itemurl' => (($rr['addr'] != "") ? $rr['addr'] : $rr['url']), + 'itemurl' => defaults($rr, 'addr', $rr['url']), 'url' => $url, 'network' => ContactSelector::networkToName($rr['network'], $rr['url']), 'nick' => htmlentities($rr['nick']), From 12ddb3bb5472cac5292131b9002935904e846fc2 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 18:25:44 -0400 Subject: [PATCH 392/428] Replace unwarranted uses of $a->data['contact'] --- src/Module/Contact.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Module/Contact.php b/src/Module/Contact.php index 93b05df659..74dac524a0 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -72,21 +72,21 @@ class Contact extends BaseModule $a->data['contact'] = $contact; - if (($a->data['contact']['network'] != "") && ($a->data['contact']['network'] != Protocol::DFRN)) { - $networkname = format_network_name($a->data['contact']['network'], $a->data['contact']['url']); + if (($contact['network'] != '') && ($contact['network'] != Protocol::DFRN)) { + $networkname = format_network_name($contact['network'], $contact['url']); } else { $networkname = ''; } /// @TODO Add nice spaces - $vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"), [ - '$name' => htmlentities($a->data['contact']['name']), - '$photo' => $a->data['contact']['photo'], - '$url' => Model\Contact::MagicLink($a->data['contact']['url']), + $vcard_widget = replace_macros(get_markup_template('vcard-widget.tpl'), [ + '$name' => htmlentities($contact['name']), + '$photo' => $contact['photo'], + '$url' => Model\Contact::MagicLink($contact['url']), '$addr' => defaults($contact, 'addr', ''), '$network_name' => $networkname, - '$network' => L10n::t('Network:'), - '$account_type' => Model\Contact::getAccountType($a->data['contact']) + '$network' => L10n::t('Network:'), + '$account_type' => Model\Contact::getAccountType($contact) ]); $findpeople_widget = ''; From a883a99fe6533c4378091c37fac1c8e335c1bdeb Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 18:27:24 -0400 Subject: [PATCH 393/428] Replace string fields by array in Module\Contact --- src/Module/Contact.php | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/Module/Contact.php b/src/Module/Contact.php index 74dac524a0..6c0d876050 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -281,45 +281,34 @@ class Contact extends BaseModule return; } - $updatefields = ["name", "nick", "url", "addr", "batch", "notify", "poll", "request", "confirm", - "poco", "network", "alias"]; - $update = []; + $updatefields = ['name', 'nick', 'url', 'addr', 'batch', 'notify', 'poll', 'request', 'confirm', 'poco', 'network', 'alias']; + $fields = []; - if ($data["network"] == Protocol::OSTATUS) { - $result = Model\Contact::createFromProbe($uid, $data["url"], false); + if ($data['network'] == Protocol::OSTATUS) { + $result = Model\Contact::createFromProbe($uid, $data['url'], false); if ($result['success']) { - $update["subhub"] = true; + $fields['subhub'] = true; } } foreach ($updatefields AS $field) { - if (isset($data[$field]) && ($data[$field] != "")) { - $update[$field] = $data[$field]; + if (!empty($data[$field])) { + $fields[$field] = $data[$field]; } } - $update["nurl"] = normalise_link($data["url"]); + $fields['nurl'] = normalise_link($data['url']); - $query = ""; - - if (isset($data["priority"]) && ($data["priority"] != 0)) { - $query = "'priority' => '" . intval($data["priority"]) . "'"; + if (!empty($data['priority'])) { + $fields['priority'] = intval($data['priority']); } - foreach ($update AS $key => $value) { - if ($query != "") { - $query .= ", "; - } - - $query .= "'" . $key . "' => '" . DBA::escape($value) . "'"; - } - - if ($query == "") { + if (empty($fields)) { return; } - $r = DBA::update('contact', $query, ['id' => $contact_id, 'uid' => local_user()]); + $r = DBA::update('contact', $fields, ['id' => $contact_id, 'uid' => local_user()]); // Update the entry in the contact table Model\Contact::updateAvatar($data['photo'], local_user(), $contact_id, true); From aa8039373a0017001dd8e020031d78c16d064d0d Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 18:30:02 -0400 Subject: [PATCH 394/428] Update formatting of Module\Contact - Replace double quotes with single - Align array declarations - Replace q() call with Model\User::getOwnerDataById() --- src/Module/Contact.php | 305 ++++++++++++++++++++--------------------- 1 file changed, 150 insertions(+), 155 deletions(-) diff --git a/src/Module/Contact.php b/src/Module/Contact.php index 6c0d876050..0eb912e00a 100644 --- a/src/Module/Contact.php +++ b/src/Module/Contact.php @@ -26,7 +26,7 @@ use Friendica\Module\Login; * * @brief manages contacts */ -class Contact extends BaseModule +class Contact extends BaseModule { public static function init() { @@ -37,8 +37,8 @@ class Contact extends BaseModule } $nets = defaults($_GET, 'nets', ''); - if ($nets == "all") { - $nets = ""; + if ($nets == 'all') { + $nets = ''; } if (!x($a->page, 'aside')) { @@ -47,7 +47,9 @@ class Contact extends BaseModule $contact_id = null; $contact = null; - if ((($a->argc == 2) && intval($a->argv[1])) || (($a->argc == 3) && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations']))) { + if ($a->argc == 2 && intval($a->argv[1]) + || $a->argc == 3 && intval($a->argv[1]) && in_array($a->argv[2], ['posts', 'conversations']) + ) { $contact_id = intval($a->argv[1]); $contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]); @@ -110,16 +112,16 @@ class Contact extends BaseModule $groups_widget = null; } - $a->page['aside'] .= replace_macros(get_markup_template("contacts-widget-sidebar.tpl"), [ - '$vcard_widget' => $vcard_widget, + $a->page['aside'] .= replace_macros(get_markup_template('contacts-widget-sidebar.tpl'), [ + '$vcard_widget' => $vcard_widget, '$findpeople_widget' => $findpeople_widget, - '$follow_widget' => $follow_widget, - '$groups_widget' => $groups_widget, - '$networks_widget' => $networks_widget + '$follow_widget' => $follow_widget, + '$groups_widget' => $groups_widget, + '$networks_widget' => $networks_widget ]); $base = $a->getBaseURL(); - $tpl = get_markup_template("contacts-head.tpl"); + $tpl = get_markup_template('contacts-head.tpl'); $a->page['htmlhead'] .= replace_macros($tpl, [ '$baseurl' => System::baseUrl(true), '$base' => $base @@ -136,7 +138,7 @@ class Contact extends BaseModule $stmt = DBA::select('contact', ['id'], ['id' => $contacts_id, 'uid' => local_user(), 'self' => false]); $orig_records = DBA::toArray($stmt); - + $count_actions = 0; foreach ($orig_records as $orig_record) { $contact_id = $orig_record['id']; @@ -163,7 +165,7 @@ class Contact extends BaseModule } } if ($count_actions > 0) { - info(L10n::tt("%d contact edited.", "%d contacts edited.", $count_actions)); + info(L10n::tt('%d contact edited.', '%d contacts edited.', $count_actions)); } goaway('contact'); @@ -177,7 +179,7 @@ class Contact extends BaseModule return; } - if ($a->argv[1] === "batch") { + if ($a->argv[1] === 'batch') { self::batchActions($a); return; } @@ -218,15 +220,16 @@ class Contact extends BaseModule $info = escape_tags(trim($_POST['info'])); - $r = DBA::update('contact', - ['profile-id' => $profile_id, - 'priority' => $priority, - 'info' => $info, - 'hidden' => $hidden, - 'notify_new_posts' => $notify, - 'fetch_further_information' => $fetch_further_information, - 'ffi_keyword_blacklist' => $ffi_keyword_blacklist], - ['id' => $contact_id, 'uid' => local_user()]); + $r = DBA::update('contact', [ + 'profile-id' => $profile_id, + 'priority' => $priority, + 'info' => $info, + 'hidden' => $hidden, + 'notify_new_posts' => $notify, + 'fetch_further_information' => $fetch_further_information, + 'ffi_keyword_blacklist' => $ffi_keyword_blacklist], + ['id' => $contact_id, 'uid' => local_user()] + ); if (DBA::isResult($r)) { info(L10n::t('Contact updated.') . EOL); @@ -251,17 +254,17 @@ class Contact extends BaseModule return; } - $uid = $contact["uid"]; + $uid = $contact['uid']; - if ($contact["network"] == Protocol::OSTATUS) { - $result = Model\Contact::createFromProbe($uid, $contact["url"], false, $contact["network"]); + if ($contact['network'] == Protocol::OSTATUS) { + $result = Model\Contact::createFromProbe($uid, $contact['url'], false, $contact['network']); if ($result['success']) { DBA::update('contact', ['subhub' => 1], ['id' => $contact_id]); } } else { // pull feed and consume it, which should subscribe to the hub. - Worker::add(PRIORITY_HIGH, "OnePoll", $contact_id, "force"); + Worker::add(PRIORITY_HIGH, 'OnePoll', $contact_id, 'force'); } } @@ -272,12 +275,12 @@ class Contact extends BaseModule return; } - $uid = $contact["uid"]; + $uid = $contact['uid']; - $data = Probe::uri($contact["url"], "", 0, false); + $data = Probe::uri($contact['url'], '', 0, false); - // "Feed" or "Unknown" is mostly a sign of communication problems - if ((in_array($data["network"], [Protocol::FEED, Protocol::PHANTOM])) && ($data["network"] != $contact["network"])) { + // 'Feed' or 'Unknown' is mostly a sign of communication problems + if ((in_array($data['network'], [Protocol::FEED, Protocol::PHANTOM])) && ($data['network'] != $contact['network'])) { return; } @@ -314,7 +317,7 @@ class Contact extends BaseModule Model\Contact::updateAvatar($data['photo'], local_user(), $contact_id, true); // Update the entry in the gcontact table - Model\GContact::updateFromProbe($data["url"]); + Model\GContact::updateFromProbe($data['url']); } private static function blockContact($contact_id) @@ -339,17 +342,12 @@ class Contact extends BaseModule private static function dropContact($orig_record) { - $a = get_app(); - - $r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` - WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1", - intval($a->user['uid']) - ); - if (!DBA::isResult($r)) { + $owner = Model\User::getOwnerDataById(local_user()); + if (!DBA::isResult($owner)) { return; } - Model\Contact::terminateFriendship($r[0], $orig_record, true); + Model\Contact::terminateFriendship($owner, $orig_record, true); Model\Contact::remove($orig_record['id']); } @@ -480,7 +478,7 @@ class Contact extends BaseModule '$baseurl' => $a->getBaseURL(true), ]); - $contact['blocked'] = Model\Contact::isBlockedByUser($contact['id'], local_user()); + $contact['blocked'] = Model\Contact::isBlockedByUser($contact['id'], local_user()); $contact['readonly'] = Model\Contact::isIgnoredByUser($contact['id'], local_user()); $dir_icon = ''; @@ -510,7 +508,7 @@ class Contact extends BaseModule } if (!in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::OSTATUS, Protocol::DIASPORA])) { - $relation_text = ""; + $relation_text = ''; } $relation_text = sprintf($relation_text, htmlentities($contact['name'])); @@ -527,13 +525,13 @@ class Contact extends BaseModule $last_update = (($contact['last-update'] <= NULL_DATE) ? L10n::t('Never') : DateTimeFormat::local($contact['last-update'], 'D, j M Y, g:i A')); if ($contact['last-update'] > NULL_DATE) { - $last_update .= ' ' . (($contact['last-update'] <= $contact['success_update']) ? L10n::t("\x28Update was successful\x29") : L10n::t("\x28Update was not successful\x29")); + $last_update .= ' ' . (($contact['last-update'] <= $contact['success_update']) ? L10n::t('(Update was successful)') : L10n::t('(Update was not successful)')); } $lblsuggest = (($contact['network'] === Protocol::DFRN) ? L10n::t('Suggest friends') : ''); $poll_enabled = in_array($contact['network'], [Protocol::DFRN, Protocol::OSTATUS, Protocol::FEED, Protocol::MAIL]); - $nettype = L10n::t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact["url"])); + $nettype = L10n::t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact['url'])); // tabs $tab_str = self::getTabsHTML($a, $contact, 3); @@ -546,8 +544,9 @@ class Contact extends BaseModule 'fetch_further_information', L10n::t('Fetch further information for feeds'), $contact['fetch_further_information'], - L10n::t("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."), - ['0' => L10n::t('Disabled'), + L10n::t('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.'), + [ + '0' => L10n::t('Disabled'), '1' => L10n::t('Fetch information'), '3' => L10n::t('Fetch keywords'), '2' => L10n::t('Fetch information and keywords') @@ -557,12 +556,12 @@ class Contact extends BaseModule $poll_interval = null; if (in_array($contact['network'], [Protocol::FEED, Protocol::MAIL])) { - $poll_interval = ContactSelector::pollInterval($contact['priority'], (!$poll_enabled)); + $poll_interval = ContactSelector::pollInterval($contact['priority'], !$poll_enabled); } $profile_select = null; if ($contact['network'] == Protocol::DFRN) { - $profile_select = ContactSelector::profileAssign($contact['profile-id'], (($contact['network'] !== Protocol::DFRN) ? true : false)); + $profile_select = ContactSelector::profileAssign($contact['profile-id'], $contact['network'] !== Protocol::DFRN); } /// @todo Only show the following link with DFRN when the remote version supports it @@ -570,12 +569,12 @@ class Contact extends BaseModule $follow_text = ''; if (in_array($contact['rel'], [Model\Contact::FRIEND, Model\Contact::SHARING])) { if (in_array($contact['network'], Protocol::NATIVE_SUPPORT)) { - $follow = $a->getBaseURL(true) . "/unfollow?url=" . urlencode($contact["url"]); - $follow_text = L10n::t("Disconnect/Unfollow"); + $follow = $a->getBaseURL(true) . '/unfollow?url=' . urlencode($contact['url']); + $follow_text = L10n::t('Disconnect/Unfollow'); } } else { - $follow = $a->getBaseURL(true) . "/follow?url=" . urlencode($contact["url"]); - $follow_text = L10n::t("Connect/Follow"); + $follow = $a->getBaseURL(true) . '/follow?url=' . urlencode($contact['url']); + $follow_text = L10n::t('Connect/Follow'); } // Load contactact related actions like hide, suggest, delete and others @@ -591,72 +590,72 @@ class Contact extends BaseModule $contact_settings_label = null; } - $tpl = get_markup_template("contact_edit.tpl"); + $tpl = get_markup_template('contact_edit.tpl'); $o .= replace_macros($tpl, [ - '$header' => L10n::t("Contact"), - '$tab_str' => $tab_str, - '$submit' => L10n::t('Submit'), - '$lbl_vis1' => $lbl_vis1, - '$lbl_vis2' => L10n::t('Please choose the profile you would like to display to %s when viewing your profile securely.', $contact['name']), - '$lbl_info1' => $lbl_info1, - '$lbl_info2' => L10n::t('Their personal note'), - '$reason' => trim(notags($contact['reason'])), - '$infedit' => L10n::t('Edit contact notes'), - '$common_link' => 'common/loc/' . local_user() . '/' . $contact['id'], - '$relation_text' => $relation_text, - '$visit' => L10n::t('Visit %s\'s profile [%s]', $contact['name'], $contact['url']), - '$blockunblock' => L10n::t('Block/Unblock contact'), - '$ignorecont' => L10n::t('Ignore contact'), - '$lblcrepair' => L10n::t("Repair URL settings"), - '$lblrecent' => L10n::t('View conversations'), - '$lblsuggest' => $lblsuggest, - '$nettype' => $nettype, - '$poll_interval' => $poll_interval, - '$poll_enabled' => $poll_enabled, - '$lastupdtext' => L10n::t('Last update:'), - '$lost_contact' => $lost_contact, - '$updpub' => L10n::t('Update public posts'), - '$last_update' => $last_update, - '$udnow' => L10n::t('Update now'), - '$follow' => $follow, - '$follow_text' => $follow_text, + '$header' => L10n::t('Contact'), + '$tab_str' => $tab_str, + '$submit' => L10n::t('Submit'), + '$lbl_vis1' => $lbl_vis1, + '$lbl_vis2' => L10n::t('Please choose the profile you would like to display to %s when viewing your profile securely.', $contact['name']), + '$lbl_info1' => $lbl_info1, + '$lbl_info2' => L10n::t('Their personal note'), + '$reason' => trim(notags($contact['reason'])), + '$infedit' => L10n::t('Edit contact notes'), + '$common_link' => 'common/loc/' . local_user() . '/' . $contact['id'], + '$relation_text' => $relation_text, + '$visit' => L10n::t('Visit %s\'s profile [%s]', $contact['name'], $contact['url']), + '$blockunblock' => L10n::t('Block/Unblock contact'), + '$ignorecont' => L10n::t('Ignore contact'), + '$lblcrepair' => L10n::t('Repair URL settings'), + '$lblrecent' => L10n::t('View conversations'), + '$lblsuggest' => $lblsuggest, + '$nettype' => $nettype, + '$poll_interval' => $poll_interval, + '$poll_enabled' => $poll_enabled, + '$lastupdtext' => L10n::t('Last update:'), + '$lost_contact' => $lost_contact, + '$updpub' => L10n::t('Update public posts'), + '$last_update' => $last_update, + '$udnow' => L10n::t('Update now'), + '$follow' => $follow, + '$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' => (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') : ''), - '$hidden' => ['hidden', L10n::t('Hide this contact from others'), ($contact['hidden'] == 1), L10n::t('Replies/likes to your public posts may 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')], + '$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' => (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') : ''), + '$hidden' => ['hidden', L10n::t('Hide this contact from others'), ($contact['hidden'] == 1), L10n::t('Replies/likes to your public posts may 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, '$ffi_keyword_blacklist' => $contact['ffi_keyword_blacklist'], '$ffi_keyword_blacklist' => ['ffi_keyword_blacklist', L10n::t('Blacklisted keywords'), $contact['ffi_keyword_blacklist'], L10n::t('Comma separated list of keywords that should not be converted to hashtags, when "Fetch information and keywords" is selected')], - '$photo' => $contact['photo'], - '$name' => htmlentities($contact['name']), - '$dir_icon' => $dir_icon, - '$sparkle' => $sparkle, - '$url' => $url, - '$profileurllabel' => L10n::t('Profile URL'), - '$profileurl' => $contact['url'], - '$account_type' => Model\Contact::getAccountType($contact), - '$location' => BBCode::convert($contact["location"]), - '$location_label' => L10n::t("Location:"), - '$xmpp' => BBCode::convert($contact["xmpp"]), - '$xmpp_label' => L10n::t("XMPP:"), - '$about' => BBCode::convert($contact["about"], false), - '$about_label' => L10n::t("About:"), - '$keywords' => $contact["keywords"], - '$keywords_label' => L10n::t("Tags:"), - '$contact_action_button' => L10n::t("Actions"), - '$contact_actions' => $contact_actions, - '$contact_status' => L10n::t("Status"), + '$photo' => $contact['photo'], + '$name' => htmlentities($contact['name']), + '$dir_icon' => $dir_icon, + '$sparkle' => $sparkle, + '$url' => $url, + '$profileurllabel'=> L10n::t('Profile URL'), + '$profileurl' => $contact['url'], + '$account_type' => Model\Contact::getAccountType($contact), + '$location' => BBCode::convert($contact['location']), + '$location_label' => L10n::t('Location:'), + '$xmpp' => BBCode::convert($contact['xmpp']), + '$xmpp_label' => L10n::t('XMPP:'), + '$about' => BBCode::convert($contact['about'], false), + '$about_label' => L10n::t('About:'), + '$keywords' => $contact['keywords'], + '$keywords_label' => L10n::t('Tags:'), + '$contact_action_button' => L10n::t('Actions'), + '$contact_actions'=> $contact_actions, + '$contact_status' => L10n::t('Status'), '$contact_settings_label' => $contact_settings_label, - '$contact_profile_label' => L10n::t("Profile"), + '$contact_profile_label' => L10n::t('Profile'), ]); $arr = ['contact' => $contact, 'output' => $o]; @@ -800,29 +799,29 @@ class Contact extends BaseModule } } - $tpl = get_markup_template("contacts-template.tpl"); + $tpl = get_markup_template('contacts-template.tpl'); $o .= replace_macros($tpl, [ - '$baseurl' => System::baseUrl(), - '$header' => L10n::t('Contacts') . (($nets) ? ' - ' . ContactSelector::networkToName($nets) : ''), - '$tabs' => $t, - '$total' => $total, - '$search' => $search_hdr, - '$desc' => L10n::t('Search your contacts'), - '$finding' => $searching ? L10n::t('Results for: %s', $search) : "", - '$submit' => L10n::t('Find'), - '$cmd' => $a->cmd, - '$contacts' => $contacts, + '$baseurl' => System::baseUrl(), + '$header' => L10n::t('Contacts') . (($nets) ? ' - ' . ContactSelector::networkToName($nets) : ''), + '$tabs' => $t, + '$total' => $total, + '$search' => $search_hdr, + '$desc' => L10n::t('Search your contacts'), + '$finding' => $searching ? L10n::t('Results for: %s', $search) : '', + '$submit' => L10n::t('Find'), + '$cmd' => $a->cmd, + '$contacts' => $contacts, '$contact_drop_confirm' => L10n::t('Do you really want to delete this contact?'), 'multiselect' => 1, '$batch_actions' => [ 'contacts_batch_update' => L10n::t('Update'), - 'contacts_batch_block' => L10n::t('Block') . "/" . L10n::t("Unblock"), - "contacts_batch_ignore" => L10n::t('Ignore') . "/" . L10n::t("Unignore"), - "contacts_batch_archive" => L10n::t('Archive') . "/" . L10n::t("Unarchive"), - "contacts_batch_drop" => L10n::t('Delete'), + 'contacts_batch_block' => L10n::t('Block') . '/' . L10n::t('Unblock'), + 'contacts_batch_ignore' => L10n::t('Ignore') . '/' . L10n::t('Unignore'), + 'contacts_batch_archive' => L10n::t('Archive') . '/' . L10n::t('Unarchive'), + 'contacts_batch_drop' => L10n::t('Delete'), ], '$h_batch_actions' => L10n::t('Batch Actions'), - '$paginate' => paginate($a), + '$paginate' => paginate($a), ]); return $o; @@ -938,18 +937,16 @@ class Contact extends BaseModule } if (DBA::isResult($contact)) { - $a->page['aside'] = ""; + $a->page['aside'] = ''; - $profiledata = Model\Contact::getDetailsByURL($contact["url"]); + $profiledata = Model\Contact::getDetailsByURL($contact['url']); - if (local_user()) { - if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { - $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]); - } + if (local_user() && in_array($profiledata['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { + $profiledata['remoteconnect'] = System::baseUrl() . '/follow?url=' . urlencode($profiledata['url']); } - Model\Profile::load($a, "", 0, $profiledata, true); - $o .= Model\Contact::getPostsFromUrl($contact["url"], true, $update); + Model\Profile::load($a, '', 0, $profiledata, true); + $o .= Model\Contact::getPostsFromUrl($contact['url'], true, $update); } return $o; @@ -962,18 +959,16 @@ class Contact extends BaseModule $o = self::getTabsHTML($a, $contact, 2); if (DBA::isResult($contact)) { - $a->page['aside'] = ""; + $a->page['aside'] = ''; - $profiledata = Model\Contact::getDetailsByURL($contact["url"]); + $profiledata = Model\Contact::getDetailsByURL($contact['url']); - if (local_user()) { - if (in_array($profiledata["network"], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { - $profiledata["remoteconnect"] = System::baseUrl()."/follow?url=".urlencode($profiledata["url"]); - } + if (local_user() && in_array($profiledata['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS])) { + $profiledata['remoteconnect'] = System::baseUrl() . '/follow?url=' . urlencode($profiledata['url']); } - Model\Profile::load($a, "", 0, $profiledata, true); - $o .= Model\Contact::getPostsFromUrl($contact["url"]); + Model\Profile::load($a, '', 0, $profiledata, true); + $o .= Model\Contact::getPostsFromUrl($contact['url']); } return $o; @@ -1021,20 +1016,20 @@ class Contact extends BaseModule return [ 'img_hover' => L10n::t('Visit %s\'s profile [%s]', $rr['name'], $rr['url']), - 'edit_hover' => L10n::t('Edit contact'), - 'photo_menu' => Model\Contact::photoMenu($rr), - 'id' => $rr['id'], - 'alt_text' => $alt_text, - 'dir_icon' => $dir_icon, - 'thumb' => ProxyUtils::proxifyUrl($rr['thumb'], false, ProxyUtils::SIZE_THUMB), - 'name' => htmlentities($rr['name']), - 'username' => htmlentities($rr['name']), + 'edit_hover'=> L10n::t('Edit contact'), + 'photo_menu'=> Model\Contact::photoMenu($rr), + 'id' => $rr['id'], + 'alt_text' => $alt_text, + 'dir_icon' => $dir_icon, + 'thumb' => ProxyUtils::proxifyUrl($rr['thumb'], false, ProxyUtils::SIZE_THUMB), + 'name' => htmlentities($rr['name']), + 'username' => htmlentities($rr['name']), 'account_type' => Model\Contact::getAccountType($rr), - 'sparkle' => $sparkle, + 'sparkle' => $sparkle, 'itemurl' => defaults($rr, 'addr', $rr['url']), - 'url' => $url, - 'network' => ContactSelector::networkToName($rr['network'], $rr['url']), - 'nick' => htmlentities($rr['nick']), + 'url' => $url, + 'network' => ContactSelector::networkToName($rr['network'], $rr['url']), + 'nick' => htmlentities($rr['nick']), ]; } From ea8b159df476ac6048d9e1152aa2a6490fca3aa3 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Sun, 14 Oct 2018 23:09:11 -0400 Subject: [PATCH 395/428] Fix wrong use statement in mod/update_contacts --- mod/update_contacts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mod/update_contacts.php b/mod/update_contacts.php index 6123d03045..1144ed1427 100644 --- a/mod/update_contacts.php +++ b/mod/update_contacts.php @@ -5,7 +5,7 @@ use Friendica\App; use Friendica\Core\L10n; use Friendica\Core\PConfig; -use Friendica\Module\Contacts; +use Friendica\Module\Contact; function update_contacts_content(App $a) { From e2762e032ceb0cd42d411b1e7832d576fb511f40 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 15 Oct 2018 05:19:35 +0000 Subject: [PATCH 396/428] Poddibility to defer worker execution --- boot.php | 2 +- config/dbstructure.json | 6 +++-- src/Core/Worker.php | 49 +++++++++++++++++++++++++++++++++++------ 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/boot.php b/boot.php index eda4ed1e8d..f40edaf907 100644 --- 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', 1285); +define('DB_UPDATE_VERSION', 1286); define('NEW_UPDATE_ROUTINE_VERSION', 1170); /** diff --git a/config/dbstructure.json b/config/dbstructure.json index 443f9bd755..8ea5aaa4bf 100644 --- a/config/dbstructure.json +++ b/config/dbstructure.json @@ -1298,14 +1298,16 @@ "created": {"type": "datetime", "not null": "1", "default": "0001-01-01 00:00:00", "comment": "Creation date"}, "pid": {"type": "int unsigned", "not null": "1", "default": "0", "comment": "Process id of the worker"}, "executed": {"type": "datetime", "not null": "1", "default": "0001-01-01 00:00:00", "comment": "Execution date"}, + "next_try": {"type": "datetime", "not null": "1", "default": "0001-01-01 00:00:00", "comment": "Next retrial date"}, + "retrial": {"type": "tinyint", "not null": "1", "default": "0", "comment": "Retrial counter"}, "done": {"type": "boolean", "not null": "1", "default": "0", "comment": "Marked 1 when the task was done - will be deleted later"} }, "indexes": { "PRIMARY": ["id"], "pid": ["pid"], "parameter": ["parameter(64)"], - "priority_created": ["priority", "created"], - "done_executed": ["done", "executed"] + "priority_created_next_try": ["priority", "created", "next_try"], + "done_executed_next_try": ["done", "executed", "next_try"] } } } diff --git a/src/Core/Worker.php b/src/Core/Worker.php index bf7e9f3bc8..723cd809da 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -8,6 +8,7 @@ use Friendica\Database\DBA; use Friendica\Model\Process; use Friendica\Util\DateTimeFormat; use Friendica\Util\Network; +use Friendica\BaseObject; require_once 'include/dba.php'; @@ -152,7 +153,8 @@ class Worker */ private static function totalEntries() { - return DBA::count('workerqueue', ["`executed` <= ? AND NOT `done`", NULL_DATE]); + return DBA::count('workerqueue', ["`executed` <= ? AND NOT `done` AND `next_try` < ?", + NULL_DATE, DateTimeFormat::utcNow()]); } /** @@ -162,7 +164,7 @@ class Worker */ private static function highestPriority() { - $condition = ["`executed` <= ? AND NOT `done`", NULL_DATE]; + $condition = ["`executed` <= ? AND NOT `done` AND `next_try` < ?", NULL_DATE, DateTimeFormat::utcNow()]; $workerqueue = DBA::selectFirst('workerqueue', ['priority'], $condition, ['order' => ['priority']]); if (DBA::isResult($workerqueue)) { return $workerqueue["priority"]; @@ -180,7 +182,8 @@ class Worker */ private static function processWithPriorityActive($priority) { - $condition = ["`priority` <= ? AND `executed` > ? AND NOT `done`", $priority, NULL_DATE]; + $condition = ["`priority` <= ? AND `executed` > ? AND NOT `done` AND `next_try` < ?", + $priority, NULL_DATE, DateTimeFormat::utcNow()]; return DBA::exists('workerqueue', $condition); } @@ -240,7 +243,7 @@ class Worker self::execFunction($queue, $include, $argv, true); $stamp = (float)microtime(true); - if (DBA::update('workerqueue', ['done' => true], ['id' => $queue["id"]])) { + if (DBA::update('workerqueue', ['done' => true], ['id' => $queue['id']])) { Config::set('system', 'last_worker_execution', DateTimeFormat::utcNow()); } self::$db_duration = (microtime(true) - $stamp); @@ -805,7 +808,8 @@ class Worker $result = DBA::select( 'workerqueue', ['id'], - ["`executed` <= ? AND `priority` < ? AND NOT `done`", NULL_DATE, $highest_priority], + ["`executed` <= ? AND `priority` < ? AND NOT `done` AND `next_try` < ?", + NULL_DATE, $highest_priority, DateTimeFormat::utcNow()], ['limit' => $limit, 'order' => ['priority', 'created']] ); @@ -821,7 +825,8 @@ class Worker $result = DBA::select( 'workerqueue', ['id'], - ["`executed` <= ? AND `priority` > ? AND NOT `done`", NULL_DATE, $highest_priority], + ["`executed` <= ? AND `priority` > ? AND NOT `done` AND `next_try` < ?", + NULL_DATE, $highest_priority, DateTimeFormat::utcNow()], ['limit' => $limit, 'order' => ['priority', 'created']] ); @@ -840,7 +845,8 @@ class Worker $result = DBA::select( 'workerqueue', ['id'], - ["`executed` <= ? AND NOT `done`", NULL_DATE], + ["`executed` <= ? AND NOT `done` AND `next_try` < ?", + NULL_DATE, DateTimeFormat::utcNow()], ['limit' => $limit, 'order' => ['priority', 'created']] ); @@ -1116,6 +1122,35 @@ class Worker return true; } + /** + * Defers the current worker entry + */ + public static function defer() + { + if (empty(BaseObject::getApp()->queue)) { + return; + } + + $queue = BaseObject::getApp()->queue; + + $retrial = $queue['retrial']; + $id = $queue['id']; + + if ($retrial > 14) { + logger('Id ' . $id . ' had been tried 14 times, it will be deleted now.', LOGGER_DEBUG); + DBA::delete('workerqueue', ['id' => $id]); + } + + // Calculate the delay until the next trial + $delay = (($retrial + 3) ** 4) + (rand(1, 30) * ($retrial + 1)); + $next = DateTimeFormat::utc('now + ' . $delay . ' seconds'); + + logger('Defer execution ' . $retrial . ' of id ' . $id . ' to ' . $next, LOGGER_DEBUG); + + $fields = ['retrial' => $retrial + 1, 'next_try' => $next, 'executed' => NULL_DATE, 'pid' => 0]; + DBA::update('workerqueue', $fields, ['id' => $id]); + } + /** * Log active processes into the "process" table * From c2c2f25d9224dee090d92a883d2b9c72fe813068 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Mon, 15 Oct 2018 10:36:27 +0200 Subject: [PATCH 397/428] added links to alternative ways to install Friendica to the docs --- INSTALL.txt | 7 +++++++ doc/Install.md | 8 ++++++++ doc/de/Install.md | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/INSTALL.txt b/INSTALL.txt index 705eb8fed2..fe733eefe7 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -56,6 +56,13 @@ you wish to communicate with the Diaspora network. - For alternative server configurations (such as Nginx server and MariaDB database engine), refer to the wiki at https://github.com/friendica/friendica/wiki +This guide will walk you through the manual installation process of Friendica. +If this is nothing for you, you might be interested in + +* the Friendica Docker image (https://github.com/friendica/docker) or +* how install Friendica with YunoHost] https://github.com/YunoHost-Apps/friendica_ynh). + + 2. Unpack the Friendica files into the root of your web server document area. - If you copy the directory tree to your webserver, make sure diff --git a/doc/Install.md b/doc/Install.md index 427299c3ea..e6d1d40645 100644 --- a/doc/Install.md +++ b/doc/Install.md @@ -40,6 +40,14 @@ Requirements Installation procedure --- +### Alternative Installation Methods + +This guide will walk you through the manual installation process of Friendica. +If this is nothing for you, you might be interested in + +* the [Friendica Docker image](https://github.com/friendica/docker) or +* how [install Friendica with YunoHost](https://github.com/YunoHost-Apps/friendica_ynh). + ### Get Friendica Unpack the Friendica files into the root of your web server document area. diff --git a/doc/de/Install.md b/doc/de/Install.md index 84d9a0d48e..132fbc1904 100644 --- a/doc/de/Install.md +++ b/doc/de/Install.md @@ -40,6 +40,14 @@ Requirements Installation --- +### Alternative Wege um Friendica zu Installieren + +Diese Anleitung wird dir Schritt-für-Schritt zeigen wie du Friendica auf deinem Server installieren kannst. +Falls du an automatischen Möglichkeiten interesse hast, wirf doch einen Blick auf + +* das [Docker image für Friendica](https://github.com/friendica/docker) oder +* die [Installation von Friendica auf YunoHost](https://github.com/YunoHost-Apps/friendica_ynh). + ### Friendica Entpacke die Friendica-Daten in das Quellverzeichnis (root) des Dokumentenbereichs deines Webservers. From 4496fdba2475540458e5878d6525bacf47487218 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Mon, 15 Oct 2018 13:44:09 +0200 Subject: [PATCH 398/428] use the right bracket --- INSTALL.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL.txt b/INSTALL.txt index fe733eefe7..ee98b8981d 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -60,7 +60,7 @@ This guide will walk you through the manual installation process of Friendica. If this is nothing for you, you might be interested in * the Friendica Docker image (https://github.com/friendica/docker) or -* how install Friendica with YunoHost] https://github.com/YunoHost-Apps/friendica_ynh). +* how install Friendica with YunoHos (https://github.com/YunoHost-Apps/friendica_ynh). 2. Unpack the Friendica files into the root of your web server document area. From 092125edb6812116d4a2f82d5a58afdd396a599b Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Mon, 15 Oct 2018 13:45:21 +0200 Subject: [PATCH 399/428] ypot --- INSTALL.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL.txt b/INSTALL.txt index ee98b8981d..2f0613fb7d 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -60,7 +60,7 @@ This guide will walk you through the manual installation process of Friendica. If this is nothing for you, you might be interested in * the Friendica Docker image (https://github.com/friendica/docker) or -* how install Friendica with YunoHos (https://github.com/YunoHost-Apps/friendica_ynh). +* how install Friendica with YunoHost (https://github.com/YunoHost-Apps/friendica_ynh). 2. Unpack the Friendica files into the root of your web server document area. From 9e1065ff87e22dcf38f97f203030bc7a73ae64ba Mon Sep 17 00:00:00 2001 From: Benjamin Lorteau Date: Mon, 15 Oct 2018 11:58:52 -0400 Subject: [PATCH 400/428] Improve transition from previous behavior - Simplify Model\User methods parameter list - Use DBA methods in mod/regmod - Replace killme with exit in mod/regmod - Simplify goaway() calls --- mod/register.php | 11 +++------ mod/regmod.php | 57 ++++++++++++++++++---------------------------- src/Model/User.php | 38 +++++++++++++++++++------------ 3 files changed, 48 insertions(+), 58 deletions(-) diff --git a/mod/register.php b/mod/register.php index 79e9455cd5..48fe67afc5 100644 --- a/mod/register.php +++ b/mod/register.php @@ -91,12 +91,10 @@ function register_post(App $a) // Only send a password mail when the password wasn't manually provided if (!x($_POST, 'password1') || !x($_POST, 'confirm')) { $res = Model\User::sendRegisterOpenEmail( - $user['email'], + $user, Config::get('config', 'sitename'), $a->getBaseUrl(), - $user['username'], - $result['password'], - $user + $result['password'] ); if ($res) { @@ -153,12 +151,9 @@ function register_post(App $a) } // send notification to the user, that the registration is pending Model\User::sendRegisterPendingEmail( - $user['uid'], - $user['email'], + $user, Config::get('config', 'sitename'), - $user['username'], $a->getBaseURL(), - $user['nickname'], $result['password'] ); diff --git a/mod/regmod.php b/mod/regmod.php index 433a8f5e4e..3f6f0e04e3 100644 --- a/mod/regmod.php +++ b/mod/regmod.php @@ -20,44 +20,34 @@ function user_allow($hash) $a = get_app(); $register = Register::getByHash($hash); - if (!DBA::isResult($register)) { return false; } - $user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", - intval($register['uid']) - ); - + $user = User::getById($register['uid']); if (!DBA::isResult($user)) { - killme(); + exit(); } Register::deleteByHash($hash); - $r = q("UPDATE `user` SET `blocked` = 0, `verified` = 1 WHERE `uid` = %d", - intval($register['uid']) - ); + DBA::update('user', ['blocked' => false, 'verified' => true], ['uid' => $register['uid']]); - $r = q("SELECT * FROM `profile` WHERE `uid` = %d AND `is-default` = 1", - intval($user[0]['uid']) - ); - if (DBA::isResult($r) && $r[0]['net-publish']) { - $url = System::baseUrl() . '/profile/' . $user[0]['nickname']; - if ($url && strlen(Config::get('system', 'directory'))) { - Worker::add(PRIORITY_LOW, "Directory", $url); - } + $profile = DBA::selectFirst('profile', ['net-publish'], ['uid' => $register['uid'], 'is-default' => true]); + + if (DBA::isResult($profile) && $profile['net-publish'] && Config::get('system', 'directory')) { + $url = System::baseUrl() . '/profile/' . $user['nickname']; + Worker::add(PRIORITY_LOW, "Directory", $url); } L10n::pushLang($register['language']); $res = User::sendRegisterOpenEmail( - $user[0]['email'], + $user, Config::get('config', 'sitename'), - System::baseUrl(), - $user[0]['username'], - 'Sent in a previous email', - $user[0]); + $a->getBaseUrl(), + defaults($register, 'password', 'Sent in a previous email') + ); L10n::popLang(); @@ -73,20 +63,20 @@ function user_allow($hash) function user_deny($hash) { $register = Register::getByHash($hash); - if (!DBA::isResult($register)) { return false; } - $user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", - intval($register['uid']) - ); + $user = User::getById($register['uid']); + if (!DBA::isResult($user)) { + exit(); + } DBA::delete('user', ['uid' => $register['uid']]); Register::deleteByHash($register['hash']); - notice(L10n::t('Registration revoked for %s', $user[0]['username']) . EOL); + notice(L10n::t('Registration revoked for %s', $user['username']) . EOL); return true; } @@ -94,17 +84,16 @@ function regmod_content(App $a) { if (!local_user()) { info(L10n::t('Please login.') . EOL); - $o = '

      ' . Login::form($a->query_string, intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED ? 0 : 1); - return $o; + return Login::form($a->query_string, intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED ? 0 : 1); } - if ((!is_site_admin()) || (x($_SESSION, 'submanage') && intval($_SESSION['submanage']))) { + if (!is_site_admin() || !empty($_SESSION['submanage'])) { notice(L10n::t('Permission denied.') . EOL); return ''; } if ($a->argc != 3) { - killme(); + exit(); } $cmd = $a->argv[1]; @@ -112,13 +101,11 @@ function regmod_content(App $a) if ($cmd === 'deny') { user_deny($hash); - goaway(System::baseUrl() . "/admin/users/"); - killme(); + goaway('admin/users/'); } if ($cmd === 'allow') { user_allow($hash); - goaway(System::baseUrl() . "/admin/users/"); - killme(); + goaway('admin/users/'); } } diff --git a/src/Model/User.php b/src/Model/User.php index 2888410c7f..eb042eb8b4 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -43,9 +43,18 @@ class User } /** - * @brief Returns the user id of a given profile url + * @param integer $uid + * @return array|boolean User record if it exists, false otherwise + */ + public static function getById($uid) + { + return DBA::selectFirst('user', [], ['uid' => $uid]); + } + + /** + * @brief Returns the user id of a given profile URL * - * @param string $profile + * @param string $url * * @return integer user id */ @@ -657,13 +666,13 @@ class User /** * @brief Sends pending registration confirmation email * - * @param string $email + * @param array $user User record array * @param string $sitename - * @param string $username + * @param string $siteurl * @param string $password Plaintext password * @return NULL|boolean from notification() and email() inherited */ - public static function sendRegisterPendingEmail($uid, $email, $sitename, $username, $siteurl, $nickname, $password) + public static function sendRegisterPendingEmail($user, $sitename, $siteurl, $password) { $body = deindent(L10n::t(' Dear %1$s, @@ -675,13 +684,13 @@ class User Login Name: %4$s Password: %5$s ', - $body, $username, $sitename, $siteurl, $nickname, $password + $body, $user['username'], $sitename, $siteurl, $user['nickname'], $password )); return notification([ 'type' => SYSTEM_EMAIL, - 'uid' => $uid, - 'to_email' => $email, + 'uid' => $user['uid'], + 'to_email' => $user['email'], 'subject' => L10n::t('Registration at %s', $sitename), 'body' => $body ]); @@ -692,20 +701,19 @@ class User * * It's here as a function because the mail is sent from different parts * - * @param string $email + * @param array $user User record array * @param string $sitename * @param string $siteurl - * @param string $username - * @param string $password + * @param string $password Plaintext password * @return NULL|boolean from notification() and email() inherited */ - public static function sendRegisterOpenEmail($email, $sitename, $siteurl, $username, $password, $user) + public static function sendRegisterOpenEmail($user, $sitename, $siteurl, $password) { $preamble = deindent(L10n::t(' Dear %1$s, Thank you for registering at %2$s. Your account has been created. ', - $preamble, $username, $sitename + $preamble, $user['username'], $sitename )); $body = deindent(L10n::t(' The login details are as follows: @@ -734,14 +742,14 @@ class User If you ever want to delete your account, you can do so at %3$s/removeme Thank you and welcome to %2$s.', - $body, $email, $sitename, $siteurl, $username, $password + $body, $user['email'], $sitename, $siteurl, $user['username'], $password )); return notification([ 'uid' => $user['uid'], 'language' => $user['language'], 'type' => SYSTEM_EMAIL, - 'to_email' => $email, + 'to_email' => $user['email'], 'subject' => L10n::t('Registration details for %s', $sitename), 'preamble' => $preamble, 'body' => $body From 8d0f4710a4e4646c9dcc99cf8b4c0c36650c8efd Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 15 Oct 2018 21:42:55 +0000 Subject: [PATCH 401/428] Signed Diaspora posts should now be stored more reliable --- boot.php | 2 +- config/dbstructure.json | 10 ++++++++++ database.sql | 17 ++++++++++++++--- src/Model/Item.php | 34 +++++++++++++++++++++++----------- src/Protocol/Diaspora.php | 26 +++++++++----------------- 5 files changed, 57 insertions(+), 32 deletions(-) diff --git a/boot.php b/boot.php index f40edaf907..ea1b273f2e 100644 --- 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', 1286); +define('DB_UPDATE_VERSION', 1287); define('NEW_UPDATE_ROUTINE_VERSION', 1170); /** diff --git a/config/dbstructure.json b/config/dbstructure.json index 8ea5aaa4bf..51cb3ce4f3 100644 --- a/config/dbstructure.json +++ b/config/dbstructure.json @@ -254,6 +254,16 @@ "received": ["received"] } }, + "diaspora-interaction": { + "comment": "Signed Diaspora Interaction", + "fields": { + "uri-id": {"type": "int unsigned", "not null": "1", "primary": "1", "relation": {"item-uri": "id"}, "comment": "Id of the item-uri table entry that contains the item uri"}, + "interaction": {"type": "mediumtext", "comment": "The Diaspora interaction"} + }, + "indexes": { + "PRIMARY": ["uri-id"] + } + }, "event": { "comment": "Events", "fields": { diff --git a/database.sql b/database.sql index 341ee5a858..2f67a341cc 100644 --- a/database.sql +++ b/database.sql @@ -1,6 +1,6 @@ -- ------------------------------------------ -- Friendica 2018.12-dev (The Tazmans Flax-lily) --- DB_UPDATE_VERSION 1285 +-- DB_UPDATE_VERSION 1287 -- ------------------------------------------ @@ -247,6 +247,15 @@ CREATE TABLE IF NOT EXISTS `conversation` ( INDEX `received` (`received`) ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Raw data and structure information for messages'; +-- +-- TABLE diaspora-interaction +-- +CREATE TABLE IF NOT EXISTS `diaspora-interaction` ( + `uri-id` int unsigned NOT NULL COMMENT 'Id of the item-uri table entry that contains the item uri', + `interaction` mediumtext COMMENT 'The Diaspora interaction', + PRIMARY KEY(`uri-id`) +) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Signed Diaspora Interaction'; + -- -- TABLE event -- @@ -1242,12 +1251,14 @@ CREATE TABLE IF NOT EXISTS `workerqueue` ( `created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Creation date', `pid` int unsigned NOT NULL DEFAULT 0 COMMENT 'Process id of the worker', `executed` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Execution date', + `next_try` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Next retrial date', + `retrial` tinyint NOT NULL DEFAULT 0 COMMENT 'Retrial counter', `done` boolean NOT NULL DEFAULT '0' COMMENT 'Marked 1 when the task was done - will be deleted later', PRIMARY KEY(`id`), INDEX `pid` (`pid`), INDEX `parameter` (`parameter`(64)), - INDEX `priority_created` (`priority`,`created`), - INDEX `done_executed` (`done`,`executed`) + INDEX `priority_created_next_try` (`priority`,`created`,`next_try`), + INDEX `done_executed_next_try` (`done`,`executed`,`next_try`) ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Background tasks queue entries'; diff --git a/src/Model/Item.php b/src/Model/Item.php index ed80f4e9e8..824e240cc3 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -231,6 +231,10 @@ class Item extends BaseObject } } + if (array_key_exists('signed_text', $row) && array_key_exists('interaction', $row) && !is_null($row['interaction'])) { + $row['signed_text'] = $row['interaction']; + } + if (array_key_exists('ignored', $row) && array_key_exists('internal-user-ignored', $row) && !is_null($row['internal-user-ignored'])) { $row['ignored'] = $row['internal-user-ignored']; } @@ -242,6 +246,7 @@ class Item extends BaseObject unset($row['internal-iaid']); unset($row['internal-icid']); unset($row['internal-user-ignored']); + unset($row['interaction']); return $row; } @@ -567,6 +572,8 @@ class Item extends BaseObject $fields['sign'] = ['signed_text', 'signature', 'signer']; + $fields['diaspora-interaction'] = ['interaction']; + return $fields; } @@ -653,6 +660,10 @@ class Item extends BaseObject $joins .= " LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id`"; } + if (strpos($sql_commands, "`diaspora-interaction`.") !== false) { + $joins .= " LEFT JOIN `diaspora-interaction` ON `diaspora-interaction`.`uri-id` = `item`.`uri-id`"; + } + if (strpos($sql_commands, "`item-activity`.") !== false) { $joins .= " LEFT JOIN `item-activity` ON `item-activity`.`id` = `item`.`iaid`"; } @@ -705,6 +716,10 @@ class Item extends BaseObject $selected[] = 'internal-user-ignored'; } + if (in_array('signed_text', $selected)) { + $selected[] = 'interaction'; + } + $selection = []; foreach ($fields as $table => $table_fields) { foreach ($table_fields as $field => $select) { @@ -1487,7 +1502,6 @@ 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']; @@ -1534,10 +1548,6 @@ 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 @@ -1578,7 +1588,6 @@ 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; @@ -1803,14 +1812,17 @@ class Item extends BaseObject logger("Repaired double encoded signature from handle ".$dsprsig->signer, LOGGER_DEBUG); } - DBA::insert('sign', ['iid' => $current_post, 'signed_text' => $dsprsig->signed_text, - 'signature' => $dsprsig->signature, 'signer' => $dsprsig->signer]); + if (!empty($dsprsig->signed_text) && empty($dsprsig->signature) && empty($dsprsig->signer)) { + DBA::insert('diaspora-interaction', ['uri-id' => $item['uri-id'], 'interaction' => $dsprsig->signed_text], true); + } else { + // The other fields are used by very old Friendica servers, so we currently store them differently + DBA::insert('sign', ['iid' => $current_post, 'signed_text' => $dsprsig->signed_text, + 'signature' => $dsprsig->signature, 'signer' => $dsprsig->signer]); + } } if (!empty($diaspora_signed_text)) { - // Formerly we stored the signed text, the signature and the author in different fields. - // We now store the raw data so that we are more flexible. - DBA::insert('sign', ['iid' => $current_post, 'signed_text' => $diaspora_signed_text]); + DBA::insert('diaspora-interaction', ['uri-id' => $item['uri-id'], 'interaction' => $diaspora_signed_text], true); } $deleted = self::tagDeliver($item['uid'], $current_post); diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index eb52c05037..00f4e1702d 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -3749,13 +3749,13 @@ class Diaspora * * @return string The message */ - private static function messageFromSignature(array $item, array $signature) + private static function messageFromSignature(array $item) { // Split the signed text - $signed_parts = explode(";", $signature['signed_text']); + $signed_parts = explode(";", $item['signed_text']); if ($item["deleted"]) { - $message = ["author" => $signature['signer'], + $message = ["author" => $item['signer'], "target_guid" => $signed_parts[0], "target_type" => $signed_parts[1]]; } elseif (in_array($item["verb"], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) { @@ -3764,7 +3764,7 @@ class Diaspora "parent_guid" => $signed_parts[3], "parent_type" => $signed_parts[2], "positive" => $signed_parts[0], - "author_signature" => $signature['signature'], + "author_signature" => $item['signature'], "parent_author_signature" => ""]; } else { // Remove the comment guid @@ -3783,7 +3783,7 @@ class Diaspora "guid" => $guid, "parent_guid" => $parent_guid, "text" => implode(";", $signed_parts), - "author_signature" => $signature['signature'], + "author_signature" => $item['signature'], "parent_author_signature" => ""]; } return $message; @@ -3811,20 +3811,12 @@ class Diaspora logger("Got relayable data ".$type." for item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG); - // fetch the original signature - $fields = ['signed_text', 'signature', 'signer']; - $signature = DBA::selectFirst('sign', $fields, ['iid' => $item["id"]]); - if (!DBA::isResult($signature)) { - logger("Couldn't fetch signatur for item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG); - return false; - } - // Old way - is used by the internal Friendica functions /// @todo Change all signatur storing functions to the new format - if ($signature['signed_text'] && $signature['signature'] && $signature['signer']) { - $message = self::messageFromSignature($item, $signature); + if ($item['signed_text'] && $item['signature'] && $item['signer']) { + $message = self::messageFromSignature($item); } else {// New way - $msg = json_decode($signature['signed_text'], true); + $msg = json_decode($item['signed_text'], true); $message = []; if (is_array($msg)) { @@ -3841,7 +3833,7 @@ class Diaspora $message[$field] = $data; } } else { - logger("Signature text for item ".$item["guid"]." (".$item["id"].") couldn't be extracted: ".$signature['signed_text'], LOGGER_DEBUG); + logger("Signature text for item ".$item["guid"]." (".$item["id"].") couldn't be extracted: ".$item['signed_text'], LOGGER_DEBUG); } } From d71327e311120cff52b4db9baf498ac7c3239635 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Mon, 15 Oct 2018 18:35:36 -0400 Subject: [PATCH 402/428] Fix namespace usage in mod/group --- mod/group.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mod/group.php b/mod/group.php index 5bc188e50d..f8fefc78f9 100644 --- a/mod/group.php +++ b/mod/group.php @@ -16,7 +16,7 @@ use Friendica\Module; function group_init(App $a) { if (local_user()) { - $a->page['aside'] = Group::sidebarWidget('contacts', 'group', 'extended', (($a->argc > 1) ? $a->argv[1] : 'everyone')); + $a->page['aside'] = Model\Group::sidebarWidget('contacts', 'group', 'extended', (($a->argc > 1) ? $a->argv[1] : 'everyone')); } } @@ -31,10 +31,10 @@ function group_post(App $a) { check_form_security_token_redirectOnErr('/group/new', 'group_edit'); $name = notags(trim($_POST['groupname'])); - $r = Group::create(local_user(), $name); + $r = Model\Group::create(local_user(), $name); if ($r) { info(L10n::t('Group created.') . EOL); - $r = Group::getIdByName(local_user(), $name); + $r = Model\Group::getIdByName(local_user(), $name); if ($r) { goaway(System::baseUrl() . '/group/' . $r); } @@ -71,7 +71,7 @@ function group_post(App $a) { } } - $a->page['aside'] = Group::sidebarWidget(); + $a->page['aside'] = Model\Group::sidebarWidget(); } return; } @@ -148,7 +148,7 @@ function group_content(App $a) { $result = null; if (DBA::isResult($r)) { - $result = Group::removeByName(local_user(), $r[0]['name']); + $result = Model\Group::removeByName(local_user(), $r[0]['name']); } if ($result) { @@ -198,9 +198,9 @@ function group_content(App $a) { if ($change) { if (in_array($change, $preselected)) { - Group::removeMember($group['id'], $change); + Model\Group::removeMember($group['id'], $change); } else { - Group::addMember($group['id'], $change); + Model\Group::addMember($group['id'], $change); } $members = Model\Contact::getByGroupId($group['id']); @@ -261,7 +261,7 @@ function group_content(App $a) { $groupeditor['members'][] = $entry; } else { - Group::removeMember($group['id'], $member['id']); + Model\Group::removeMember($group['id'], $member['id']); } } From 0de1351a0976d4672e1023216e3474aadbbee324 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Mon, 15 Oct 2018 23:12:29 -0400 Subject: [PATCH 403/428] Fix notices in Network\Probe --- src/Network/Probe.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 2c42643b44..23b97a5cd0 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -953,13 +953,13 @@ class Probe $prof_data["addr"] = $data["addr"]; $prof_data["nick"] = $data["nick"]; - $prof_data["dfrn-request"] = $data["request"]; - $prof_data["dfrn-confirm"] = $data["confirm"]; - $prof_data["dfrn-notify"] = $data["notify"]; - $prof_data["dfrn-poll"] = $data["poll"]; - $prof_data["photo"] = $data["photo"]; - $prof_data["fn"] = $data["name"]; - $prof_data["key"] = $data["pubkey"]; + $prof_data["dfrn-request"] = defaults($data, 'request', null); + $prof_data["dfrn-confirm"] = defaults($data, 'confirm', null); + $prof_data["dfrn-notify"] = defaults($data, 'notify' , null); + $prof_data["dfrn-poll"] = defaults($data, 'poll' , null); + $prof_data["photo"] = defaults($data, 'photo' , null); + $prof_data["fn"] = defaults($data, 'name' , null); + $prof_data["key"] = defaults($data, 'pubkey' , null); logger("Result for profile ".$profile_link.": ".print_r($prof_data, true), LOGGER_DEBUG); From 481b0ac138511825f3736342b40dd9b3a2e2a8d5 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Mon, 15 Oct 2018 23:13:00 -0400 Subject: [PATCH 404/428] Fix notices in include/enotify --- include/enotify.php | 6 +++--- src/Database/DBStructure.php | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/enotify.php b/include/enotify.php index b184a6935e..d8e5614c17 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -42,9 +42,9 @@ function notification($params) } $params['notify_flags'] = defaults($params, 'notify_flags', $user['notify-flags']); - $params['language'] = defaults($params, 'language', $user['language']); - $params['to_name'] = defaults($params, 'to_name', $user['username']); - $params['to_email'] = defaults($params, 'to_email', $user['email']); + $params['language'] = defaults($params, 'language' , $user['language']); + $params['to_name'] = defaults($params, 'to_name' , $user['username']); + $params['to_email'] = defaults($params, 'to_email' , $user['email']); // from here on everything is in the recipients language L10n::pushLang($params['language']); diff --git a/src/Database/DBStructure.php b/src/Database/DBStructure.php index 0472d753dd..f8fc1651c1 100644 --- a/src/Database/DBStructure.php +++ b/src/Database/DBStructure.php @@ -83,10 +83,11 @@ class DBStructure $body = sprintf($body, $error_message); notification([ - 'type' => SYSTEM_EMAIL, + 'uid' => $admin['uid'], + 'type' => SYSTEM_EMAIL, 'to_email' => $admin['email'], 'preamble' => $preamble, - 'body' => $body, + 'body' => $body, 'language' => $lang] ); } From 012fe3c11ed8e6c291e39108addf85a9cc58d3cc Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 16 Oct 2018 06:32:12 +0000 Subject: [PATCH 405/428] Avoid endless loop at magic auth --- src/Model/Profile.php | 85 ++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 41 deletions(-) diff --git a/src/Model/Profile.php b/src/Model/Profile.php index 28736750bd..e44ac29519 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -1010,56 +1010,59 @@ class Profile $my_url = self::getMyURL(); $my_url = Network::isUrlValid($my_url); - if ($my_url) { - if (!local_user()) { - // Is it a DDoS attempt? - // The check fetches the cached value from gprobe to reduce the load for this system - $urlparts = parse_url($my_url); + if (empty($my_url) || local_user()) { + return; + } - $result = Cache::get('gprobe:' . $urlparts['host']); - if ((!is_null($result)) && (in_array($result['network'], [Protocol::FEED, Protocol::PHANTOM]))) { - logger('DDoS attempt detected for ' . $urlparts['host'] . ' by ' . $_SERVER['REMOTE_ADDR'] . '. server data: ' . print_r($_SERVER, true), LOGGER_DEBUG); - return; - } + // Avoid endless loops + $cachekey = 'zrlInit:' . $my_url; + if (Cache::get($cachekey)) { + logger('URL ' . $my_url . ' already tried to authenticate.', LOGGER_DEBUG); + return; + } else { + Cache::set($cachekey, true, CACHE_MINUTE); + } - Worker::add(PRIORITY_LOW, 'GProbe', $my_url); - $arr = ['zrl' => $my_url, 'url' => $a->cmd]; - Addon::callHooks('zrl_init', $arr); + $arr = ['zrl' => $my_url, 'url' => $a->cmd]; + Addon::callHooks('zrl_init', $arr); - // Try to find the public contact entry of the visitor. - $cid = Contact::getIdForURL($my_url); - if (!$cid) { - logger('No contact record found for ' . $my_url, LOGGER_DEBUG); - return; - } + // Try to find the public contact entry of the visitor. + $cid = Contact::getIdForURL($my_url); + if (!$cid) { + logger('No contact record found for ' . $my_url, LOGGER_DEBUG); + return; + } - $contact = DBA::selectFirst('contact',['id', 'url'], ['id' => $cid]); + Worker::add(PRIORITY_LOW, 'GProbe', $my_url); - if (DBA::isResult($contact) && remote_user() && remote_user() == $contact['id']) { - // The visitor is already authenticated. - return; - } + $contact = DBA::selectFirst('contact',['id', 'url'], ['id' => $cid]); - logger('Not authenticated. Invoking reverse magic-auth for ' . $my_url, LOGGER_DEBUG); + if (DBA::isResult($contact) && remote_user() && remote_user() == $contact['id']) { + logger('The visitor ' . $my_url . ' is already authenticated', LOGGER_DEBUG); + return; + } - // Try to avoid recursion - but send them home to do a proper magic auth. - $query = str_replace(array('?zrl=', '&zid='), array('?rzrl=', '&rzrl='), $a->query_string); - // The other instance needs to know where to redirect. - $dest = urlencode(System::baseUrl() . '/' . $query); + logger('Not authenticated. Invoking reverse magic-auth for ' . $my_url, LOGGER_DEBUG); - // We need to extract the basebath from the profile url - // to redirect the visitors '/magic' module. - // Note: We should have the basepath of a contact also in the contact table. - $urlarr = explode('/profile/', $contact['url']); - $basepath = $urlarr[0]; + // Try to avoid recursion - but send them home to do a proper magic auth. + $query = str_replace(array('?zrl=', '&zid='), array('?rzrl=', '&rzrl='), $a->query_string); + // The other instance needs to know where to redirect. + $dest = urlencode(System::baseUrl() . '/' . $query); - 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 ($serverret->isSuccess()) { - goaway($magic_path); - } - } + // We need to extract the basebath from the profile url + // to redirect the visitors '/magic' module. + // Note: We should have the basepath of a contact also in the contact table. + $urlarr = explode('/profile/', $contact['url']); + $basepath = $urlarr[0]; + + if ($basepath != System::baseUrl() && !strstr($dest, '/magic') && !strstr($dest, '/rmagic')) { + $magic_path = $basepath . '/magic' . '?f=&owa=1&dest=' . $dest; + + // We have to check if the remote server does understand /magic without invoking something + $serverret = Network::curl($basepath . '/magic'); + if ($serverret->isSuccess()) { + logger('Doing magic auth for visitor ' . $my_url . ' to ' . $magic_path, LOGGER_DEBUG); + goaway($magic_path); } } } From 35a73b729f4dea95e8a0a40ba672b89f0eadd603 Mon Sep 17 00:00:00 2001 From: Michael Date: Tue, 16 Oct 2018 13:17:01 +0000 Subject: [PATCH 406/428] Onepoll hadn't polled anymore / small relocation in zrlinit for better logging --- src/Model/Profile.php | 22 +++++++++++----------- src/Worker/OnePoll.php | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Model/Profile.php b/src/Model/Profile.php index e44ac29519..1f0773cd18 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -1014,15 +1014,6 @@ class Profile return; } - // Avoid endless loops - $cachekey = 'zrlInit:' . $my_url; - if (Cache::get($cachekey)) { - logger('URL ' . $my_url . ' already tried to authenticate.', LOGGER_DEBUG); - return; - } else { - Cache::set($cachekey, true, CACHE_MINUTE); - } - $arr = ['zrl' => $my_url, 'url' => $a->cmd]; Addon::callHooks('zrl_init', $arr); @@ -1033,8 +1024,6 @@ class Profile return; } - Worker::add(PRIORITY_LOW, 'GProbe', $my_url); - $contact = DBA::selectFirst('contact',['id', 'url'], ['id' => $cid]); if (DBA::isResult($contact) && remote_user() && remote_user() == $contact['id']) { @@ -1042,8 +1031,19 @@ class Profile return; } + // Avoid endless loops + $cachekey = 'zrlInit:' . $my_url; + if (Cache::get($cachekey)) { + logger('URL ' . $my_url . ' already tried to authenticate.', LOGGER_DEBUG); + return; + } else { + Cache::set($cachekey, true, CACHE_MINUTE); + } + logger('Not authenticated. Invoking reverse magic-auth for ' . $my_url, LOGGER_DEBUG); + Worker::add(PRIORITY_LOW, 'GProbe', $my_url); + // Try to avoid recursion - but send them home to do a proper magic auth. $query = str_replace(array('?zrl=', '&zid='), array('?rzrl=', '&rzrl='), $a->query_string); // The other instance needs to know where to redirect. diff --git a/src/Worker/OnePoll.php b/src/Worker/OnePoll.php index 3c16af75f8..0066a04aed 100644 --- a/src/Worker/OnePoll.php +++ b/src/Worker/OnePoll.php @@ -333,7 +333,7 @@ class OnePoll $curlResult = Network::curl($contact['poll'], false, $redirects, ['cookiejar' => $cookiejar]); unlink($cookiejar); - if (!$curlResult->isTimeout()) { + 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); From be2e6c39298121872debf8b21e25169981ebdb06 Mon Sep 17 00:00:00 2001 From: Jonny Tischbein Date: Tue, 16 Oct 2018 19:14:55 +0200 Subject: [PATCH 407/428] Fix Issue #5896 by setting static return for edit_post to display item page (kind of revert parts of #5774) --- mod/editpost.php | 10 ++-------- src/Object/Post.php | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/mod/editpost.php b/mod/editpost.php index d6493b3c0c..780145ed3f 100644 --- a/mod/editpost.php +++ b/mod/editpost.php @@ -21,20 +21,14 @@ function editpost_content(App $a) } $post_id = (($a->argc > 1) ? intval($a->argv[1]) : 0); - $return_url = (($a->argc > 2) ? base64_decode($a->argv[2]) : ''); if (!$post_id) { notice(L10n::t('Item not found') . EOL); return; } - // Fallback to SESSION return_path - if (empty($return_url)) { - $return_url = $_SESSION['return_url']; - } - $fields = ['allow_cid', 'allow_gid', 'deny_cid', 'deny_gid', - 'type', 'body', 'title', 'file', 'wall', 'post-type']; + 'type', 'body', 'title', 'file', 'wall', 'post-type', 'guid']; $item = Item::selectFirstForUser(local_user(), $fields, ['id' => $post_id, 'uid' => local_user()]); @@ -92,7 +86,7 @@ function editpost_content(App $a) $o .= replace_macros($tpl, [ '$is_edit' => true, - '$return_path' => $return_url, + '$return_path' => '/display/' . $item['guid'], '$action' => 'item', '$share' => L10n::t('Save'), '$upload' => L10n::t('Upload photo'), diff --git a/src/Object/Post.php b/src/Object/Post.php index 48ffe65b74..34a5f8138a 100644 --- a/src/Object/Post.php +++ b/src/Object/Post.php @@ -157,7 +157,7 @@ class Post extends BaseObject if ($item["event-id"] != 0) { $edpost = ["events/event/" . $item['event-id'], L10n::t("Edit")]; } else { - $edpost = ["editpost/" . $item['id'] . "/" . base64_encode($a->cmd), L10n::t("Edit")]; + $edpost = ["editpost/" . $item['id'], L10n::t("Edit")]; } $dropping = in_array($item['uid'], [0, local_user()]); } else { From e9c9eb9c66f4053f95fc4fa6936c00bf4ce4e312 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 16 Oct 2018 18:26:43 -0400 Subject: [PATCH 408/428] Fix notice in Worker\Delivery --- src/Worker/Delivery.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Worker/Delivery.php b/src/Worker/Delivery.php index f2951cce1f..1c353fb632 100644 --- a/src/Worker/Delivery.php +++ b/src/Worker/Delivery.php @@ -39,13 +39,13 @@ class Delivery extends BaseObject $followup = false; $public_message = false; + $items = []; if ($cmd == self::MAIL) { $target_item = DBA::selectFirst('mail', [], ['id' => $item_id]); if (!DBA::isResult($target_item)) { return; } $uid = $target_item['uid']; - $items = []; } elseif ($cmd == self::SUGGESTION) { $target_item = DBA::selectFirst('fsuggest', [], ['id' => $item_id]); if (!DBA::isResult($target_item)) { @@ -65,7 +65,6 @@ class Delivery extends BaseObject $params = ['order' => ['id']]; $itemdata = Item::select([], $condition, $params); - $items = []; while ($item = Item::fetch($itemdata)) { if ($item['id'] == $parent_id) { $parent = $item; From c4318fe05e491a45fa8d8c2eacf4541a64588e9c Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 16 Oct 2018 18:27:13 -0400 Subject: [PATCH 409/428] Fix notices in Parse URL feature --- mod/parse_url.php | 1 + src/Util/ParseUrl.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/mod/parse_url.php b/mod/parse_url.php index 40eddc3bdd..a14379e709 100644 --- a/mod/parse_url.php +++ b/mod/parse_url.php @@ -73,6 +73,7 @@ function parse_url_content(App $a) $hdrs[$k] = $v; } } + $type = null; if (array_key_exists('Content-Type', $hdrs)) { $type = $hdrs['Content-Type']; } diff --git a/src/Util/ParseUrl.php b/src/Util/ParseUrl.php index f2a5eccd39..24089b9cbd 100644 --- a/src/Util/ParseUrl.php +++ b/src/Util/ParseUrl.php @@ -141,7 +141,7 @@ class ParseUrl } // If the file is too large then exit - if ($curlResult->getInfo()['download_content_length'] > 1000000) { + if (defaults($curlResult->getInfo(), 'download_content_length', 0) > 1000000) { return $siteinfo; } From 2b1d15de8733313aeb5af92ad3e3d0a782c8607e Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 16 Oct 2018 18:28:27 -0400 Subject: [PATCH 410/428] Fix undefined index: id in Protocol\Diaspora --- src/Protocol/Diaspora.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 00f4e1702d..71280a20de 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -949,6 +949,7 @@ class Diaspora $person = DBA::selectFirst('fcontact', [], ['network' => Protocol::DIASPORA, 'addr' => $handle]); if (!DBA::isResult($person)) { $person = $r; + $person['id'] = 0; } } } From cb854b8b105a23d3453275257d872da001b390cc Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 16 Oct 2018 18:29:08 -0400 Subject: [PATCH 411/428] Fix Undefined index: timezone in Protocol\Diaspora --- src/Protocol/Diaspora.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index 71280a20de..0c3a52b2d3 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -3430,12 +3430,9 @@ class Diaspora /// @todo - establish "all day" events in Friendica $eventdata["all_day"] = "false"; - if (!$event['adjust']) { + $eventdata['timezone'] = 'UTC'; + if (!$event['adjust'] && $user['timezone']) { $eventdata['timezone'] = $user['timezone']; - - if ($eventdata['timezone'] == "") { - $eventdata['timezone'] = 'UTC'; - } } if ($event['start']) { From 341b83d1dfb4dd04a4635e64fb4dc54ed98acee9 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 16 Oct 2018 18:29:28 -0400 Subject: [PATCH 412/428] Fix Undefined index: photo in ActivityPub/Receiver --- src/Protocol/ActivityPub/Receiver.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 04da5fa596..a5ba0763db 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -461,7 +461,7 @@ class Receiver logger('Switch contact ' . $cid . ' (' . $profile['url'] . ') for user ' . $uid . ' to ActivityPub'); - $photo = $profile['photo']; + $photo = defaults($profile, 'photo', null); unset($profile['photo']); unset($profile['baseurl']); @@ -478,7 +478,7 @@ class Receiver } /** - * + * * * @param $receivers * @param $actor @@ -503,12 +503,12 @@ class Receiver } /** - * + * * * @param $object_data * @param array $activity * - * @return + * @return */ private static function addActivityFields($object_data, $activity) { From c50be325bd105d4088010f52e4da45bfcdf7b139 Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Tue, 16 Oct 2018 18:30:24 -0400 Subject: [PATCH 413/428] Remove unused parameter $selected in Model\Item::fieldlist --- src/Model/Item.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Model/Item.php b/src/Model/Item.php index 824e240cc3..4275c18251 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -380,7 +380,7 @@ class Item extends BaseObject $usermode = true; } - $fields = self::fieldlist($selected, $usermode); + $fields = self::fieldlist($usermode); $select_fields = self::constructSelectFields($fields, $selected); @@ -487,7 +487,7 @@ class Item extends BaseObject $usermode = true; } - $fields = self::fieldlist($selected, $usermode); + $fields = self::fieldlist($usermode); $fields['thread'] = ['mention', 'ignored', 'iid']; @@ -523,7 +523,7 @@ class Item extends BaseObject * * @return array field list */ - private static function fieldlist($selected, $usermode) + private static function fieldlist($usermode) { $fields = []; From b5fb81f535b7daba255bc3a9750c89b9adcc5abe Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Wed, 17 Oct 2018 01:10:07 -0400 Subject: [PATCH 414/428] Add Mastodon/Pleroma protocol guessing --- src/Core/Protocol.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Core/Protocol.php b/src/Core/Protocol.php index d41250a686..949e2350c3 100644 --- a/src/Core/Protocol.php +++ b/src/Core/Protocol.php @@ -108,6 +108,13 @@ class Protocol } } + // Mastodon, Pleroma + if (preg_match('=https?://(.+?)/users/(.+)=ism', $profile_url, $matches) + || preg_match('=https?://(.+?)/@(.+)=ism', $profile_url, $matches) + ) { + return self::ACTIVITYPUB; + } + // pumpio (http://host.name/user) if (preg_match('=https?://([\.\w]+)/([\.\w]+)$=ism', $profile_url, $matches)) { return self::PUMPIO; From 45748da8a1d0580e5f1cd81c34ec3b807ed8ea3b Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Wed, 17 Oct 2018 01:11:50 -0400 Subject: [PATCH 415/428] Remove network exception in handle_tag --- mod/item.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mod/item.php b/mod/item.php index 053a00c977..4d798ac1e5 100644 --- a/mod/item.php +++ b/mod/item.php @@ -1015,11 +1015,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n $profile = $contact["url"]; $alias = $contact["alias"]; - $newname = $contact["nick"]; - - if (($newname == "") || !in_array($contact["network"], [Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::TWITTER, Protocol::STATUSNET])) { - $newname = $contact["name"]; - } + $newname = defaults($contact, "name", $contact["nick"]); } //if there is an url for this persons profile From 9239ecc5e0207eb5e62bea36f6ee200e4581932c Mon Sep 17 00:00:00 2001 From: Hypolite Petovan Date: Wed, 17 Oct 2018 01:13:18 -0400 Subject: [PATCH 416/428] Rework BBCode::convertShare to accept a callback function - Create default convertShare callback from previous code - Remove $simplehtml = 8 case (moved to Twitter addon) --- src/Content/Text/BBCode.php | 243 ++++++++++++++---------------------- 1 file changed, 97 insertions(+), 146 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index c903ee6945..f4872e7b37 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -859,187 +859,136 @@ class BBCode extends BaseObject } /** - * Processes [share] tags + * This function converts a [share] block to text according to a provided callback function whose signature is: + * + * function(array $attributes, array $author_contact, string $content): string + * + * Where: + * - $attributes is an array of attributes of the [share] block itself. Missing keys will be completed by the contact + * data lookup + * - $author_contact is a contact record array + * - $content is the inner content of the [share] block + * - Return value is the string that should replace the [share] block in the provided text + * + * This function is intended to be used by addon connector to format a share block like the target network is expecting it. + * + * @param string $text A BBCode string + * @param callable $callback + * @return string The BBCode string with all [share] blocks replaced + */ + public static function convertShare($text, callable $callback) + { + $return = preg_replace_callback( + "/\[share(.*?)\](.*?)\[\/share\]/ism", + function ($match) use ($callback) { + $attribute_string = $match[1]; + + $attributes = []; + foreach(['author', 'profile', 'avatar', 'link', 'posted'] as $field) { + preg_match("/$field=(['\"])(.+?)\\1/ism", $attribute_string, $matches); + $attributes[$field] = html_entity_decode(defaults($matches, 2, ''), ENT_QUOTES, 'UTF-8'); + } + + // We only call this so that a previously unknown contact can be added. + // This is important for the function "Model\Contact::getDetailsByURL()". + // This function then can fetch an entry from the contact table. + Contact::getIdForURL($attributes['profile'], 0, true); + + $author_contact = Contact::getDetailsByURL($attributes['profile']); + $author_contact['addr'] = defaults($author_contact, 'addr' , Protocol::getAddrFromProfileUrl($attributes['profile'])); + + $attributes['author'] = defaults($author_contact, 'name' , $attributes['author']); + $attributes['avatar'] = defaults($author_contact, 'micro', $attributes['avatar']); + $attributes['profile'] = defaults($author_contact, 'url' , $attributes['profile']); + + if ($attributes['avatar']) { + $attributes['avatar'] = ProxyUtils::proxifyUrl($attributes['avatar'], false, ProxyUtils::SIZE_THUMB); + } + + return $callback($attributes, $author_contact, $match[2]); + }, + $text + ); + + return $return; + } + + /** + * Default [share] tag conversion callback * * Note: Can produce a [bookmark] tag in the output * - * @brief Processes [share] tags - * @param array $share preg_match_callback result array - * @param bool|int $simplehtml + * @see BBCode::convertShare() + * @param array $attributes [share] block attribute values + * @param array $author_contact Contact row of the shared author + * @param string $content Inner content of the [share] block + * @param integer $simplehtml Mysterious integer value depending on the target network/formatting style * @return string */ - private static function convertShare($share, $simplehtml) + private static function convertShareCallback(array $attributes, array $author_contact, $content, $simplehtml) { - $attributes = $share[2]; - - $author = ""; - preg_match("/author='(.*?)'/ism", $attributes, $matches); - if (x($matches, 1)) { - $author = html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8'); - } - - preg_match('/author="(.*?)"/ism', $attributes, $matches); - if (x($matches, 1)) { - $author = $matches[1]; - } - - $profile = ""; - preg_match("/profile='(.*?)'/ism", $attributes, $matches); - if (x($matches, 1)) { - $profile = $matches[1]; - } - - preg_match('/profile="(.*?)"/ism', $attributes, $matches); - if (x($matches, 1)) { - $profile = $matches[1]; - } - - $avatar = ""; - preg_match("/avatar='(.*?)'/ism", $attributes, $matches); - if (x($matches, 1)) { - $avatar = $matches[1]; - } - - preg_match('/avatar="(.*?)"/ism', $attributes, $matches); - if (x($matches, 1)) { - $avatar = $matches[1]; - } - - $link = ""; - preg_match("/link='(.*?)'/ism", $attributes, $matches); - if (x($matches, 1)) { - $link = $matches[1]; - } - - preg_match('/link="(.*?)"/ism', $attributes, $matches); - if (x($matches, 1)) { - $link = $matches[1]; - } - - $posted = ""; - - preg_match("/posted='(.*?)'/ism", $attributes, $matches); - if (x($matches, 1)) { - $posted = $matches[1]; - } - - preg_match('/posted="(.*?)"/ism', $attributes, $matches); - if (x($matches, 1)) { - $posted = $matches[1]; - } - - // We only call this so that a previously unknown contact can be added. - // This is important for the function "Model\Contact::getDetailsByURL()". - // This function then can fetch an entry from the contact table. - Contact::getIdForURL($profile, 0, true); - - $data = Contact::getDetailsByURL($profile); - - if (x($data, "name") && x($data, "addr")) { - $userid_compact = $data["name"] . " (" . $data["addr"] . ")"; - } else { - $userid_compact = Protocol::getAddrFromProfileUrl($profile, $author); - } - - if (x($data, "addr")) { - $userid = $data["addr"]; - } else { - $userid = Protocol::formatMention($profile, $author); - } - - if (x($data, "name")) { - $author = $data["name"]; - } - - if (x($data, "micro")) { - $avatar = $data["micro"]; - } - - $preshare = trim($share[1]); - if ($preshare != "") { - $preshare .= "
      "; - } + $mention = Protocol::formatMention($attributes['profile'], $attributes['author']); switch ($simplehtml) { case 1: - $text = $preshare . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . ' ' . $userid . ":
      »" . $share[3] . "«"; + $text = '

      ' . html_entity_decode('♲ ', ENT_QUOTES, 'UTF-8') . ' ' . $mention . ':

      ' . "\n" . '«' . $content . '»'; break; case 2: - $text = $preshare . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . ' ' . $userid_compact . ":
      " . $share[3]; + $text = '

      ' . html_entity_decode('♲ ', ENT_QUOTES, 'UTF-8') . ' ' . $author_contact['addr'] . ':

      ' . "\n" . $content; break; case 3: // Diaspora - $headline = '' . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . $userid . ':
      '; + $headline = '

      ' . html_entity_decode('♲ ', ENT_QUOTES, 'UTF-8') . $mention . ':

      ' . "\n"; - $text = trim($share[1]); - - if ($text != "") { - $text .= "
      "; - } - - if (stripos(normalise_link($link), 'http://twitter.com/') === 0) { - $text .= '
      ' . $link . ''; + if (stripos(normalise_link($attributes['link']), 'http://twitter.com/') === 0) { + $text = '

      ' . $attributes['link'] . '

      ' . "\n"; } else { - $text .= $headline . '
      ' . trim($share[3]) . "

      "; + $text = $headline . '
      ' . trim($content) . '
      ' . "\n"; - if ($link != "") { - $text .= '
      [l]'; + if ($attributes['link'] != '') { + $text .= '

      [l]

      ' . "\n"; } } break; case 4: - $headline = '
      ' . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8'); - $headline .= L10n::t('%2$s %3$s', $link, $userid, $posted); - $headline .= ":
      "; + $headline = '

      ' . html_entity_decode('♲ ', ENT_QUOTES, 'UTF-8'); + $headline .= L10n::t('%2$s %3$s', $attributes['link'], $mention, $attributes['posted']); + $headline .= ':

      ' . "\n"; - $text = trim($share[1]); - - if ($text != "") { - $text .= "
      "; - } - - $text .= $headline . '
      ' . trim($share[3]) . "

      "; + $text = $headline . '
      ' . trim($content) . '
      ' . "\n"; break; case 5: - $text = $preshare . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . ' ' . $userid_compact . ":
      " . $share[3]; + $text = '

      ' . html_entity_decode('♲ ', ENT_QUOTES, 'UTF-8') . ' ' . $author_contact['addr'] . ':

      ' . "\n" . $content; break; case 7: // statusnet/GNU Social - $text = $preshare . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . " @" . $userid_compact . ": " . $share[3]; - break; - case 8: // twitter - $text = $preshare . "RT @" . $userid_compact . ": " . $share[3]; + $text = '

      ' . html_entity_decode('♲ ', ENT_QUOTES, 'UTF-8') . ' @' . $author_contact['addr'] . ': ' . $content . '

      ' . "\n"; break; case 9: // Google+ - $text = $preshare . html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8') . ' ' . $userid_compact . ":
      " . $share[3]; + $text = '

      ' . html_entity_decode('♲ ', ENT_QUOTES, 'UTF-8') . ' ' . $author_contact['addr'] . ':

      ' . "\n"; + $text .= '

      ' . $content . '

      ' . "\n"; - if ($link != "") { - $text .= "

      " . $link; + if ($attributes['link'] != '') { + $text .= '

      ' . $attributes['link'] . '

      '; } break; default: // Transforms quoted tweets in rich attachments to avoid nested tweets - if (stripos(normalise_link($link), 'http://twitter.com/') === 0 && OEmbed::isAllowedURL($link)) { + if (stripos(normalise_link($attributes['link']), 'http://twitter.com/') === 0 && OEmbed::isAllowedURL($attributes['link'])) { try { - $oembed = OEmbed::getHTML($link, $preshare); + $text = OEmbed::getHTML($attributes['link']); } catch (Exception $e) { - $oembed = sprintf('[bookmark=%s]%s[/bookmark]', $link, $preshare); + $text = sprintf('[bookmark=%s]%s[/bookmark]', $attributes['link'], $content); } - - $text = $preshare . $oembed; } else { - $text = trim($share[1]) . "\n"; - - $avatar = ProxyUtils::proxifyUrl($avatar, false, ProxyUtils::SIZE_THUMB); - $tpl = get_markup_template('shared_content.tpl'); - $text .= replace_macros($tpl, [ - '$profile' => $profile, - '$avatar' => $avatar, - '$author' => $author, - '$link' => $link, - '$posted' => $posted, - '$content' => trim($share[3]) + $text = replace_macros($tpl, [ + '$profile' => $attributes['profile'], + '$avatar' => $attributes['avatar'], + '$author' => $attributes['author'], + '$link' => $attributes['link'], + '$posted' => $attributes['posted'], + '$content' => trim($content) ]); } break; @@ -1621,10 +1570,12 @@ class BBCode extends BaseObject $text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/ism", '' . L10n::t('Image/photo') . '', $text); // Shared content - $text = preg_replace_callback("/(.*?)\[share(.*?)\](.*?)\[\/share\]/ism", - function ($match) use ($simple_html) { - return self::convertShare($match, $simple_html); - }, $text); + $text = self::convertShare( + $text, + function (array $attributes, array $author_contact, string $content) use ($simple_html) { + return self::convertShareCallback($attributes, $author_contact, $content, $simple_html); + } + ); $text = preg_replace("/\[crypt\](.*?)\[\/crypt\]/ism", '
      ' . L10n::t('Encrypted content') . '
      ', $text); $text = preg_replace("/\[crypt(.*?)\](.*?)\[\/crypt\]/ism", '
      ' . L10n::t('Encrypted content') . '
      ', $text); From 2db8c7d64f8f4016382d1b6bd9f08680473b7af6 Mon Sep 17 00:00:00 2001 From: Adam Magness Date: Wed, 17 Oct 2018 07:25:23 -0400 Subject: [PATCH 417/428] Fix template urls from contacts/ to contact/ Update templates to match recent contact/ changes. --- view/templates/contact_edit.tpl | 2 +- view/theme/frio/templates/contact_edit.tpl | 2 +- view/theme/vier/templates/contact_edit.tpl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/view/templates/contact_edit.tpl b/view/templates/contact_edit.tpl index 344ee296a2..b4c34f74e2 100644 --- a/view/templates/contact_edit.tpl +++ b/view/templates/contact_edit.tpl @@ -5,7 +5,7 @@
      - +