Merge pull request #11402 from annando/featured-endpoint

We now offer an endpoint for featured posts
This commit is contained in:
Hypolite Petovan 2022-04-11 11:17:56 -04:00 committed by GitHub
commit 3842f02b02
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 265 additions and 173 deletions

View file

@ -28,12 +28,14 @@ use Friendica\Content\Nav;
use Friendica\Content\Widget; use Friendica\Content\Widget;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Core\Session; use Friendica\Core\Session;
use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Event; use Friendica\Model\Event;
use Friendica\Model\Item; use Friendica\Model\Item;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Module\BaseProfile; use Friendica\Module\BaseProfile;
use Friendica\Module\Response;
use Friendica\Network\HTTPException; use Friendica\Network\HTTPException;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Temporal; use Friendica\Util\Temporal;
@ -216,8 +218,7 @@ function cal_content(App $a)
$events = Event::prepareListForTemplate($r); $events = Event::prepareListForTemplate($r);
if (!empty(DI::args()->getArgv()[2]) && (DI::args()->getArgv()[2] === 'json')) { if (!empty(DI::args()->getArgv()[2]) && (DI::args()->getArgv()[2] === 'json')) {
echo json_encode($events); System::jsonExit($events);
exit();
} }
// links: array('href', 'text', 'extra css classes', 'title') // links: array('href', 'text', 'extra css classes', 'title')
@ -253,8 +254,7 @@ function cal_content(App $a)
]); ]);
if (!empty($_GET['id'])) { if (!empty($_GET['id'])) {
echo $o; System::httpExit($o);
exit();
} }
return $o; return $o;
@ -289,10 +289,8 @@ function cal_content(App $a)
// If nothing went wrong we can echo the export content // If nothing went wrong we can echo the export content
if ($evexport["success"]) { if ($evexport["success"]) {
header('Content-type: text/calendar');
header('content-disposition: attachment; filename="' . DI::l10n()->t('calendar') . '-' . $nick . '.' . $evexport["extension"] . '"'); header('content-disposition: attachment; filename="' . DI::l10n()->t('calendar') . '-' . $nick . '.' . $evexport["extension"] . '"');
echo $evexport["content"]; System::httpExit($evexport["content"], Response::TYPE_BLANK, 'text/calendar');
exit();
} }
return; return;

View file

@ -25,6 +25,7 @@ use Friendica\Content\Widget;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Core\Session; use Friendica\Core\Session;
use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
@ -32,6 +33,7 @@ use Friendica\Model\Item;
use Friendica\Model\Post; use Friendica\Model\Post;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Module\ActivityPub\Objects; use Friendica\Module\ActivityPub\Objects;
use Friendica\Module\Response;
use Friendica\Network\HTTPException; use Friendica\Network\HTTPException;
use Friendica\Protocol\ActivityPub; use Friendica\Protocol\ActivityPub;
use Friendica\Protocol\DFRN; use Friendica\Protocol\DFRN;
@ -342,7 +344,6 @@ function displayShowFeed(int $uri_id, int $uid, bool $conversation)
if ($xml == '') { if ($xml == '') {
throw new HTTPException\InternalServerErrorException(DI::l10n()->t('The feed for this item is unavailable.')); throw new HTTPException\InternalServerErrorException(DI::l10n()->t('The feed for this item is unavailable.'));
} }
header("Content-type: application/atom+xml");
echo $xml; System::httpExit($xml, Response::TYPE_ATOM);
exit();
} }

View file

@ -27,6 +27,7 @@ use Friendica\Core\ACL;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Core\Protocol; use Friendica\Core\Protocol;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Core\Theme; use Friendica\Core\Theme;
use Friendica\Core\Worker; use Friendica\Core\Worker;
use Friendica\Database\DBA; use Friendica\Database\DBA;
@ -122,8 +123,7 @@ function events_post(App $a)
if (strcmp($finish, $start) < 0 && !$nofinish) { if (strcmp($finish, $start) < 0 && !$nofinish) {
notice(DI::l10n()->t('Event can not end before it has started.')); notice(DI::l10n()->t('Event can not end before it has started.'));
if (intval($_REQUEST['preview'])) { if (intval($_REQUEST['preview'])) {
echo DI::l10n()->t('Event can not end before it has started.'); System::httpExit(DI::l10n()->t('Event can not end before it has started.'));
exit();
} }
DI::baseUrl()->redirect($onerror_path); DI::baseUrl()->redirect($onerror_path);
} }
@ -131,8 +131,7 @@ function events_post(App $a)
if (!$summary || ($start === DBA::NULL_DATETIME)) { if (!$summary || ($start === DBA::NULL_DATETIME)) {
notice(DI::l10n()->t('Event title and start time are required.')); notice(DI::l10n()->t('Event title and start time are required.'));
if (intval($_REQUEST['preview'])) { if (intval($_REQUEST['preview'])) {
echo DI::l10n()->t('Event title and start time are required.'); System::httpExit(DI::l10n()->t('Event title and start time are required.'));
exit();
} }
DI::baseUrl()->redirect($onerror_path); DI::baseUrl()->redirect($onerror_path);
} }
@ -192,9 +191,7 @@ function events_post(App $a)
$datarray['id'] = $event_id; $datarray['id'] = $event_id;
if (intval($_REQUEST['preview'])) { if (intval($_REQUEST['preview'])) {
$html = Event::getHTML($datarray); System::httpExit(Event::getHTML($datarray));
echo $html;
exit();
} }
$event_id = Event::store($datarray); $event_id = Event::store($datarray);
@ -391,8 +388,7 @@ function events_content(App $a)
]); ]);
if (!empty($_GET['id'])) { if (!empty($_GET['id'])) {
echo $o; System::httpExit($o);
exit();
} }
return $o; return $o;

View file

@ -24,6 +24,7 @@
use Friendica\App; use Friendica\App;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Photo; use Friendica\Model\Photo;
@ -153,7 +154,6 @@ function fbrowser_content(App $a)
if (!empty($_GET['mode'])) { if (!empty($_GET['mode'])) {
return $o; return $o;
} else { } else {
echo $o; System::httpExit($o);
exit();
} }
} }

View file

