X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fapi.php;h=8e89895ded26fb68eb8eeb71610536d4cd4732a4;hb=c18622caf999e2ddf7e2cda5bf4a50d6506c3931;hp=bcf14d6a829603e38054331a762f81bb08a46655;hpb=199f72ee3cd3c2ef7edfafa1d5a36a365bad93ad;p=friendica.git
diff --git a/include/api.php b/include/api.php
index bcf14d6a82..8e89895ded 100644
--- a/include/api.php
+++ b/include/api.php
@@ -1,6 +1,6 @@
user@server, ignoring server part
*
* @param App $a App
+ * @param bool $do_login try to log in when not logged in, otherwise quit silently
* @throws ForbiddenException
* @throws InternalServerErrorException
* @throws UnauthorizedException
@@ -186,8 +186,10 @@ function api_register_func($path, $func, $auth = false, $method = API_METHOD_ANY
* 'authenticated' => return status,
* 'user_record' => return authenticated user record
*/
-function api_login(App $a)
+function api_login(App $a, bool $do_login = true)
{
+ $_SESSION["allow_api"] = false;
+
// workaround for HTTP-auth in CGI mode
if (!empty($_SERVER['REDIRECT_REMOTE_USER'])) {
$userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6));
@@ -217,6 +219,10 @@ function api_login(App $a)
Logger::warning(API_LOG_PREFIX . 'OAuth error', ['module' => 'api', 'action' => 'login', 'exception' => $e->getMessage()]);
}
+ if (!$do_login) {
+ return;
+ }
+
Logger::debug(API_LOG_PREFIX . 'failed', ['module' => 'api', 'action' => 'login', 'parameters' => $_SERVER]);
header('WWW-Authenticate: Basic realm="Friendica"');
throw new UnauthorizedException("This API requires login");
@@ -248,7 +254,7 @@ function api_login(App $a)
*/
Hook::callAll('authenticate', $addon_auth);
- if ($addon_auth['authenticated'] && count($addon_auth['user_record'])) {
+ if ($addon_auth['authenticated'] && !empty($addon_auth['user_record'])) {
$record = $addon_auth['user_record'];
} else {
$user_id = User::authenticate(trim($user), trim($password), true);
@@ -258,6 +264,9 @@ function api_login(App $a)
}
if (!DBA::isResult($record)) {
+ if (!$do_login) {
+ return;
+ }
Logger::debug(API_LOG_PREFIX . 'failed', ['module' => 'api', 'action' => 'login', 'parameters' => $_SERVER]);
header('WWW-Authenticate: Basic realm="Friendica"');
//header('HTTP/1.0 401 Unauthorized');
@@ -1022,7 +1031,7 @@ function api_statuses_mediap($type)
$_REQUEST['profile_uid'] = api_user();
$_REQUEST['api_source'] = true;
- $txt = requestdata('status');
+ $txt = requestdata('status') ?? '';
/// @TODO old-lost code?
//$txt = urldecode(requestdata('status'));
@@ -1077,7 +1086,7 @@ function api_statuses_update($type)
// convert $_POST array items to the form we use for web posts.
if (requestdata('htmlstatus')) {
- $txt = requestdata('htmlstatus');
+ $txt = requestdata('htmlstatus') ?? '';
if ((strpos($txt, '<') !== false) || (strpos($txt, '>') !== false)) {
$txt = HTML::toBBCodeVideo($txt);
@@ -1119,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 `received` > ?", api_user(), $datefrom];
- $posts_day = DBA::count('thread', $condition);
+ $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, api_user(), $datefrom];
+ $posts_day = Post::count($condition);
if ($posts_day > $throttle_day) {
Logger::log('Daily posting limit reached for user '.api_user(), Logger::DEBUG);
@@ -1133,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 `received` > ?", api_user(), $datefrom];
- $posts_week = DBA::count('thread', $condition);
+ $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, api_user(), $datefrom];
+ $posts_week = Post::count($condition);
if ($posts_week > $throttle_week) {
Logger::log('Weekly posting limit reached for user '.api_user(), Logger::DEBUG);
@@ -1147,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 `received` > ?", api_user(), $datefrom];
- $posts_month = DBA::count('thread', $condition);
+ $condition = ["`gravity` = ? AND `uid` = ? AND `wall` AND `received` > ?", GRAVITY_PARENT, api_user(), $datefrom];
+ $posts_month = Post::count($condition);
if ($posts_month > $throttle_month) {
Logger::log('Monthly posting limit reached for user '.api_user(), Logger::DEBUG);
@@ -1158,30 +1167,56 @@ function api_statuses_update($type)
}
}
- if (!empty($_FILES['media'])) {
+ if (requestdata('media_ids')) {
+ $ids = explode(',', requestdata('media_ids') ?? '');
+ } elseif (!empty($_FILES['media'])) {
// upload the image if we have one
$picture = wall_upload_post($a, false);
if (is_array($picture)) {
- $_REQUEST['body'] .= "\n\n" . '[url=' . $picture["albumpage"] . '][img]' . $picture["preview"] . "[/img][/url]";
+ $ids[] = $picture['id'];
}
}
- if (requestdata('media_ids')) {
- $ids = explode(',', requestdata('media_ids'));
+ $attachments = [];
+ $ressources = [];
+
+ if (!empty($ids)) {
foreach ($ids as $id) {
- $r = q(
- "SELECT `resource-id`, `scale`, `nickname`, `type`, `desc` FROM `photo` INNER JOIN `user` ON `user`.`uid` = `photo`.`uid` WHERE `resource-id` IN (SELECT `resource-id` FROM `photo` WHERE `id` = %d) AND `scale` > 0 AND `photo`.`uid` = %d ORDER BY `photo`.`width` DESC LIMIT 1",
- intval($id),
- api_user()
- );
- if (DBA::isResult($r)) {
+ $media = DBA::toArray(DBA::p("SELECT `resource-id`, `scale`, `nickname`, `type`, `desc`, `filename`, `datasize`, `width`, `height` FROM `photo`
+ INNER JOIN `user` ON `user`.`uid` = `photo`.`uid` WHERE `resource-id` IN
+ (SELECT `resource-id` FROM `photo` WHERE `id` = ?) AND `photo`.`uid` = ?
+ ORDER BY `photo`.`width` DESC LIMIT 2", $id, api_user()));
+
+ if (!empty($media)) {
+ $ressources[] = $media[0]['resource-id'];
$phototypes = Images::supportedTypes();
- $ext = $phototypes[$r[0]['type']];
- $description = $r[0]['desc'] ?? '';
- $_REQUEST['body'] .= "\n\n" . '[url=' . DI::baseUrl() . '/photos/' . $r[0]['nickname'] . '/image/' . $r[0]['resource-id'] . ']';
- $_REQUEST['body'] .= '[img=' . DI::baseUrl() . '/photo/' . $r[0]['resource-id'] . '-' . $r[0]['scale'] . '.' . $ext . ']' . $description . '[/img][/url]';
+ $ext = $phototypes[$media[0]['type']];
+
+ $attachment = ['type' => Post\Media::IMAGE, 'mimetype' => $media[0]['type'],
+ 'url' => DI::baseUrl() . '/photo/' . $media[0]['resource-id'] . '-' . $media[0]['scale'] . '.' . $ext,
+ 'size' => $media[0]['datasize'],
+ 'name' => $media[0]['filename'] ?: $media[0]['resource-id'],
+ 'description' => $media[0]['desc'] ?? '',
+ 'width' => $media[0]['width'],
+ 'height' => $media[0]['height']];
+
+ if (count($media) > 1) {
+ $attachment['preview'] = DI::baseUrl() . '/photo/' . $media[1]['resource-id'] . '-' . $media[1]['scale'] . '.' . $ext;
+ $attachment['preview-width'] = $media[1]['width'];
+ $attachment['preview-height'] = $media[1]['height'];
+ }
+ $attachments[] = $attachment;
}
}
+
+ // We have to avoid that the post is rejected because of an empty body
+ if (empty($_REQUEST['body'])) {
+ $_REQUEST['body'] = '[hr]';
+ }
+ }
+
+ if (!empty($attachments)) {
+ $_REQUEST['attachments'] = $attachments;
}
// set this so that the item_post() function is quiet and doesn't redirect or emit json
@@ -1195,6 +1230,13 @@ function api_statuses_update($type)
// call out normal post function
$item_id = item_post($a);
+ if (!empty($ressources) && !empty($item_id)) {
+ $item = Post::selectFirst(['uri-id', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid'], ['id' => $item_id]);
+ foreach ($ressources as $ressource) {
+ Photo::setPermissionForRessource($ressource, api_user(), $item['allow_cid'], $item['allow_gid'], $item['deny_cid'], $item['deny_gid']);
+ }
+ }
+
// output the post that we just posted.
return api_status_show($type, $item_id);
}
@@ -1732,16 +1774,16 @@ function api_statuses_public_timeline($type)
$start = max(0, ($page - 1) * $count);
if ($exclude_replies && !$conversation_id) {
- $condition = ["`gravity` IN (?, ?) AND `iid` > ? AND `private` = ? AND `wall` AND NOT `author-hidden`",
- GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, Item::PUBLIC];
+ $condition = ["`gravity` = ? AND `id` > ? AND `private` = ? AND `wall` AND NOT `author-hidden`",
+ GRAVITY_PARENT, $since_id, Item::PUBLIC];
if ($max_id > 0) {
- $condition[0] .= " AND `iid` <= ?";
+ $condition[0] .= " AND `id` <= ?";
$condition[] = $max_id;
}
- $params = ['order' => ['iid' => true], 'limit' => [$start, $count]];
- $statuses = Post::selectThreadForUser(api_user(), Item::DISPLAY_FIELDLIST, $condition, $params);
+ $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
+ $statuses = Post::selectForUser(api_user(), [], $condition, $params);
$r = Post::toArray($statuses);
} else {
@@ -1811,18 +1853,18 @@ function api_statuses_networkpublic_timeline($type)
$start = max(0, ($page - 1) * $count);
- $condition = ["`uid` = 0 AND `gravity` IN (?, ?) AND `iid` > ? AND `private` = ?",
+ $condition = ["`uid` = 0 AND `gravity` IN (?, ?) AND `id` > ? AND `private` = ?",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, Item::PUBLIC];
if ($max_id > 0) {
- $condition[0] .= " AND `iid` <= ?";
+ $condition[0] .= " AND `id` <= ?";
$condition[] = $max_id;
}
- $params = ['order' => ['iid' => true], 'limit' => [$start, $count]];
- $statuses = Post::selectThreadForUser(api_user(), Item::DISPLAY_FIELDLIST, $condition, $params);
+ $params = ['order' => ['id' => true], 'limit' => [$start, $count]];
+ $statuses = Post::toArray(Post::selectForUser(api_user(), Item::DISPLAY_FIELDLIST, $condition, $params));
- $ret = api_format_items(Post::toArray($statuses), $user_info, false, $type);
+ $ret = api_format_items($statuses, $user_info, false, $type);
bindComments($ret);
@@ -2041,13 +2083,13 @@ function api_statuses_repeat($type)
$fields = ['uri-id', 'network', 'body', 'title', 'author-name', 'author-link', 'author-avatar', 'guid', 'created', 'plink'];
$item = Post::selectFirst($fields, ['id' => $id, 'private' => [Item::PUBLIC, Item::UNLISTED]]);
-
+
if (DBA::isResult($item) && !empty($item['body'])) {
if (in_array($item['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::TWITTER])) {
if (!Item::performActivity($id, 'announce', local_user())) {
throw new InternalServerErrorException();
}
-
+
$item_id = $id;
} else {
if (strpos($item['body'], "[/share]") !== false) {
@@ -2170,24 +2212,21 @@ function api_statuses_mentions($type)
$start = max(0, ($page - 1) * $count);
- $query = "`gravity` IN (?, ?) AND `id` IN (SELECT `iid` FROM `user-item`
- WHERE (`hidden` IS NULL OR NOT `hidden`) AND
- `uid` = ? AND `notification-type` & ? != 0
- AND `iid` > ?";
+ $query = "`gravity` IN (?, ?) AND `uri-id` IN
+ (SELECT `uri-id` FROM `post-user-notification` WHERE `uid` = ? AND `notification-type` & ? != 0 ORDER BY `uri-id`)
+ AND (`uid` = 0 OR (`uid` = ? AND NOT `global`)) AND `id` > ?";
$condition = [GRAVITY_PARENT, GRAVITY_COMMENT, api_user(),
- UserItem::NOTIF_EXPLICIT_TAGGED | UserItem::NOTIF_IMPLICIT_TAGGED |
- UserItem::NOTIF_THREAD_COMMENT | UserItem::NOTIF_DIRECT_COMMENT |
- UserItem::NOTIF_DIRECT_THREAD_COMMENT,
- $since_id];
+ Post\UserNotification::NOTIF_EXPLICIT_TAGGED | Post\UserNotification::NOTIF_IMPLICIT_TAGGED |
+ Post\UserNotification::NOTIF_THREAD_COMMENT | Post\UserNotification::NOTIF_DIRECT_COMMENT |
+ Post\UserNotification::NOTIF_DIRECT_THREAD_COMMENT,
+ api_user(), $since_id];
if ($max_id > 0) {
- $query .= " AND `iid` <= ?";
+ $query .= " AND `id` <= ?";
$condition[] = $max_id;
}
- $query .= ")";
-
array_unshift($condition, $query);
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
@@ -2266,7 +2305,6 @@ function api_statuses_user_timeline($type)
$condition[0] .= " AND `id` <= ?";
$condition[] = $max_id;
}
-
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$statuses = Post::selectForUser(api_user(), [], $condition, $params);
@@ -2513,7 +2551,8 @@ function api_format_messages($item, $recipient, $sender)
*/
function api_convert_item($item)
{
- $body = $item['body'];
+ $body = api_add_attachments_to_body($item);
+
$entities = api_get_entitities($statustext, $body);
// Add pictures to the attachment array and remove them from the body
@@ -2538,7 +2577,7 @@ function api_convert_item($item)
$statustext = mb_substr($statustext, 0, 1000) . "... \n" . ($item['plink'] ?? '');
}
- $statushtml = BBCode::convert(BBCode::removeAttachment($body), false);
+ $statushtml = BBCode::convert(BBCode::removeAttachment($body), false, BBCode::API, true);
// Workaround for clients with limited HTML parser functionality
$search = ["
", "
", "", @@ -2581,6 +2620,34 @@ function api_convert_item($item) ]; } +/** + * Add media attachments to the body + * + * @param array $item + * @return string body with added media + */ +function api_add_attachments_to_body(array $item) +{ + $body = Post\Media::addAttachmentsToBody($item['uri-id'], $item['body']); + + if (strpos($body, '[/img]') !== false) { + return $body; + } + + foreach (Post\Media::getByURIId($item['uri-id'], [Post\Media::HTML]) as $media) { + if (!empty($media['preview'])) { + $description = $media['description'] ?: $media['name']; + if (!empty($description)) { + $body .= "\n[img=" . $media['preview'] . ']' . $description .'[/img]'; + } else { + $body .= "\n[img]" . $media['preview'] .'[/img]'; + } + } + } + + return $body; +} + /** * * @param string $body @@ -2609,7 +2676,11 @@ function api_get_attachments(&$body) $imagedata = Images::getInfoFromURLCached($image); if ($imagedata) { - $attachments[] = ["url" => $image, "mimetype" => $imagedata["mime"], "size" => $imagedata["size"]]; + if (DI::config()->get("system", "proxy_disabled")) { + $attachments[] = ["url" => $image, "mimetype" => $imagedata["mime"], "size" => $imagedata["size"]]; + } else { + $attachments[] = ["url" => ProxyUtils::proxifyUrl($image, false), "mimetype" => $imagedata["mime"], "size" => $imagedata["size"]]; + } } } @@ -2633,7 +2704,7 @@ function api_get_entitities(&$text, $bbcode) preg_match_all("/\[img](.*?)\[\/img\]/ism", $bbcode, $images); foreach ($images[1] as $image) { - $replace = ProxyUtils::proxifyUrl($image); + $replace = ProxyUtils::proxifyUrl($image, false); $text = str_replace($image, $replace, $text); } return []; @@ -2748,7 +2819,7 @@ function api_get_entitities(&$text, $bbcode) // If image cache is activated, then use the following sizes: // thumb (150), small (340), medium (600) and large (1024) if (!DI::config()->get("system", "proxy_disabled")) { - $media_url = ProxyUtils::proxifyUrl($url); + $media_url = ProxyUtils::proxifyUrl($url, false); $sizes = []; $scale = Images::getScalingDimensions($image[0], $image[1], 150); @@ -2935,6 +3006,10 @@ function api_format_items($items, $user_info, $filter_user = false, $type = "jso $ret = []; + if (empty($items)) { + return $ret; + } + foreach ((array)$items as $item) { list($status_user, $author_user, $owner_user) = api_item_get_user($a, $item); @@ -4825,7 +4900,7 @@ function prepare_photo_data($type, $scale, $photo_id) "SELECT %s `resource-id`, `created`, `edited`, `title`, `desc`, `album`, `filename`, `type`, `height`, `width`, `datasize`, `profile`, `allow_cid`, `deny_cid`, `allow_gid`, `deny_gid`, MIN(`scale`) AS `minscale`, MAX(`scale`) AS `maxscale` - FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' %s GROUP BY + FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' %s GROUP BY `resource-id`, `created`, `edited`, `title`, `desc`, `album`, `filename`, `type`, `height`, `width`, `datasize`, `profile`, `allow_cid`, `deny_cid`, `allow_gid`, `deny_gid`", $data_sql, @@ -4873,7 +4948,7 @@ function prepare_photo_data($type, $scale, $photo_id) } // retrieve item element for getting activities (like, dislike etc.) related to photo - $condition = ['uid' => api_user(), 'resource-id' => $photo_id, 'type' => 'photo']; + $condition = ['uid' => api_user(), 'resource-id' => $photo_id]; $item = Post::selectFirst(['id', 'uid', 'uri', 'parent', 'allow_cid', 'deny_cid', 'allow_gid', 'deny_gid'], $condition); if (!DBA::isResult($item)) { throw new NotFoundException('Photo-related item not found.'); @@ -4882,7 +4957,7 @@ function prepare_photo_data($type, $scale, $photo_id) $data['photo']['friendica_activities'] = api_format_items_activities($item, $type); // retrieve comments on photo - $condition = ["`parent` = ? AND `uid` = ? AND (`gravity` IN (?, ?) OR `type`='photo')", + $condition = ["`parent` = ? AND `uid` = ? AND `gravity` IN (?, ?)", $item['parent'], api_user(), GRAVITY_PARENT, GRAVITY_COMMENT]; $statuses = Post::selectForUser(api_user(), [], $condition); @@ -5995,12 +6070,12 @@ api_register_func('api/saved_searches/list', 'api_saved_searches_list', true); * * @return void */ -function bindComments(&$data) +function bindComments(&$data) { if (count($data) == 0) { return; } - + $ids = []; $comments = []; foreach ($data as $item) { @@ -6008,7 +6083,7 @@ function bindComments(&$data) } $idStr = DBA::escape(implode(', ', $ids)); - $sql = "SELECT `parent`, COUNT(*) as comments FROM `post-view` WHERE `parent` IN ($idStr) AND `deleted` = ? AND `gravity`= ? GROUP BY `parent`"; + $sql = "SELECT `parent`, COUNT(*) as comments FROM `post-user-view` WHERE `parent` IN ($idStr) AND `deleted` = ? AND `gravity`= ? GROUP BY `parent`"; $items = DBA::p($sql, 0, GRAVITY_COMMENT); $itemsData = DBA::toArray($items);