From fe52719d374fc0dc7155835c930de338095b258e Mon Sep 17 00:00:00 2001 From: very-ape Date: Thu, 20 May 2021 13:47:12 -0700 Subject: [PATCH 001/311] Fix Message button. --- src/Model/Profile.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Model/Profile.php b/src/Model/Profile.php index 3e35d60c29..ff08977498 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -145,7 +145,7 @@ class Profile */ public static function load(App $a, $nickname, array $profiledata = [], $show_connect = true) { - $user = DBA::selectFirst('user', ['uid'], ['nickname' => $nickname, 'account_removed' => false]); + $user = DBA::selectFirst('user', [], ['nickname' => $nickname, 'account_removed' => false]); if (!DBA::isResult($user) && empty($profiledata)) { Logger::log('profile error: ' . DI::args()->getQueryString(), Logger::DEBUG); @@ -166,7 +166,16 @@ class Profile } } - $profile = !empty($user['uid']) ? User::getOwnerDataById($user['uid'], false) : []; + if (empty($user['uid'])) { + $profile = []; + } else { + $profile = array_merge( + $user, + Profile::getByUID($user['uid']), + Contact::getById(Contact::getIdForURL(Strings::normaliseLink(DI::baseurl() . '/profile/' . $nickname), local_user())) + ); + $profile['cid'] = $profile['id']; + } if (empty($profile) && empty($profiledata)) { Logger::log('profile error: ' . DI::args()->getQueryString(), Logger::DEBUG); @@ -334,7 +343,7 @@ class Profile if (Contact::canReceivePrivateMessages($profile)) { if ($visitor_is_followed || $visitor_is_following) { - $wallmessage_link = $visitor_base_path . '/message/new/' . base64_encode($profile['addr'] ?? ''); + $wallmessage_link = $visitor_base_path . '/message/new/' . $profile['cid']; } elseif ($visitor_is_authenticated && !empty($profile['unkmail'])) { $wallmessage_link = 'wallmessage/' . $profile['nickname']; } From 8bf80c92bdb7aee58671504aab9018c3adb70a29 Mon Sep 17 00:00:00 2001 From: Tobias Diekershoff Date: Fri, 21 May 2021 18:38:54 +0200 Subject: [PATCH 002/311] version 2021.06-rc --- VERSION | 2 +- boot.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION b/VERSION index e9cd37efec..79ec0dc3af 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2021.06-dev +2021.06-rc diff --git a/boot.php b/boot.php index bbb66c2f9a..aa3739f010 100644 --- a/boot.php +++ b/boot.php @@ -38,7 +38,7 @@ use Friendica\Util\DateTimeFormat; define('FRIENDICA_PLATFORM', 'Friendica'); define('FRIENDICA_CODENAME', 'Siberian Iris'); -define('FRIENDICA_VERSION', '2021.06-dev'); +define('FRIENDICA_VERSION', '2021.06-rc'); define('DFRN_PROTOCOL_VERSION', '2.23'); define('NEW_TABLE_STRUCTURE_VERSION', 1288); From 93926e99b89524a9f4ce7e52a7a583960e178505 Mon Sep 17 00:00:00 2001 From: very-ape Date: Fri, 21 May 2021 10:15:32 -0700 Subject: [PATCH 003/311] Use getByNickname as suggested in code review. --- src/Model/Profile.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Profile.php b/src/Model/Profile.php index ff08977498..7454929943 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -145,7 +145,7 @@ class Profile */ public static function load(App $a, $nickname, array $profiledata = [], $show_connect = true) { - $user = DBA::selectFirst('user', [], ['nickname' => $nickname, 'account_removed' => false]); + $user = User::getByNickname($nickname); if (!DBA::isResult($user) && empty($profiledata)) { Logger::log('profile error: ' . DI::args()->getQueryString(), Logger::DEBUG); From bcb2073c9a8f6b94d88f507ae76b9db4d2a90eab Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 21 May 2021 17:36:51 +0000 Subject: [PATCH 004/311] New class to process HTTP input data --- .../Mastodon/Accounts/UpdateCredentials.php | 8 +- src/Util/HTTPInputData.php | 260 ++++++++++++++++++ 2 files changed, 265 insertions(+), 3 deletions(-) create mode 100644 src/Util/HTTPInputData.php diff --git a/src/Module/Api/Mastodon/Accounts/UpdateCredentials.php b/src/Module/Api/Mastodon/Accounts/UpdateCredentials.php index d3f4c15fe0..b2a23cf424 100644 --- a/src/Module/Api/Mastodon/Accounts/UpdateCredentials.php +++ b/src/Module/Api/Mastodon/Accounts/UpdateCredentials.php @@ -21,8 +21,9 @@ namespace Friendica\Module\Api\Mastodon\Accounts; +use Friendica\Core\Logger; use Friendica\Module\BaseApi; -use Friendica\Util\Network; +use Friendica\Util\HTTPInputData; /** * @see https://docs.joinmastodon.org/methods/accounts/ @@ -34,9 +35,10 @@ class UpdateCredentials extends BaseApi self::login(self::SCOPE_WRITE); $uid = self::getCurrentUserID(); - $data = Network::postdata(); + $data = HTTPInputData::process(); + + Logger::info('Patch data', ['data' => $data]); - // @todo Parse the raw data that is in the "multipart/form-data" format self::unsupported('patch'); } } diff --git a/src/Util/HTTPInputData.php b/src/Util/HTTPInputData.php new file mode 100644 index 0000000000..e3b48cf58d --- /dev/null +++ b/src/Util/HTTPInputData.php @@ -0,0 +1,260 @@ +. + * + */ + +namespace Friendica\Util; + +/** + * Derived from the work of Reid Johnson + * @see https://codereview.stackexchange.com/questions/69882/parsing-multipart-form-data-in-php-for-put-requests + */ +class HTTPInputData +{ + public static function process() + { + $content_parts = explode(';', $_SERVER['CONTENT_TYPE'] ?? 'application/x-www-form-urlencoded'); + + $boundary = ''; + $encoding = ''; + + $content_type = array_shift($content_parts); + + foreach ($content_parts as $part) { + if (strpos($part, 'boundary') !== false) { + $part = explode('=', $part, 2); + if (!empty($part[1])) { + $boundary = '--' . $part[1]; + } + } elseif (strpos($part, 'charset') !== false) { + $part = explode('=', $part, 2); + if (!empty($part[1])) { + $encoding = $part[1]; + } + } + if ($boundary !== '' && $encoding !== '') { + break; + } + } + + if ($content_type == 'multipart/form-data') { + return self::fetchFromMultipart($boundary); + } + + // can be handled by built in PHP functionality + $content = file_get_contents('php://input'); + + $variables = json_decode($content); + + if (empty($variables)) { + parse_str($content, $variables); + } + + return ['variables' => $variables, 'files' => []]; + } + + private static function fetchFromMultipart(string $boundary) + { + $result = ['variables' => [], 'files' => []]; + + $stream = fopen('php://input', 'rb'); + + $sanity = fgets($stream, strlen($boundary) + 5); + + // malformed file, boundary should be first item + if (rtrim($sanity) !== $boundary) { + return $result; + } + + $raw_headers = ''; + + while (($chunk = fgets($stream)) !== false) { + if ($chunk === $boundary) { + continue; + } + + if (!empty(trim($chunk))) { + $raw_headers .= $chunk; + continue; + } + + $result = self::parseRawHeader($stream, $raw_headers, $boundary, $result); + $raw_headers = ''; + } + + fclose($stream); + + return $result; + } + + private static function parseRawHeader($stream, string $raw_headers, string $boundary, array $result) + { + $variables = $result['variables']; + $files = $result['files']; + + $headers = []; + + foreach (explode("\r\n", $raw_headers) as $header) { + if (strpos($header, ':') === false) { + continue; + } + list($name, $value) = explode(':', $header, 2); + $headers[strtolower($name)] = ltrim($value, ' '); + } + + if (!isset($headers['content-disposition'])) { + return ['variables' => $variables, 'files' => $files]; + } + + if (!preg_match('/^(.+); *name="([^"]+)"(; *filename="([^"]+)")?/', $headers['content-disposition'], $matches)) { + return ['variables' => $variables, 'files' => $files]; + } + + $name = $matches[2]; + $filename = $matches[4] ?? ''; + + if (!empty($filename)) { + $files[$name] = self::fetchFileData($stream, $boundary, $headers, $filename); + return ['variables' => $variables, 'files' => $files]; + } else { + $variables = self::fetchVariables($stream, $boundary, $name, $variables); + } + + return ['variables' => $variables, 'files' => $files]; + } + + private static function fetchFileData($stream, string $boundary, array $headers, string $filename) + { + $error = UPLOAD_ERR_OK; + + if (isset($headers['content-type'])) { + $tmp = explode(';', $headers['content-type']); + $contentType = $tmp[0]; + } else { + $contentType = 'unknown'; + } + + $tmpnam = tempnam(ini_get('upload_tmp_dir'), 'php'); + $fileHandle = fopen($tmpnam, 'wb'); + + if ($fileHandle === false) { + $error = UPLOAD_ERR_CANT_WRITE; + } else { + $lastLine = NULL; + while (($chunk = fgets($stream, 8096)) !== false && strpos($chunk, $boundary) !== 0) { + if ($lastLine !== NULL) { + if (fwrite($fileHandle, $lastLine) === false) { + $error = UPLOAD_ERR_CANT_WRITE; + break; + } + } + $lastLine = $chunk; + } + + if ($lastLine !== NULL && $error !== UPLOAD_ERR_CANT_WRITE) { + if (fwrite($fileHandle, rtrim($lastLine, "\r\n")) === false) { + $error = UPLOAD_ERR_CANT_WRITE; + } + } + } + + return [ + 'name' => $filename, + 'type' => $contentType, + 'tmp_name' => $tmpnam, + 'error' => $error, + 'size' => filesize($tmpnam) + ]; + } + + private static function fetchVariables($stream, string $boundary, string $name, array $variables) + { + $fullValue = ''; + $lastLine = NULL; + + while (($chunk = fgets($stream)) !== false && strpos($chunk, $boundary) !== 0) { + if ($lastLine !== NULL) { + $fullValue .= $lastLine; + } + + $lastLine = $chunk; + } + + if ($lastLine !== NULL) { + $fullValue .= rtrim($lastLine, "\r\n"); + } + + if (isset($headers['content-type'])) { + $encoding = ''; + + foreach (explode(';', $headers['content-type']) as $part) { + if (strpos($part, 'charset') !== false) { + $part = explode($part, '=', 2); + if (isset($part[1])) { + $encoding = $part[1]; + } + break; + } + } + + if ($encoding !== '' && strtoupper($encoding) !== 'UTF-8' && strtoupper($encoding) !== 'UTF8') { + $tmp = mb_convert_encoding($fullValue, 'UTF-8', $encoding); + if ($tmp !== false) { + $fullValue = $tmp; + } + } + } + + $fullValue = $name . '=' . $fullValue; + + $tmp = []; + parse_str($fullValue, $tmp); + + return self::expandVariables(explode('[', $name), $variables, $tmp); + } + + private static function expandVariables(array $names, $variables, array $values) + { + if (!is_array($variables)) { + return $values; + } + + $name = rtrim(array_shift($names), ']'); + if ($name !== '') { + $name = $name . '=p'; + + $tmp = []; + parse_str($name, $tmp); + + $tmp = array_keys($tmp); + $name = reset($tmp); + } + + if ($name === '') { + $variables[] = reset($values); + } elseif (isset($variables[$name]) && isset($values[$name])) { + $variables[$name] = self::expandVariables($names, $variables[$name], $values[$name]); + } elseif (isset($values[$name])) { + $variables[$name] = $values[$name]; + } + + return $variables; + } +} +?> From 52c62f8d1d6096f36b3be3c5d623d98fa4e0666d Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 21 May 2021 17:49:25 +0000 Subject: [PATCH 005/311] New section for dummy endpoints --- doc/API-Mastodon.md | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/doc/API-Mastodon.md b/doc/API-Mastodon.md index a734bd5445..5610f926fb 100644 --- a/doc/API-Mastodon.md +++ b/doc/API-Mastodon.md @@ -119,17 +119,29 @@ These endpoints use the [Mastodon API entities](https://docs.joinmastodon.org/en ## Currently unimplemented endpoints -These emdpoints are planned to be implemented +These emdpoints are planned to be implemented somewhere in the future. - [`PATCH /api/v1/accounts/update_credentials`](https://docs.joinmastodon.org/methods/accounts/) - [`GET /api/v1/instance/activity`](https://docs.joinmastodon.org/methods/instance#weekly-activity) +## Dummy endpoints + +These endpoints are returning empty data to avoid error messages with (for example) mobile clients. +They belong to a functionality that doesn't exist in Friendica yet. + +- [`GET /api/v1/accounts/:id/identity_proofs`](https://docs.joinmastodon.org/methods/accounts/) +- [`GET /api/v1/announcements`](https://docs.joinmastodon.org/methods/announcements/) +- [`GET /api/v1/endorsements`](https://docs.joinmastodon.org/methods/accounts/endorsements/) +- [`GET /api/v1/filters`](https://docs.joinmastodon.org/methods/accounts/filters/) +- [`GET /api/v1/markers`](https://docs.joinmastodon.org/methods/timelines/markers/) +- [`GET /api/v1/scheduled_statuses`](https://docs.joinmastodon.org/methods/statuses/scheduled_statuses/) + ## Non supportable endpoints -These endpoints won't be implemented, since they refer to functionality that doesn't exist in Friendica +These endpoints won't be implemented at the moment. +They belong to a functionality that doesn't exist in Friendica yet. - [`POST /api/v1/accounts`](https://docs.joinmastodon.org/methods/accounts/) -- [`GET /api/v1/accounts/:id/identity_proofs`](https://docs.joinmastodon.org/methods/accounts/) - [`POST /api/v1/accounts/:id/pin`](https://docs.joinmastodon.org/methods/accounts/) - [`POST /api/v1/accounts/:id/unpin`](https://docs.joinmastodon.org/methods/accounts/) - [`GET /api/v1/admin/accounts`](https://docs.joinmastodon.org/methods/admin/) @@ -138,29 +150,24 @@ These endpoints won't be implemented, since they refer to functionality that doe - [`GET /api/v1/admin/reports`](https://docs.joinmastodon.org/methods/admin/) - [`GET /api/v1/admin/reports/:id`](https://docs.joinmastodon.org/methods/admin/) - [`POST /api/v1/admin/reports/:id/{action}`](https://docs.joinmastodon.org/methods/admin/) -- [`GET /api/v1/announcements`](https://docs.joinmastodon.org/methods/announcements/) - [`POST /api/v1/announcements/:id/dismiss`](https://docs.joinmastodon.org/methods/announcements/) - [`PUT /api/v1/announcements/:id/reactions/{name}`](https://docs.joinmastodon.org/methods/announcements/) - [`DELETE /api/v1/announcements/:id/reactions/{name}`](https://docs.joinmastodon.org/methods/announcements/) - [`GET /api/v1/domain_blocks`](https://docs.joinmastodon.org/methods/accounts/domain_blocks/) - [`POST /api/v1/domain_blocks`](https://docs.joinmastodon.org/methods/accounts/domain_blocks/) - [`DELETE /api/v1/domain_blocks`](https://docs.joinmastodon.org/methods/accounts/domain_blocks/) -- [`GET /api/v1/endorsements`](https://docs.joinmastodon.org/methods/accounts/endorsements/) - [`GET /api/v1/featured_tags`](https://docs.joinmastodon.org/methods/accounts/featured_tags/) - [`POST /api/v1/featured_tags`](https://docs.joinmastodon.org/methods/accounts/featured_tags/) - [`DELETE /api/v1/featured_tags/:id`](https://docs.joinmastodon.org/methods/accounts/featured_tags/) - [`GET /api/v1/featured_tags/suggestions`](https://docs.joinmastodon.org/methods/accounts/featured_tags/) -- [`GET /api/v1/filters`](https://docs.joinmastodon.org/methods/accounts/filters/) - [`GET /api/v1/filters/:id`](https://docs.joinmastodon.org/methods/accounts/filters/) - [`POST /api/v1/filters/:id`](https://docs.joinmastodon.org/methods/accounts/filters/) - [`PUT /api/v1/filters/:id`](https://docs.joinmastodon.org/methods/accounts/filters/) - [`DELETE /api/v1/filters/:id`](https://docs.joinmastodon.org/methods/accounts/filters/) -- [`GET /api/v1/markers`](https://docs.joinmastodon.org/methods/timelines/markers/) - [`POST /api/v1/markers`](https://docs.joinmastodon.org/methods/timelines/markers/) - [`GET /api/v1/polls/:id`](https://docs.joinmastodon.org/methods/statuses/polls/) - [`POST /api/v1/polls/:id/votes`](https://docs.joinmastodon.org/methods/statuses/polls/) - [`POST /api/v1/reports`](https://docs.joinmastodon.org/methods/accounts/reports/) -- [`GET /api/v1/scheduled_statuses`](https://docs.joinmastodon.org/methods/statuses/scheduled_statuses/) - [`GET /api/v1/scheduled_statuses/:id`](https://docs.joinmastodon.org/methods/statuses/scheduled_statuses/) - [`PUT /api/v1/scheduled_statuses/:id`](https://docs.joinmastodon.org/methods/statuses/scheduled_statuses/) - [`DELETE /api/v1/scheduled_statuses/:id`](https://docs.joinmastodon.org/methods/statuses/scheduled_statuses/) From 081652e09a3613bc3545b93f0f5df3e7e107327e Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 21 May 2021 18:00:03 +0000 Subject: [PATCH 006/311] Wrong class path --- .../Api/Mastodon/{Conversation.php => Conversations.php} | 2 +- src/Module/Api/Mastodon/Conversations/Read.php | 2 +- static/routes.config.php | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/Module/Api/Mastodon/{Conversation.php => Conversations.php} (98%) diff --git a/src/Module/Api/Mastodon/Conversation.php b/src/Module/Api/Mastodon/Conversations.php similarity index 98% rename from src/Module/Api/Mastodon/Conversation.php rename to src/Module/Api/Mastodon/Conversations.php index e87818ac27..3b4496a012 100644 --- a/src/Module/Api/Mastodon/Conversation.php +++ b/src/Module/Api/Mastodon/Conversations.php @@ -29,7 +29,7 @@ use Friendica\Module\BaseApi; /** * @see https://docs.joinmastodon.org/methods/timelines/conversations/ */ -class Conversation extends BaseApi +class Conversations extends BaseApi { public static function delete(array $parameters = []) { diff --git a/src/Module/Api/Mastodon/Conversations/Read.php b/src/Module/Api/Mastodon/Conversations/Read.php index d1c349eaac..955ca5c96f 100644 --- a/src/Module/Api/Mastodon/Conversations/Read.php +++ b/src/Module/Api/Mastodon/Conversations/Read.php @@ -19,7 +19,7 @@ * */ -namespace Friendica\Module\Api\Mastodon\Conversation; +namespace Friendica\Module\Api\Mastodon\Conversations; use Friendica\Core\System; use Friendica\Database\DBA; diff --git a/static/routes.config.php b/static/routes.config.php index 80b1aadeb8..4569038a41 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -90,9 +90,9 @@ return [ '/apps/verify_credentials' => [Module\Api\Mastodon\Apps\VerifyCredentials::class, [R::GET ]], '/blocks' => [Module\Api\Mastodon\Blocks::class, [R::GET ]], '/bookmarks' => [Module\Api\Mastodon\Bookmarks::class, [R::GET ]], - '/conversations' => [Module\Api\Mastodon\Conversation::class, [R::GET ]], - '/conversations/{id:\d+}' => [Module\Api\Mastodon\Conversation::class, [R::DELETE ]], - '/conversations/{id:\d+}/read' => [Module\Api\Mastodon\Conversation\Read::class, [R::POST ]], + '/conversations' => [Module\Api\Mastodon\Conversations::class, [R::GET ]], + '/conversations/{id:\d+}' => [Module\Api\Mastodon\Conversations::class, [R::DELETE ]], + '/conversations/{id:\d+}/read' => [Module\Api\Mastodon\Conversations\Read::class, [R::POST ]], '/custom_emojis' => [Module\Api\Mastodon\CustomEmojis::class, [R::GET ]], '/domain_blocks' => [Module\Api\Mastodon\Unimplemented::class, [R::GET, R::POST, R::DELETE]], // not supported '/directory' => [Module\Api\Mastodon\Directory::class, [R::GET ]], From 9330fe1440945f11fc8e0fce9b1c5c867b1aa996 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 21 May 2021 18:18:39 +0000 Subject: [PATCH 007/311] Updated messages.po --- view/lang/C/messages.po | 148 ++++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 74 deletions(-) diff --git a/view/lang/C/messages.po b/view/lang/C/messages.po index 2234a8c16c..ac5bf2bf9a 100644 --- a/view/lang/C/messages.po +++ b/view/lang/C/messages.po @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: 2021.06-dev\n" +"Project-Id-Version: 2021.06-rc\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-05-16 07:41+0000\n" +"POT-Creation-Date: 2021-05-21 18:18+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -39,8 +39,8 @@ msgstr "" #: include/api.php:4528 mod/photos.php:107 mod/photos.php:211 #: mod/photos.php:639 mod/photos.php:1043 mod/photos.php:1060 -#: mod/photos.php:1609 src/Model/User.php:1045 src/Model/User.php:1053 -#: src/Model/User.php:1061 src/Module/Settings/Profile/Photo/Crop.php:97 +#: mod/photos.php:1609 src/Model/User.php:1100 src/Model/User.php:1108 +#: src/Model/User.php:1116 src/Module/Settings/Profile/Photo/Crop.php:97 #: src/Module/Settings/Profile/Photo/Crop.php:113 #: src/Module/Settings/Profile/Photo/Crop.php:129 #: src/Module/Settings/Profile/Photo/Crop.php:178 @@ -54,7 +54,7 @@ msgstr "" msgid "%1$s poked %2$s" msgstr "" -#: include/conversation.php:227 src/Model/Item.php:2523 +#: include/conversation.php:227 src/Model/Item.php:2534 msgid "event" msgstr "" @@ -62,7 +62,7 @@ msgstr "" msgid "status" msgstr "" -#: include/conversation.php:235 mod/tagger.php:90 src/Model/Item.php:2525 +#: include/conversation.php:235 mod/tagger.php:90 src/Model/Item.php:2536 msgid "photo" msgstr "" @@ -951,7 +951,7 @@ msgstr "" msgid "list" msgstr "" -#: mod/cal.php:297 src/Console/User.php:182 src/Model/User.php:607 +#: mod/cal.php:297 src/Console/User.php:182 src/Model/User.php:662 #: src/Module/Admin/Users/Active.php:73 src/Module/Admin/Users/Blocked.php:74 #: src/Module/Admin/Users/Index.php:80 src/Module/Admin/Users/Pending.php:71 #: src/Module/Api/Twitter/ContactEndpoint.php:73 @@ -2966,7 +2966,7 @@ msgstr "" msgid "File upload failed." msgstr "" -#: mod/wall_upload.php:233 +#: mod/wall_upload.php:233 src/Model/Photo.php:953 msgid "Wall Photos" msgstr "" @@ -3636,39 +3636,39 @@ msgstr "" msgid "last" msgstr "" -#: src/Content/Text/BBCode.php:942 src/Content/Text/BBCode.php:1605 -#: src/Content/Text/BBCode.php:1606 +#: src/Content/Text/BBCode.php:942 src/Content/Text/BBCode.php:1607 +#: src/Content/Text/BBCode.php:1608 msgid "Image/photo" msgstr "" -#: src/Content/Text/BBCode.php:1064 +#: src/Content/Text/BBCode.php:1066 #, php-format msgid "" "%2$s %3$s" msgstr "" -#: src/Content/Text/BBCode.php:1089 src/Model/Item.php:3024 -#: src/Model/Item.php:3030 src/Model/Item.php:3031 +#: src/Content/Text/BBCode.php:1091 src/Model/Item.php:3035 +#: src/Model/Item.php:3041 src/Model/Item.php:3042 msgid "Link to source" msgstr "" -#: src/Content/Text/BBCode.php:1523 src/Content/Text/HTML.php:951 +#: src/Content/Text/BBCode.php:1525 src/Content/Text/HTML.php:951 msgid "Click to open/close" msgstr "" -#: src/Content/Text/BBCode.php:1554 +#: src/Content/Text/BBCode.php:1556 msgid "$1 wrote:" msgstr "" -#: src/Content/Text/BBCode.php:1608 src/Content/Text/BBCode.php:1609 +#: src/Content/Text/BBCode.php:1610 src/Content/Text/BBCode.php:1611 msgid "Encrypted content" msgstr "" -#: src/Content/Text/BBCode.php:1822 +#: src/Content/Text/BBCode.php:1824 msgid "Invalid source protocol" msgstr "" -#: src/Content/Text/BBCode.php:1837 +#: src/Content/Text/BBCode.php:1839 msgid "Invalid link protocol" msgstr "" @@ -4542,25 +4542,25 @@ msgstr "" msgid "%s: updating %s table." msgstr "" -#: src/Factory/Api/Mastodon/Error.php:32 +#: src/Factory/Api/Mastodon/Error.php:38 msgid "Record not found" msgstr "" -#: src/Factory/Api/Mastodon/Error.php:41 +#: src/Factory/Api/Mastodon/Error.php:48 msgid "Unprocessable Entity" msgstr "" -#: src/Factory/Api/Mastodon/Error.php:50 +#: src/Factory/Api/Mastodon/Error.php:58 #: src/Module/Special/HTTPException.php:50 msgid "Unauthorized" msgstr "" -#: src/Factory/Api/Mastodon/Error.php:59 +#: src/Factory/Api/Mastodon/Error.php:68 msgid "" "Token is not authorized with a valid user or is missing a required scope" msgstr "" -#: src/Factory/Api/Mastodon/Error.php:68 +#: src/Factory/Api/Mastodon/Error.php:78 #: src/Module/Special/HTTPException.php:53 msgid "Internal Server Error" msgstr "" @@ -4815,33 +4815,33 @@ msgstr "" msgid "Edit groups" msgstr "" -#: src/Model/Item.php:1582 +#: src/Model/Item.php:1600 #, php-format msgid "Detected languages in this post:\\n%s" msgstr "" -#: src/Model/Item.php:2527 +#: src/Model/Item.php:2538 msgid "activity" msgstr "" -#: src/Model/Item.php:2529 +#: src/Model/Item.php:2540 msgid "comment" msgstr "" -#: src/Model/Item.php:2532 +#: src/Model/Item.php:2543 msgid "post" msgstr "" -#: src/Model/Item.php:2646 +#: src/Model/Item.php:2657 #, php-format msgid "Content warning: %s" msgstr "" -#: src/Model/Item.php:2989 +#: src/Model/Item.php:3000 msgid "bytes" msgstr "" -#: src/Model/Item.php:3018 src/Model/Item.php:3019 +#: src/Model/Item.php:3029 src/Model/Item.php:3030 msgid "View on separate page" msgstr "" @@ -4959,138 +4959,138 @@ msgstr "" msgid "Enter a valid existing folder" msgstr "" -#: src/Model/User.php:186 src/Model/User.php:931 +#: src/Model/User.php:186 src/Model/User.php:986 msgid "SERIOUS ERROR: Generation of security keys failed." msgstr "" -#: src/Model/User.php:549 +#: src/Model/User.php:571 src/Model/User.php:604 msgid "Login failed" msgstr "" -#: src/Model/User.php:581 +#: src/Model/User.php:636 msgid "Not enough information to authenticate" msgstr "" -#: src/Model/User.php:676 +#: src/Model/User.php:731 msgid "Password can't be empty" msgstr "" -#: src/Model/User.php:695 +#: src/Model/User.php:750 msgid "Empty passwords are not allowed." msgstr "" -#: src/Model/User.php:699 +#: src/Model/User.php:754 msgid "" "The new password has been exposed in a public data dump, please choose " "another." msgstr "" -#: src/Model/User.php:705 +#: src/Model/User.php:760 msgid "" "The password can't contain accentuated letters, white spaces or colons (:)" msgstr "" -#: src/Model/User.php:811 +#: src/Model/User.php:866 msgid "Passwords do not match. Password unchanged." msgstr "" -#: src/Model/User.php:818 +#: src/Model/User.php:873 msgid "An invitation is required." msgstr "" -#: src/Model/User.php:822 +#: src/Model/User.php:877 msgid "Invitation could not be verified." msgstr "" -#: src/Model/User.php:830 +#: src/Model/User.php:885 msgid "Invalid OpenID url" msgstr "" -#: src/Model/User.php:843 src/Security/Authentication.php:224 +#: src/Model/User.php:898 src/Security/Authentication.php:224 msgid "" "We encountered a problem while logging in with the OpenID you provided. " "Please check the correct spelling of the ID." msgstr "" -#: src/Model/User.php:843 src/Security/Authentication.php:224 +#: src/Model/User.php:898 src/Security/Authentication.php:224 msgid "The error message was:" msgstr "" -#: src/Model/User.php:849 +#: src/Model/User.php:904 msgid "Please enter the required information." msgstr "" -#: src/Model/User.php:863 +#: src/Model/User.php:918 #, php-format msgid "" "system.username_min_length (%s) and system.username_max_length (%s) are " "excluding each other, swapping values." msgstr "" -#: src/Model/User.php:870 +#: src/Model/User.php:925 #, php-format msgid "Username should be at least %s character." msgid_plural "Username should be at least %s characters." msgstr[0] "" msgstr[1] "" -#: src/Model/User.php:874 +#: src/Model/User.php:929 #, php-format msgid "Username should be at most %s character." msgid_plural "Username should be at most %s characters." msgstr[0] "" msgstr[1] "" -#: src/Model/User.php:882 +#: src/Model/User.php:937 msgid "That doesn't appear to be your full (First Last) name." msgstr "" -#: src/Model/User.php:887 +#: src/Model/User.php:942 msgid "Your email domain is not among those allowed on this site." msgstr "" -#: src/Model/User.php:891 +#: src/Model/User.php:946 msgid "Not a valid email address." msgstr "" -#: src/Model/User.php:894 +#: src/Model/User.php:949 msgid "The nickname was blocked from registration by the nodes admin." msgstr "" -#: src/Model/User.php:898 src/Model/User.php:906 +#: src/Model/User.php:953 src/Model/User.php:961 msgid "Cannot use that email." msgstr "" -#: src/Model/User.php:913 +#: src/Model/User.php:968 msgid "Your nickname can only contain a-z, 0-9 and _." msgstr "" -#: src/Model/User.php:921 src/Model/User.php:978 +#: src/Model/User.php:976 src/Model/User.php:1033 msgid "Nickname is already registered. Please choose another." msgstr "" -#: src/Model/User.php:965 src/Model/User.php:969 +#: src/Model/User.php:1020 src/Model/User.php:1024 msgid "An error occurred during registration. Please try again." msgstr "" -#: src/Model/User.php:992 +#: src/Model/User.php:1047 msgid "An error occurred creating your default profile. Please try again." msgstr "" -#: src/Model/User.php:999 +#: src/Model/User.php:1054 msgid "An error occurred creating your self contact. Please try again." msgstr "" -#: src/Model/User.php:1004 +#: src/Model/User.php:1059 msgid "Friends" msgstr "" -#: src/Model/User.php:1008 +#: src/Model/User.php:1063 msgid "" "An error occurred creating your default contact group. Please try again." msgstr "" -#: src/Model/User.php:1199 +#: src/Model/User.php:1254 #, php-format msgid "" "\n" @@ -5098,7 +5098,7 @@ msgid "" "\t\t\tthe administrator of %2$s has set up an account for you." msgstr "" -#: src/Model/User.php:1202 +#: src/Model/User.php:1257 #, php-format msgid "" "\n" @@ -5135,12 +5135,12 @@ msgid "" "\t\tThank you and welcome to %4$s." msgstr "" -#: src/Model/User.php:1235 src/Model/User.php:1342 +#: src/Model/User.php:1290 src/Model/User.php:1397 #, php-format msgid "Registration details for %s" msgstr "" -#: src/Model/User.php:1255 +#: src/Model/User.php:1310 #, php-format msgid "" "\n" @@ -5156,12 +5156,12 @@ msgid "" "\t\t" msgstr "" -#: src/Model/User.php:1274 +#: src/Model/User.php:1329 #, php-format msgid "Registration at %s" msgstr "" -#: src/Model/User.php:1298 +#: src/Model/User.php:1353 #, php-format msgid "" "\n" @@ -5170,7 +5170,7 @@ msgid "" "\t\t\t" msgstr "" -#: src/Model/User.php:1306 +#: src/Model/User.php:1361 #, php-format msgid "" "\n" @@ -7201,7 +7201,7 @@ msgstr "" msgid "Deny" msgstr "" -#: src/Module/Api/Mastodon/Apps.php:47 src/Module/Api/Mastodon/Apps.php:58 +#: src/Module/Api/Mastodon/Apps.php:58 msgid "Missing parameters" msgstr "" @@ -8882,15 +8882,15 @@ msgstr "" msgid "Show all" msgstr "" -#: src/Module/OAuth/Authorize.php:49 +#: src/Module/OAuth/Authorize.php:51 msgid "Unsupported or missing response type" msgstr "" -#: src/Module/OAuth/Authorize.php:54 src/Module/OAuth/Token.php:55 +#: src/Module/OAuth/Authorize.php:56 src/Module/OAuth/Token.php:57 msgid "Incomplete request data" msgstr "" -#: src/Module/OAuth/Token.php:79 +#: src/Module/OAuth/Token.php:81 msgid "Unsupported or missing grant type" msgstr "" @@ -10585,20 +10585,20 @@ msgstr "" msgid "Contact information and Social Networks" msgstr "" -#: src/Security/Authentication.php:210 src/Security/Authentication.php:262 +#: src/Security/Authentication.php:210 msgid "Login failed." msgstr "" -#: src/Security/Authentication.php:273 +#: src/Security/Authentication.php:251 msgid "Login failed. Please check your credentials." msgstr "" -#: src/Security/Authentication.php:392 +#: src/Security/Authentication.php:370 #, php-format msgid "Welcome %s" msgstr "" -#: src/Security/Authentication.php:393 +#: src/Security/Authentication.php:371 msgid "Please upload a profile photo." msgstr "" From 97a9ec4e401155f0041326bd471566e4fe12e5fb Mon Sep 17 00:00:00 2001 From: very-ape Date: Fri, 21 May 2021 11:38:50 -0700 Subject: [PATCH 008/311] Bug fix: last commit results in logged-in user's contacts being displayed on contact profile sidebar. --- src/Model/Profile.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Model/Profile.php b/src/Model/Profile.php index 7454929943..1476d67a51 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -169,12 +169,13 @@ class Profile if (empty($user['uid'])) { $profile = []; } else { + $contact_id = Contact::getIdForURL(Strings::normaliseLink(DI::baseurl() . '/profile/' . $nickname), local_user()); $profile = array_merge( $user, + Contact::getById($contact_id), Profile::getByUID($user['uid']), - Contact::getById(Contact::getIdForURL(Strings::normaliseLink(DI::baseurl() . '/profile/' . $nickname), local_user())) ); - $profile['cid'] = $profile['id']; + $profile['cid'] = $contact_id; } if (empty($profile) && empty($profiledata)) { From 46301b79511af58f17921d8533a80265c31227f6 Mon Sep 17 00:00:00 2001 From: Michael Date: Fri, 21 May 2021 20:45:01 +0000 Subject: [PATCH 009/311] Changed description --- doc/API-Mastodon.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/API-Mastodon.md b/doc/API-Mastodon.md index 5610f926fb..37f62e0607 100644 --- a/doc/API-Mastodon.md +++ b/doc/API-Mastodon.md @@ -126,8 +126,8 @@ These emdpoints are planned to be implemented somewhere in the future. ## Dummy endpoints -These endpoints are returning empty data to avoid error messages with (for example) mobile clients. -They belong to a functionality that doesn't exist in Friendica yet. +These endpoints are returning empty data to avoid error messages when using third party clients. +They refer to features that don't exist in Friendica yet. - [`GET /api/v1/accounts/:id/identity_proofs`](https://docs.joinmastodon.org/methods/accounts/) - [`GET /api/v1/announcements`](https://docs.joinmastodon.org/methods/announcements/) @@ -139,7 +139,7 @@ They belong to a functionality that doesn't exist in Friendica yet. ## Non supportable endpoints These endpoints won't be implemented at the moment. -They belong to a functionality that doesn't exist in Friendica yet. +They refer to features that don't exist in Friendica yet. - [`POST /api/v1/accounts`](https://docs.joinmastodon.org/methods/accounts/) - [`POST /api/v1/accounts/:id/pin`](https://docs.joinmastodon.org/methods/accounts/) From c22ef3e79e0fb22f41f8d425e3d89c50e27f7de9 Mon Sep 17 00:00:00 2001 From: very-ape Date: Fri, 21 May 2021 14:28:01 -0700 Subject: [PATCH 010/311] Fix message button using a more targeted approach. --- src/Model/Profile.php | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/Model/Profile.php b/src/Model/Profile.php index 1476d67a51..0efdb7ae66 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -145,7 +145,7 @@ class Profile */ public static function load(App $a, $nickname, array $profiledata = [], $show_connect = true) { - $user = User::getByNickname($nickname); + $user = DBA::selectFirst('user', ['uid'], ['nickname' => $nickname, 'account_removed' => false]); if (!DBA::isResult($user) && empty($profiledata)) { Logger::log('profile error: ' . DI::args()->getQueryString(), Logger::DEBUG); @@ -166,17 +166,7 @@ class Profile } } - if (empty($user['uid'])) { - $profile = []; - } else { - $contact_id = Contact::getIdForURL(Strings::normaliseLink(DI::baseurl() . '/profile/' . $nickname), local_user()); - $profile = array_merge( - $user, - Contact::getById($contact_id), - Profile::getByUID($user['uid']), - ); - $profile['cid'] = $contact_id; - } + $profile = !empty($user['uid']) ? User::getOwnerDataById($user['uid'], false) : []; if (empty($profile) && empty($profiledata)) { Logger::log('profile error: ' . DI::args()->getQueryString(), Logger::DEBUG); @@ -273,8 +263,17 @@ class Profile $o = ''; $location = false; - // This function can also use contact information in $profile - $is_contact = !empty($profile['cid']); + // This function can also use contact information in $profile, but the 'cid' + // value is going to be coming from 'owner-view', which means it's the wrong + // contact ID for the user viewing this page. Use 'nurl' to look up the + // correct contact table entry for the logged-in user. + $is_contact = !empty($profile['nurl']); + $contact = []; + + if ($is_contact) { + $contact_id = Contact::getIdForURL($profile['nurl'], local_user()); + $contact = Contact::getById($contact_id); + } if (empty($profile['nickname'])) { Logger::warning('Received profile with no nickname', ['profile' => $profile, 'callstack' => System::callstack(10)]); @@ -302,14 +301,16 @@ class Profile $subscribe_feed_link = null; $wallmessage_link = null; + // Who is the logged-in user to this profile? $visitor_contact = []; if (!empty($profile['uid']) && self::getMyURL()) { $visitor_contact = Contact::selectFirst(['rel'], ['uid' => $profile['uid'], 'nurl' => Strings::normaliseLink(self::getMyURL())]); } + // Who is this profile to the logged-in user? $profile_contact = []; - if (!empty($profile['cid']) && self::getMyURL()) { - $profile_contact = Contact::selectFirst(['rel'], ['id' => $profile['cid']]); + if (!empty($contact) && self::getMyURL()) { + $profile_contact = $contact['rel']; } $profile_is_dfrn = $profile['network'] == Protocol::DFRN; @@ -342,9 +343,9 @@ class Profile $subscribe_feed_link = 'dfrn_poll/' . $profile['nickname']; } - if (Contact::canReceivePrivateMessages($profile)) { + if (Contact::canReceivePrivateMessages($contact)) { if ($visitor_is_followed || $visitor_is_following) { - $wallmessage_link = $visitor_base_path . '/message/new/' . $profile['cid']; + $wallmessage_link = $visitor_base_path . '/message/new/' . $contact['id']; } elseif ($visitor_is_authenticated && !empty($profile['unkmail'])) { $wallmessage_link = 'wallmessage/' . $profile['nickname']; } From 857e14636fdb74b13fd7c3d8120436dc0078e4fe Mon Sep 17 00:00:00 2001 From: very-ape Date: Fri, 21 May 2021 15:58:35 -0700 Subject: [PATCH 011/311] Bug fix: Keep the introductions notification badge from claiming its own line! --- view/theme/vier/templates/nav.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/theme/vier/templates/nav.tpl b/view/theme/vier/templates/nav.tpl index 32a588f3d7..b2da2b0d7a 100644 --- a/view/theme/vier/templates/nav.tpl +++ b/view/theme/vier/templates/nav.tpl @@ -81,7 +81,7 @@ {{$userinfo.name}}{{$userinfo.name}}