@ -20,6 +20,7 @@
*/ */
use Friendica\App; use Friendica\App;
use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\User; use Friendica\Model\User;
@ -37,8 +38,7 @@ function msearch_post(App $a)
if (!strlen($search)) { if (!strlen($search)) {
$output = ['total' => 0, 'items_page' => $perpage, 'page' => $page, 'results' => $results]; $output = ['total' => 0, 'items_page' => $perpage, 'page' => $page, 'results' => $results];
echo json_encode($output); System::jsonExit($output);
exit();
} }
$total = 0; $total = 0;
@ -60,7 +60,5 @@ function msearch_post(App $a)
$output = ['total' => $total, 'items_page' => $perpage, 'page' => $page, 'results' => $results]; $output = ['total' => $total, 'items_page' => $perpage, 'page' => $page, 'results' => $results];
echo json_encode($output); System::jsonExit($output);
exit();
} }

View file

@ -21,7 +21,9 @@
use Friendica\App; use Friendica\App;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\DI; use Friendica\DI;
use Friendica\Module\Response;
use Friendica\Module\Security\Login; use Friendica\Module\Security\Login;
function oexchange_init(App $a) { function oexchange_init(App $a) {
@ -30,8 +32,7 @@ function oexchange_init(App $a) {
$tpl = Renderer::getMarkupTemplate('oexchange_xrd.tpl'); $tpl = Renderer::getMarkupTemplate('oexchange_xrd.tpl');
$o = Renderer::replaceMacros($tpl, ['$base' => DI::baseUrl()]); $o = Renderer::replaceMacros($tpl, ['$base' => DI::baseUrl()]);
echo $o; System::httpExit($o, Response::TYPE_XML, 'application/xrd+xml');
exit();
} }
} }

View file

@ -25,10 +25,11 @@ use Friendica\Content\Text\BBCode;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Core\Protocol; use Friendica\Core\Protocol;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Module\Response;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Strings;
use Friendica\Util\XML; use Friendica\Util\XML;
function poco_init(App $a) { function poco_init(App $a) {
@ -229,14 +230,10 @@ function poco_init(App $a) {
Logger::info("End of poco"); Logger::info("End of poco");
if ($format === 'xml') { if ($format === 'xml') {
header('Content-type: text/xml'); System::httpExit(Renderer::replaceMacros(Renderer::getMarkupTemplate('poco_xml.tpl'), XML::arrayEscape(['$response' => $ret])), Response::TYPE_XML);
echo Renderer::replaceMacros(Renderer::getMarkupTemplate('poco_xml.tpl'), XML::arrayEscape(['$response' => $ret]));
exit();
} }
if ($format === 'json') { if ($format === 'json') {
header('Content-type: application/json'); System::jsonExit($ret);
echo json_encode($ret);
exit();
} else { } else {
throw new \Friendica\Network\HTTPException\InternalServerErrorException(); throw new \Friendica\Network\HTTPException\InternalServerErrorException();
} }

View file

@ -21,6 +21,7 @@
use Friendica\App; use Friendica\App;
use Friendica\Core\Session; use Friendica\Core\Session;
use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Attach; use Friendica\Model\Attach;
@ -36,15 +37,13 @@ function wall_attach_post(App $a) {
$owner = User::getOwnerDataByNick($nick); $owner = User::getOwnerDataByNick($nick);
if (!DBA::isResult($owner)) { if (!DBA::isResult($owner)) {
if ($r_json) { if ($r_json) {
echo json_encode(['error' => DI::l10n()->t('Invalid request.')]); System::jsonExit(['error' => DI::l10n()->t('Invalid request.')]);
exit();
} }
return; return;
} }
} else { } else {
if ($r_json) { if ($r_json) {
echo json_encode(['error' => DI::l10n()->t('Invalid request.')]); System::jsonExit(['error' => DI::l10n()->t('Invalid request.')]);
exit();
} }
return; return;
@ -65,8 +64,7 @@ function wall_attach_post(App $a) {
if (!$can_post) { if (!$can_post) {
if ($r_json) { if ($r_json) {
echo json_encode(['error' => DI::l10n()->t('Permission denied.')]); System::jsonExit(['error' => DI::l10n()->t('Permission denied.')]);
exit();
} }
notice(DI::l10n()->t('Permission denied.') . EOL ); notice(DI::l10n()->t('Permission denied.') . EOL );
exit(); exit();
@ -74,7 +72,7 @@ function wall_attach_post(App $a) {
if (empty($_FILES['userfile'])) { if (empty($_FILES['userfile'])) {
if ($r_json) { if ($r_json) {
echo json_encode(['error' => DI::l10n()->t('Invalid request.')]); System::jsonExit(['error' => DI::l10n()->t('Invalid request.')]);
} }
exit(); exit();
} }
@ -93,23 +91,23 @@ function wall_attach_post(App $a) {
if ($filesize <= 0) { if ($filesize <= 0) {
$msg = DI::l10n()->t('Sorry, maybe your upload is bigger than the PHP configuration allows') . EOL .(DI::l10n()->t('Or - did you try to upload an empty file?')); $msg = DI::l10n()->t('Sorry, maybe your upload is bigger than the PHP configuration allows') . EOL .(DI::l10n()->t('Or - did you try to upload an empty file?'));
@unlink($src);
if ($r_json) { if ($r_json) {
echo json_encode(['error' => $msg]); System::jsonExit(['error' => $msg]);
} else { } else {
notice($msg); notice($msg);
} }
@unlink($src);
exit(); exit();
} }
if ($maxfilesize && $filesize > $maxfilesize) { if ($maxfilesize && $filesize > $maxfilesize) {
$msg = DI::l10n()->t('File exceeds size limit of %s', Strings::formatBytes($maxfilesize)); $msg = DI::l10n()->t('File exceeds size limit of %s', Strings::formatBytes($maxfilesize));
@unlink($src);
if ($r_json) { if ($r_json) {
echo json_encode(['error' => $msg]); System::jsonExit(['error' => $msg]);
} else { } else {
echo $msg . EOL; echo $msg . EOL;
} }
@unlink($src);
exit(); exit();
} }
@ -120,7 +118,7 @@ function wall_attach_post(App $a) {
if ($newid === false) { if ($newid === false) {
$msg = DI::l10n()->t('File upload failed.'); $msg = DI::l10n()->t('File upload failed.');
if ($r_json) { if ($r_json) {
echo json_encode(['error' => $msg]); System::jsonExit(['error' => $msg]);
} else { } else {
echo $msg . EOL; echo $msg . EOL;
} }
@ -128,8 +126,7 @@ function wall_attach_post(App $a) {
} }
if ($r_json) { if ($r_json) {
echo json_encode(['ok' => true, 'id' => $newid]); System::jsonExit(['ok' => true, 'id' => $newid]);
exit();
} }
$lf = "\n"; $lf = "\n";

View file

@ -28,6 +28,7 @@
use Friendica\App; use Friendica\App;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Core\Session; use Friendica\Core\Session;
use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Photo; use Friendica\Model\Photo;
@ -50,8 +51,7 @@ function wall_upload_post(App $a, $desktopmode = true)
$user = DBA::selectFirst('owner-view', ['id', 'uid', 'nickname', 'page-flags'], ['nickname' => $nick, 'blocked' => false]); $user = DBA::selectFirst('owner-view', ['id', 'uid', 'nickname', 'page-flags'], ['nickname' => $nick, 'blocked' => false]);
if (!DBA::isResult($user)) { if (!DBA::isResult($user)) {
if ($r_json) { if ($r_json) {
echo json_encode(['error' => DI::l10n()->t('Invalid request.')]); System::jsonExit(['error' => DI::l10n()->t('Invalid request.')]);
exit();
} }
return; return;
} }
@ -60,8 +60,7 @@ function wall_upload_post(App $a, $desktopmode = true)
} }
} else { } else {
if ($r_json) { if ($r_json) {
echo json_encode(['error' => DI::l10n()->t('Invalid request.')]); System::jsonExit(['error' => DI::l10n()->t('Invalid request.')]);
exit();
} }
return; return;
} }
@ -87,8 +86,7 @@ function wall_upload_post(App $a, $desktopmode = true)
if (!$can_post) { if (!$can_post) {
if ($r_json) { if ($r_json) {
echo json_encode(['error' => DI::l10n()->t('Permission denied.')]); System::jsonExit(['error' => DI::l10n()->t('Permission denied.')]);
exit();
} }
notice(DI::l10n()->t('Permission denied.')); notice(DI::l10n()->t('Permission denied.'));
exit(); exit();
@ -96,7 +94,7 @@ function wall_upload_post(App $a, $desktopmode = true)
if (empty($_FILES['userfile']) && empty($_FILES['media'])) { if (empty($_FILES['userfile']) && empty($_FILES['media'])) {
if ($r_json) { if ($r_json) {
echo json_encode(['error' => DI::l10n()->t('Invalid request.')]); System::jsonExit(['error' => DI::l10n()->t('Invalid request.')]);
} }
exit(); exit();
} }
@ -147,8 +145,7 @@ function wall_upload_post(App $a, $desktopmode = true)
if ($src == "") { if ($src == "") {
if ($r_json) { if ($r_json) {
echo json_encode(['error' => DI::l10n()->t('Invalid request.')]); System::jsonExit(['error' => DI::l10n()->t('Invalid request.')]);
exit();
} }
notice(DI::l10n()->t('Invalid request.')); notice(DI::l10n()->t('Invalid request.'));
exit(); exit();
@ -164,12 +161,12 @@ function wall_upload_post(App $a, $desktopmode = true)
if (!$Image->isValid()) { if (!$Image->isValid()) {
$msg = DI::l10n()->t('Unable to process image.'); $msg = DI::l10n()->t('Unable to process image.');
@unlink($src);
if ($r_json) { if ($r_json) {
echo json_encode(['error' => $msg]); System::jsonExit(['error' => $msg]);
} else { } else {
echo $msg. EOL; echo $msg. EOL;
} }
@unlink($src);
exit(); exit();
} }
@ -202,12 +199,12 @@ function wall_upload_post(App $a, $desktopmode = true)
if ($filesize > $maximagesize) { if ($filesize > $maximagesize) {
Logger::notice('Image size is too big', ['size' => $filesize, 'max' => $maximagesize]); Logger::notice('Image size is too big', ['size' => $filesize, 'max' => $maximagesize]);
$msg = DI::l10n()->t('Image exceeds size limit of %s', Strings::formatBytes($maximagesize)); $msg = DI::l10n()->t('Image exceeds size limit of %s', Strings::formatBytes($maximagesize));
@unlink($src);
if ($r_json) { if ($r_json) {
echo json_encode(['error' => $msg]); System::jsonExit(['error' => $msg]);
} else { } else {
echo $msg. EOL; echo $msg. EOL;
} }
@unlink($src);
exit(); exit();
} }
} }
@ -228,7 +225,7 @@ function wall_upload_post(App $a, $desktopmode = true)
if (!$r) { if (!$r) {
$msg = DI::l10n()->t('Image upload failed.'); $msg = DI::l10n()->t('Image upload failed.');
if ($r_json) { if ($r_json) {
echo json_encode(['error' => $msg]); System::jsonExit(['error' => $msg]);
} else { } else {
echo $msg. EOL; echo $msg. EOL;
} }
@ -255,8 +252,7 @@ function wall_upload_post(App $a, $desktopmode = true)
$photo = Photo::selectFirst(['id', 'datasize', 'width', 'height', 'type'], ['resource-id' => $resource_id], ['order' => ['width']]); $photo = Photo::selectFirst(['id', 'datasize', 'width', 'height', 'type'], ['resource-id' => $resource_id], ['order' => ['width']]);
if (!$photo) { if (!$photo) {
if ($r_json) { if ($r_json) {
echo json_encode(['error' => '']); System::jsonExit(['error' => '']);
exit();
} }
return false; return false;
} }
@ -272,8 +268,7 @@ function wall_upload_post(App $a, $desktopmode = true)
$picture["preview"] = DI::baseUrl() . "/photo/{$resource_id}-{$smallest}." . $Image->getExt(); $picture["preview"] = DI::baseUrl() . "/photo/{$resource_id}-{$smallest}." . $Image->getExt();
if ($r_json) { if ($r_json) {
echo json_encode(['picture' => $picture]); System::jsonExit(['picture' => $picture]);
exit();
} }
Logger::info("upload done"); Logger::info("upload done");
return $picture; return $picture;
@ -282,8 +277,7 @@ function wall_upload_post(App $a, $desktopmode = true)
Logger::info("upload done"); Logger::info("upload done");
if ($r_json) { if ($r_json) {
echo json_encode(['ok' => true]); System::jsonExit(['ok' => true]);
exit();
} }
echo "\n\n" . '[url=' . DI::baseUrl() . '/photos/' . $page_owner_nick . '/image/' . $resource_id . '][img]' . DI::baseUrl() . "/photo/{$resource_id}-{$smallest}.".$Image->getExt()."[/img][/url]\n\n"; echo "\n\n" . '[url=' . DI::baseUrl() . '/photos/' . $page_owner_nick . '/image/' . $resource_id . '][img]' . DI::baseUrl() . "/photo/{$resource_id}-{$smallest}.".$Image->getExt()."[/img][/url]\n\n";

View file

@ -31,7 +31,9 @@ use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
use Friendica\Core\Hook; use Friendica\Core\Hook;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Core\Theme; use Friendica\Core\Theme;
use Friendica\Module\Response;
use Friendica\Network\HTTPException; use Friendica\Network\HTTPException;
use Friendica\Util\Network; use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
@ -503,11 +505,7 @@ class Page implements ArrayAccess
} }
if ($_GET["mode"] == "raw") { if ($_GET["mode"] == "raw") {
header("Content-type: text/html; charset=utf-8"); System::httpExit(substr($target->saveHTML(), 6, -8), Response::TYPE_HTML);
echo substr($target->saveHTML(), 6, -8);
exit();
} }
} }

View file

@ -306,25 +306,41 @@ class System
* @param string $content Response body. Optional. * @param string $content Response body. Optional.
* @throws \Exception * @throws \Exception
*/ */
public static function httpExit($val, $message = '', $content = '') public static function httpError($httpCode, $message = '', $content = '')
{ {
if ($val >= 400) { if ($httpCode >= 400) {
Logger::debug('Exit with error', ['code' => $val, 'message' => $message, 'callstack' => System::callstack(20), 'method' => DI::args()->getMethod(), 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '']); Logger::debug('Exit with error', ['code' => $httpCode, 'message' => $message, 'callstack' => System::callstack(20), 'method' => DI::args()->getMethod(), 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '']);
} }
DI::apiResponse()->setStatus($val, $message); DI::apiResponse()->setStatus($httpCode, $message);
DI::apiResponse()->addContent($content); DI::apiResponse()->addContent($content);
DI::page()->exit(DI::apiResponse()->generate()); DI::page()->exit(DI::apiResponse()->generate());
exit(); exit();
} }
public static function jsonError($httpCode, $data, $content_type = 'application/json') /**
* This function adds the content and a content-teype HTTP header to the output.
* After finishing the process is getting killed.
*
* @param string $content
* @param [type] $responce
* @param string|null $content_type
* @return void
*/
public static function httpExit(string $content, string $responce = Response::TYPE_HTML, ?string $content_type = null) {
DI::apiResponse()->setType($responce, $content_type);
DI::apiResponse()->addContent($content);
DI::page()->exit(DI::apiResponse()->generate());
exit();
}
public static function jsonError($httpCode, $content, $content_type = 'application/json')
{ {
if ($httpCode >= 400) { if ($httpCode >= 400) {
Logger::debug('Exit with error', ['code' => $httpCode, 'content_type' => $content_type, 'callstack' => System::callstack(20), 'method' => DI::args()->getMethod(), 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '']); Logger::debug('Exit with error', ['code' => $httpCode, 'content_type' => $content_type, 'callstack' => System::callstack(20), 'method' => DI::args()->getMethod(), 'agent' => $_SERVER['HTTP_USER_AGENT'] ?? '']);
} }
DI::apiResponse()->setStatus($httpCode); DI::apiResponse()->setStatus($httpCode);
self::jsonExit($data, $content_type); self::jsonExit($content, $content_type);
} }
/** /**
@ -334,14 +350,14 @@ class System
* and adds an application/json HTTP header to the output. * and adds an application/json HTTP header to the output.
* After finishing the process is getting killed. * After finishing the process is getting killed.
* *
* @param mixed $x The input content * @param mixed $content The input content
* @param string $content_type Type of the input (Default: 'application/json') * @param string $content_type Type of the input (Default: 'application/json')
* @param integer $options JSON options * @param integer $options JSON options
* @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/ */
public static function jsonExit($x, $content_type = 'application/json', int $options = 0) { public static function jsonExit($content, $content_type = 'application/json', int $options = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) {
DI::apiResponse()->setType(Response::TYPE_JSON, $content_type); DI::apiResponse()->setType(Response::TYPE_JSON, $content_type);
DI::apiResponse()->addContent(json_encode($x, $options)); DI::apiResponse()->addContent(json_encode($content, $options));
DI::page()->exit(DI::apiResponse()->generate()); DI::page()->exit(DI::apiResponse()->generate());
exit(); exit();
} }

View file

@ -1474,7 +1474,8 @@ class Contact
if ($pager->getStart() == 0) { if ($pager->getStart() == 0) {
$cdata = Contact::getPublicAndUserContactID($cid, local_user()); $cdata = Contact::getPublicAndUserContactID($cid, local_user());
if (!empty($cdata['public'])) { if (!empty($cdata['public'])) {
$condition = ["`uri-id` IN (SELECT `uri-id` FROM `collection-view` WHERE `cid` = ?)", $cdata['public']]; $condition = ["`uri-id` IN (SELECT `uri-id` FROM `collection-view` WHERE `cid` = ? AND `type` = ?)",
$cdata['public'], Post\Collection::FEATURED];
$pinned = Post::toArray(Post::selectForUser(local_user(), $fields, $condition, $params)); $pinned = Post::toArray(Post::selectForUser(local_user(), $fields, $condition, $params));
$items = array_merge($pinned, $items); $items = array_merge($pinned, $items);
} }

View file

@ -22,6 +22,7 @@
namespace Friendica\Module; namespace Friendica\Module;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\System;
/** /**
* Static definition for the Firefox Account Manager * Static definition for the Firefox Account Manager
@ -78,7 +79,6 @@ class AccountManagementControlDocument extends BaseModule
], ],
]; ];
echo json_encode($output); System::jsonExit($output);
exit();
} }
} }

View file

@ -0,0 +1,51 @@
<?php
/**
* @copyright Copyright (C) 2010-2022, the Friendica project
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
namespace Friendica\Module\ActivityPub;
use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\Model\User;
use Friendica\Protocol\ActivityPub;
/**
* ActivityPub featured posts
*/
class Featured extends BaseModule
{
protected function rawContent(array $request = [])
{
if (empty($this->parameters['nickname'])) {
throw new \Friendica\Network\HTTPException\NotFoundException();
}
$owner = User::getOwnerDataByNick($this->parameters['nickname']);
if (empty($owner)) {
throw new \Friendica\Network\HTTPException\NotFoundException();
}
$page = $request['page'] ?? null;
$featured = ActivityPub\Transmitter::getFeatured($owner, $page);
System::jsonExit($featured, 'application/activity+json');
}
}

View file

@ -22,6 +22,7 @@
namespace Friendica\Module\ActivityPub; namespace Friendica\Module\ActivityPub;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Protocol\ActivityPub; use Friendica\Protocol\ActivityPub;
@ -48,8 +49,6 @@ class Followers extends BaseModule
$followers = ActivityPub\Transmitter::getContacts($owner, [Contact::FOLLOWER, Contact::FRIEND], 'followers', $page, (string)HTTPSignature::getSigner('', $_SERVER)); $followers = ActivityPub\Transmitter::getContacts($owner, [Contact::FOLLOWER, Contact::FRIEND], 'followers', $page, (string)HTTPSignature::getSigner('', $_SERVER));
header('Content-Type: application/activity+json'); System::jsonExit($followers, 'application/activity+json');
echo json_encode($followers);
exit();
} }
} }

View file

@ -22,6 +22,7 @@
namespace Friendica\Module\ActivityPub; namespace Friendica\Module\ActivityPub;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Protocol\ActivityPub; use Friendica\Protocol\ActivityPub;
@ -46,8 +47,6 @@ class Following extends BaseModule
$following = ActivityPub\Transmitter::getContacts($owner, [Contact::SHARING, Contact::FRIEND], 'following', $page); $following = ActivityPub\Transmitter::getContacts($owner, [Contact::SHARING, Contact::FRIEND], 'following', $page);
header('Content-Type: application/activity+json'); System::jsonExit($following, 'application/activity+json');
echo json_encode($following);
exit();
} }
} }

View file

@ -50,7 +50,7 @@ class Inbox extends BaseModule
$filename = 'failed-activitypub'; $filename = 'failed-activitypub';
} }
$tempfile = tempnam(System::getTempPath(), $filename); $tempfile = tempnam(System::getTempPath(), $filename);
file_put_contents($tempfile, json_encode(['parameters' => $this->parameters, 'header' => $_SERVER, 'body' => $postdata], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); file_put_contents($tempfile, json_encode(['parameters' => $this->parameters, 'header' => $_SERVER, 'body' => $postdata], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
Logger::notice('Incoming message stored', ['file' => $tempfile]); Logger::notice('Incoming message stored', ['file' => $tempfile]);
} }

View file

@ -31,7 +31,6 @@ use Friendica\Model\Item;
use Friendica\Model\Post; use Friendica\Model\Post;
use Friendica\Network\HTTPException; use Friendica\Network\HTTPException;
use Friendica\Protocol\ActivityPub; use Friendica\Protocol\ActivityPub;
use Friendica\Security\PermissionSet\Repository\PermissionSet;
use Friendica\Util\HTTPSignature; use Friendica\Util\HTTPSignature;
use Friendica\Util\Network; use Friendica\Util\Network;
use Friendica\Util\Strings; use Friendica\Util\Strings;
@ -130,6 +129,7 @@ class Objects extends BaseModule
// Relaxed CORS header for public items // Relaxed CORS header for public items
header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Origin: *');
System::jsonExit($data, 'application/activity+json'); System::jsonExit($data, 'application/activity+json');
} }
} }

View file

@ -22,6 +22,7 @@
namespace Friendica\Module\ActivityPub; namespace Friendica\Module\ActivityPub;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Protocol\ActivityPub; use Friendica\Protocol\ActivityPub;
use Friendica\Util\HTTPSignature; use Friendica\Util\HTTPSignature;
@ -46,8 +47,7 @@ class Outbox extends BaseModule
$requester = HTTPSignature::getSigner('', $_SERVER); $requester = HTTPSignature::getSigner('', $_SERVER);
$outbox = ActivityPub\Transmitter::getOutbox($owner, $page, $requester); $outbox = ActivityPub\Transmitter::getOutbox($owner, $page, $requester);
header('Content-Type: application/activity+json');
echo json_encode($outbox); System::jsonExit($outbox, 'application/activity+json');
exit();
} }
} }

View file

@ -22,6 +22,8 @@
namespace Friendica\Module\DFRN; namespace Friendica\Module\DFRN;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\Module\Response;
use Friendica\Protocol\OStatus; use Friendica\Protocol\OStatus;
/** /**
@ -31,9 +33,7 @@ class Poll extends BaseModule
{ {
protected function rawContent(array $request = []) protected function rawContent(array $request = [])
{ {
header("Content-type: application/atom+xml"); $last_update = $request['last_update'] ?? '';
$last_update = $_GET['last_update'] ?? ''; System::httpExit(OStatus::feed($this->parameters['nickname'], $last_update, 10), Response::TYPE_ATOM);
echo OStatus::feed($this->parameters['nickname'], $last_update, 10);
exit();
} }
} }

View file

@ -28,6 +28,7 @@ use Friendica\DI;
use Friendica\Model\Item; use Friendica\Model\Item;
use Friendica\Model\Post; use Friendica\Model\Post;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Module\Response;
use Friendica\Network\HTTPException; use Friendica\Network\HTTPException;
use Friendica\Protocol\Diaspora; use Friendica\Protocol\Diaspora;
use Friendica\Util\Strings; use Friendica\Util\Strings;
@ -84,9 +85,6 @@ class Fetch extends BaseModule
$xml = Diaspora::buildPostXml($status["type"], $status["message"]); $xml = Diaspora::buildPostXml($status["type"], $status["message"]);
// Send the envelope // Send the envelope
header("Content-Type: application/magic-envelope+xml; charset=utf-8"); System::httpExit(Diaspora::buildMagicEnvelope($xml, $user), Response::TYPE_XML, 'application/magic-envelope+xml');
echo Diaspora::buildMagicEnvelope($xml, $user);
exit();
} }
} }

View file

@ -21,6 +21,7 @@
namespace Friendica\Module\Events; namespace Friendica\Module\Events;
use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Event; use Friendica\Model\Event;
@ -94,9 +95,7 @@ class Json extends \Friendica\BaseModule
$events = self::map($events); $events = self::map($events);
} }
header('Content-Type: application/json'); System::jsonExit($events);
echo json_encode($events);
exit();
} }
private static function map(array $events): array private static function map(array $events): array

View file

@ -22,6 +22,7 @@
namespace Friendica\Module; namespace Friendica\Module;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\DI; use Friendica\DI;
use Friendica\Protocol\Feed as ProtocolFeed; use Friendica\Protocol\Feed as ProtocolFeed;
@ -43,10 +44,8 @@ class Feed extends BaseModule
{ {
protected function content(array $request = []): string protected function content(array $request = []): string
{ {
$a = DI::app(); $last_update = $request['last_update'] ?? '';
$nocache = !empty($request['nocache']) && local_user();
$last_update = $_GET['last_update'] ?? '';
$nocache = !empty($_GET['nocache']) && local_user();
$type = null; $type = null;
// @TODO: Replace with parameter from router // @TODO: Replace with parameter from router
@ -67,8 +66,6 @@ class Feed extends BaseModule
$type = 'posts'; $type = 'posts';
} }
header("Content-type: application/atom+xml; charset=utf-8"); System::httpExit(ProtocolFeed::atom($this->parameters['nickname'], $last_update, 10, $type, $nocache, true), Response::TYPE_ATOM);
echo ProtocolFeed::atom($this->parameters['nickname'], $last_update, 10, $type, $nocache, true);
exit();
} }
} }

View file

@ -182,8 +182,6 @@ class Friendica extends BaseModule
'no_scrape_url' => DI::baseUrl()->get() . '/noscrape', 'no_scrape_url' => DI::baseUrl()->get() . '/noscrape',
]; ];
header('Content-type: application/json; charset=utf-8'); System::jsonExit($data);
echo json_encode($data);
exit();
} }
} }

View file

@ -291,9 +291,7 @@ class Ping extends BaseModule
if (isset($_GET['callback'])) { if (isset($_GET['callback'])) {
// JSONP support // JSONP support
header("Content-type: application/javascript"); System::httpExit($_GET['callback'] . '(' . json_encode(['result' => $data]) . ')', Response::TYPE_BLANK, 'application/javascript');
echo $_GET['callback'] . '(' . json_encode(['result' => $data]) . ')';
exit;
} else { } else {
System::jsonExit(['result' => $data]); System::jsonExit(['result' => $data]);
} }

View file

@ -24,6 +24,7 @@ namespace Friendica\Module;
use DOMDocument; use DOMDocument;
use DOMElement; use DOMElement;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\DI; use Friendica\DI;
use Friendica\Util\XML; use Friendica\Util\XML;
@ -38,8 +39,6 @@ class OpenSearch extends BaseModule
*/ */
protected function rawContent(array $request = []) protected function rawContent(array $request = [])
{ {
header('Content-type: application/opensearchdescription+xml');
$hostname = DI::baseUrl()->getHostname(); $hostname = DI::baseUrl()->getHostname();
$baseUrl = DI::baseUrl()->get(); $baseUrl = DI::baseUrl()->get();
@ -85,8 +84,6 @@ class OpenSearch extends BaseModule
'template' => "$baseUrl/opensearch", 'template' => "$baseUrl/opensearch",
]); ]);
echo $xml->saveXML(); System::httpExit($xml->saveXML(), Response::TYPE_XML, 'application/opensearchdescription+xml');
exit();
} }
} }

View file

@ -88,8 +88,7 @@ class ParseUrl extends BaseModule
if ($format == 'json') { if ($format == 'json') {
System::jsonExit($arr['text']); System::jsonExit($arr['text']);
} else { } else {
echo $arr['text']; System::httpExit($arr['text']);
exit();
} }
} }
@ -122,8 +121,7 @@ class ParseUrl extends BaseModule
System::jsonExit($ret); System::jsonExit($ret);
} else { } else {
echo BBCode::embedURL($url, empty($_GET['noAttachment']), $title, $description, $_GET['tags'] ?? ''); System::httpExit(BBCode::embedURL($url, empty($_GET['noAttachment']), $title, $description, $_GET['tags'] ?? ''));
exit();
} }
} }
} }

View file

@ -22,6 +22,7 @@
namespace Friendica\Module; namespace Friendica\Module;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\User; use Friendica\Model\User;
use Friendica\Network\HTTPException\BadRequestException; use Friendica\Network\HTTPException\BadRequestException;
@ -48,9 +49,7 @@ class PublicRSAKey extends BaseModule
Crypto::pemToMe($user['spubkey'], $modulus, $exponent); Crypto::pemToMe($user['spubkey'], $modulus, $exponent);
header('Content-type: application/magic-public-key'); $content = 'RSA' . '.' . Strings::base64UrlEncode($modulus, true) . '.' . Strings::base64UrlEncode($exponent, true);
echo 'RSA' . '.' . Strings::base64UrlEncode($modulus, true) . '.' . Strings::base64UrlEncode($exponent, true); System::httpExit($content, Response::TYPE_BLANK, 'application/magic-public-key');
exit();
} }
} }

View file

@ -22,6 +22,7 @@
namespace Friendica\Module; namespace Friendica\Module;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\DI; use Friendica\DI;
use Friendica\Util\XML; use Friendica\Util\XML;
@ -33,10 +34,8 @@ class ReallySimpleDiscovery extends BaseModule
{ {
protected function rawContent(array $request = []) protected function rawContent(array $request = [])
{ {
header('Content-Type: text/xml');
$xml = null; $xml = null;
echo XML::fromArray([ $content = XML::fromArray([
'rsd' => [ 'rsd' => [
'@attributes' => [ '@attributes' => [
'version' => '1.0', 'version' => '1.0',
@ -69,6 +68,6 @@ class ReallySimpleDiscovery extends BaseModule
], ],
], ],
], $xml); ], $xml);
exit(); System::httpExit($content, Response::TYPE_XML);
} }
} }

View file

@ -97,7 +97,7 @@ class Response implements ICanCreateResponses
switch ($type) { switch ($type) {
case static::TYPE_HTML: case static::TYPE_HTML:
$content_type = $content_type ?? 'text/html'; $content_type = $content_type ?? 'text/html; charset=utf-8';
break; break;
case static::TYPE_JSON: case static::TYPE_JSON:
$content_type = $content_type ?? 'application/json'; $content_type = $content_type ?? 'application/json';

View file

@ -27,6 +27,7 @@ use Friendica\Core\Hook;
use Friendica\Core\Logger; use Friendica\Core\Logger;
use Friendica\Core\Protocol; use Friendica\Core\Protocol;
use Friendica\Core\Search; use Friendica\Core\Search;
use Friendica\Core\System;
use Friendica\Database\DBA; use Friendica\Database\DBA;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Contact; use Friendica\Model\Contact;
@ -61,8 +62,7 @@ class Acl extends BaseModule
$o = self::regularContactSearch($type); $o = self::regularContactSearch($type);
} }
echo json_encode($o); System::jsonExit($o);
exit;
} }
private static function globalContactSearch() private static function globalContactSearch()

View file

@ -74,7 +74,7 @@ class HTTPException
$content = Renderer::replaceMacros($tpl, self::getVars($e)); $content = Renderer::replaceMacros($tpl, self::getVars($e));
} }
System::httpExit($e->getCode(), $e->getDescription(), $content); System::httpError($e->getCode(), $e->getDescription(), $content);
} }
/** /**

View file

@ -26,6 +26,7 @@ use Friendica\BaseModule;
use Friendica\Core\Addon; use Friendica\Core\Addon;
use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Config\Capability\IManageConfigValues;
use Friendica\Core\L10n; use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Network\HTTPException\NotFoundException; use Friendica\Network\HTTPException\NotFoundException;
use Friendica\Util\Profiler; use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -78,9 +79,7 @@ class Statistics extends BaseModule
'services' => $services, 'services' => $services,
], $services); ], $services);
header("Content-Type: application/json");
echo json_encode($statistics, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
$this->logger->debug("statistics.", ['statistics' => $statistics]); $this->logger->debug("statistics.", ['statistics' => $statistics]);
exit(); System::jsonExit($statistics);
} }
} }

View file

@ -22,6 +22,7 @@
namespace Friendica\Module; namespace Friendica\Module;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\Core\Theme; use Friendica\Core\Theme;
/** /**
@ -40,7 +41,7 @@ class ThemeDetails extends BaseModule
$version = $info['version'] ?? ''; $version = $info['version'] ?? '';
$credits = $info['credits'] ?? ''; $credits = $info['credits'] ?? '';
echo json_encode([ System::jsonExit([
'img' => Theme::getScreenshot($theme), 'img' => Theme::getScreenshot($theme),
'desc' => $description, 'desc' => $description,
'version' => $version, 'version' => $version,

View file

@ -23,7 +23,9 @@ namespace Friendica\Module\WellKnown;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\DI; use Friendica\DI;
use Friendica\Module\Response;
use Friendica\Protocol\Salmon; use Friendica\Protocol\Salmon;
use Friendica\Util\Crypto; use Friendica\Util\Crypto;
@ -37,8 +39,6 @@ class HostMeta extends BaseModule
{ {
$config = DI::config(); $config = DI::config();
header('Content-type: text/xml');
if (!$config->get('system', 'site_pubkey', false)) { if (!$config->get('system', 'site_pubkey', false)) {
$res = Crypto::newKeypair(1024); $res = Crypto::newKeypair(1024);
@ -47,13 +47,13 @@ class HostMeta extends BaseModule
} }
$tpl = Renderer::getMarkupTemplate('xrd_host.tpl'); $tpl = Renderer::getMarkupTemplate('xrd_host.tpl');
echo Renderer::replaceMacros($tpl, [ $content = Renderer::replaceMacros($tpl, [
'$zhost' => DI::baseUrl()->getHostname(), '$zhost' => DI::baseUrl()->getHostname(),
'$zroot' => DI::baseUrl()->get(), '$zroot' => DI::baseUrl()->get(),
'$domain' => DI::baseUrl()->get(), '$domain' => DI::baseUrl()->get(),
'$bigkey' => Salmon::salmonKey($config->get('system', 'site_pubkey')) '$bigkey' => Salmon::salmonKey($config->get('system', 'site_pubkey'))
]); ]);
exit(); System::httpExit($content, Response::TYPE_XML, 'application/xrd+xml');
} }
} }

View file

@ -22,6 +22,7 @@
namespace Friendica\Module\WellKnown; namespace Friendica\Module\WellKnown;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\DI; use Friendica\DI;
/** /**
@ -51,8 +52,6 @@ class NodeInfo extends BaseModule
] ]
]; ];
header('Content-type: application/json; charset=utf-8'); System::jsonExit($nodeinfo);
echo json_encode($nodeinfo, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
exit;
} }
} }

View file

@ -22,6 +22,7 @@
namespace Friendica\Module\WellKnown; namespace Friendica\Module\WellKnown;
use Friendica\BaseModule; use Friendica\BaseModule;
use Friendica\Core\System;
use Friendica\DI; use Friendica\DI;
use Friendica\Model\Search; use Friendica\Model\Search;
use Friendica\Protocol\Relay; use Friendica\Protocol\Relay;
@ -76,8 +77,6 @@ class XSocialRelay extends BaseModule
$relay['protocols']['diaspora'] = ['receive' => DI::baseUrl()->get() . '/receive/public']; $relay['protocols']['diaspora'] = ['receive' => DI::baseUrl()->get() . '/receive/public'];
} }
header('Content-type: application/json; charset=utf-8'); System::jsonExit($relay);
echo json_encode($relay, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
exit;
} }
} }

View file

@ -46,9 +46,9 @@ class Xrd extends BaseModule
$uri = urldecode(trim($_GET['uri'])); $uri = urldecode(trim($_GET['uri']));
if (strpos($_SERVER['HTTP_ACCEPT'] ?? '', 'application/jrd+json') !== false) { if (strpos($_SERVER['HTTP_ACCEPT'] ?? '', 'application/jrd+json') !== false) {
$mode = 'json'; $mode = Response::TYPE_JSON;
} else { } else {
$mode = 'xml'; $mode = Response::TYPE_XML;
} }
} else { } else {
if (empty($_GET['resource'])) { if (empty($_GET['resource'])) {
@ -57,9 +57,9 @@ class Xrd extends BaseModule
$uri = urldecode(trim($_GET['resource'])); $uri = urldecode(trim($_GET['resource']));
if (strpos($_SERVER['HTTP_ACCEPT'] ?? '', 'application/xrd+xml') !== false) { if (strpos($_SERVER['HTTP_ACCEPT'] ?? '', 'application/xrd+xml') !== false) {
$mode = 'xml'; $mode = Response::TYPE_XML;
} else { } else {
$mode = 'json'; $mode = Response::TYPE_JSON;
} }
} }
@ -101,7 +101,7 @@ class Xrd extends BaseModule
$avatar = ['type' => 'image/jpeg']; $avatar = ['type' => 'image/jpeg'];
} }
if ($mode == 'xml') { if ($mode == Response::TYPE_JSON) {
self::printXML($alias, DI::baseUrl()->get(), $user, $owner, $avatar); self::printXML($alias, DI::baseUrl()->get(), $user, $owner, $avatar);
} else { } else {
self::printJSON($alias, DI::baseUrl()->get(), $owner, $avatar); self::printJSON($alias, DI::baseUrl()->get(), $owner, $avatar);
@ -238,9 +238,6 @@ class Xrd extends BaseModule
{ {
$salmon_key = Salmon::salmonKey($owner['spubkey']); $salmon_key = Salmon::salmonKey($owner['spubkey']);
header('Access-Control-Allow-Origin: *');
header('Content-type: text/xml');
$tpl = Renderer::getMarkupTemplate('xrd_person.tpl'); $tpl = Renderer::getMarkupTemplate('xrd_person.tpl');
$o = Renderer::replaceMacros($tpl, [ $o = Renderer::replaceMacros($tpl, [
@ -263,7 +260,8 @@ class Xrd extends BaseModule
$arr = ['user' => $user, 'xml' => $o]; $arr = ['user' => $user, 'xml' => $o];
Hook::callAll('personal_xrd', $arr); Hook::callAll('personal_xrd', $arr);
echo $arr['xml']; header('Access-Control-Allow-Origin: *');
exit();
System::httpExit($arr['xml'], Response::TYPE_XML, 'application/xrd+xml');
} }
} }

View file

@ -65,6 +65,10 @@ class ActivityPub
'diaspora' => 'https://diasporafoundation.org/ns/', 'diaspora' => 'https://diasporafoundation.org/ns/',
'litepub' => 'http://litepub.social/ns#', 'litepub' => 'http://litepub.social/ns#',
'toot' => 'http://joinmastodon.org/ns#', 'toot' => 'http://joinmastodon.org/ns#',
'featured' => [
"@id" => "toot:featured",
"@type" => "@id",
],
'schema' => 'http://schema.org#', 'schema' => 'http://schema.org#',
'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers', 'manuallyApprovesFollowers' => 'as:manuallyApprovesFollowers',
'sensitive' => 'as:sensitive', 'Hashtag' => 'as:Hashtag', 'sensitive' => 'as:sensitive', 'Hashtag' => 'as:Hashtag',

View file

@ -802,7 +802,7 @@ class Receiver
} }
$tempfile = tempnam(System::getTempPath(), $file); $tempfile = tempnam(System::getTempPath(), $file);
file_put_contents($tempfile, json_encode(['activity' => $activity, 'body' => $body, 'uid' => $uid, 'trust_source' => $trust_source, 'push' => $push, 'signer' => $signer, 'object_data' => $object_data], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); file_put_contents($tempfile, json_encode(['activity' => $activity, 'body' => $body, 'uid' => $uid, 'trust_source' => $trust_source, 'push' => $push, 'signer' => $signer, 'object_data' => $object_data], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
Logger::notice('Unknown activity stored', ['type' => $type, 'object_type' => $object_data['object_type'], $object_data['object_object_type'] ?? '', 'file' => $tempfile]); Logger::notice('Unknown activity stored', ['type' => $type, 'object_type' => $object_data['object_type'], $object_data['object_object_type'] ?? '', 'file' => $tempfile]);
} }

View file

@ -288,6 +288,69 @@ class Transmitter
return $data; return $data;
} }
/**
* Public posts for the given owner
*
* @param array $owner Owner array
* @param integer $page Page number
*
* @return array of posts
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function getFeatured($owner, $page = null)
{
$condition = ["`uri-id` IN (SELECT `uri-id` FROM `collection-view` WHERE `cid` = ? AND `type` = ?)",
Contact::getIdForURL($owner['url'], 0, false), Post\Collection::FEATURED];
$condition = DBA::mergeConditions($condition,
['uid' => $owner['uid'],
'author-id' => Contact::getIdForURL($owner['url'], 0, false),
'private' => [Item::PUBLIC, Item::UNLISTED],
'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT],
'network' => Protocol::FEDERATED,
'parent-network' => Protocol::FEDERATED,
'origin' => true,
'deleted' => false,
'visible' => true]);
$count = Post::count($condition);
$data = ['@context' => ActivityPub::CONTEXT];
$data['id'] = DI::baseUrl() . '/featured/' . $owner['nickname'];
$data['type'] = 'OrderedCollection';
$data['totalItems'] = $count;
if (empty($page)) {
$data['first'] = DI::baseUrl() . '/featured/' . $owner['nickname'] . '?page=1';
} else {
$data['type'] = 'OrderedCollectionPage';
$list = [];
$items = Post::select(['id'], $condition, ['limit' => [($page - 1) * 20, 20], 'order' => ['created' => true]]);
while ($item = Post::fetch($items)) {
$activity = self::createActivityFromItem($item['id'], true);
$activity['type'] = $activity['type'] == 'Update' ? 'Create' : $activity['type'];
// Only list "Create" activity objects here, no reshares
if (!empty($activity['object']) && ($activity['type'] == 'Create')) {
$list[] = $activity['object'];
}
}
DBA::close($items);
if (!empty($list)) {
$data['next'] = DI::baseUrl() . '/featured/' . $owner['nickname'] . '?page=' . ($page + 1);
}
$data['partOf'] = DI::baseUrl() . '/featured/' . $owner['nickname'];
$data['orderedItems'] = $list;
}
return $data;
}
/** /**
* Return the service array containing information the used software and it's url * Return the service array containing information the used software and it's url
* *
@ -330,6 +393,7 @@ class Transmitter
$data['followers'] = DI::baseUrl() . '/followers/' . $owner['nick']; $data['followers'] = DI::baseUrl() . '/followers/' . $owner['nick'];
$data['inbox'] = DI::baseUrl() . '/inbox/' . $owner['nick']; $data['inbox'] = DI::baseUrl() . '/inbox/' . $owner['nick'];
$data['outbox'] = DI::baseUrl() . '/outbox/' . $owner['nick']; $data['outbox'] = DI::baseUrl() . '/outbox/' . $owner['nick'];
$data['featured'] = DI::baseUrl() . '/featured/' . $owner['nick'];
} else { } else {
$data['inbox'] = DI::baseUrl() . '/friendica/inbox'; $data['inbox'] = DI::baseUrl() . '/friendica/inbox';
} }

View file

@ -363,6 +363,8 @@ return [
'/events/json' => [Module\Events\Json::class, [R::GET]], '/events/json' => [Module\Events\Json::class, [R::GET]],
'/featured/{nickname}' => [Module\ActivityPub\Featured::class, [R::GET]],
'/feed' => [ '/feed' => [
'/{nickname}' => [Module\Feed::class, [R::GET]], '/{nickname}' => [Module\Feed::class, [R::GET]],
'/{nickname}/posts' => [Module\Feed::class, [R::GET]], '/{nickname}/posts' => [Module\Feed::class, [R::GET]],

View file

@ -1,4 +1,3 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"> <XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
@ -31,4 +30,3 @@
type="text/html" type="text/html"
/> />
</XRD> </XRD>

View file

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<response> <response>
{{if $response.sorted}}<sorted>{{$response.sorted}}</sorted>{{/if}} {{if $response.sorted}}<sorted>{{$response.sorted}}</sorted>{{/if}}