Merge pull request #11028 from annando/fix-api

API: Fix profile_url handling / missing constant
This commit is contained in:
Hypolite Petovan 2021-11-26 08:52:55 -05:00 committed by GitHub
commit 3d77fd5e29
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 94 additions and 124 deletions

View file

@ -35,7 +35,6 @@ use Friendica\Model\Contact;
use Friendica\Model\Group; use Friendica\Model\Group;
use Friendica\Model\Item; use Friendica\Model\Item;
use Friendica\Model\Mail; use Friendica\Model\Mail;
use Friendica\Model\Notification;
use Friendica\Model\Photo; use Friendica\Model\Photo;
use Friendica\Model\Post; use Friendica\Model\Post;
use Friendica\Model\Profile; use Friendica\Model\Profile;
@ -49,7 +48,6 @@ use Friendica\Network\HTTPException\NotFoundException;
use Friendica\Network\HTTPException\TooManyRequestsException; use Friendica\Network\HTTPException\TooManyRequestsException;
use Friendica\Network\HTTPException\UnauthorizedException; use Friendica\Network\HTTPException\UnauthorizedException;
use Friendica\Object\Image; use Friendica\Object\Image;
use Friendica\Security\BasicAuth;
use Friendica\Util\DateTimeFormat; use Friendica\Util\DateTimeFormat;
use Friendica\Util\Images; use Friendica\Util\Images;
use Friendica\Util\Network; use Friendica\Util\Network;
@ -58,13 +56,6 @@ use Friendica\Util\Strings;
require_once __DIR__ . '/../mod/item.php'; require_once __DIR__ . '/../mod/item.php';
require_once __DIR__ . '/../mod/wall_upload.php'; require_once __DIR__ . '/../mod/wall_upload.php';
define('API_METHOD_ANY', '*');
define('API_METHOD_GET', 'GET');
define('API_METHOD_POST', 'POST,PUT');
define('API_METHOD_DELETE', 'POST,DELETE');
define('API_LOG_PREFIX', 'API {action} - ');
$API = []; $API = [];
/** /**
@ -72,19 +63,13 @@ $API = [];
* *
* @param string $path API URL path, relative to DI::baseUrl() * @param string $path API URL path, relative to DI::baseUrl()
* @param string $func Function name to call on path request * @param string $func Function name to call on path request
* @param bool $auth API need logged user
* @param string $method HTTP method reqiured to call this endpoint.
* One of API_METHOD_ANY, API_METHOD_GET, API_METHOD_POST.
* Default to API_METHOD_ANY
*/ */
function api_register_func($path, $func, $auth = false, $method = API_METHOD_ANY) function api_register_func($path, $func)
{ {
global $API; global $API;
$API[$path] = [ $API[$path] = [
'func' => $func, 'func' => $func,
'auth' => $auth,
'method' => $method,
]; ];
// Workaround for hotot // Workaround for hotot
@ -92,8 +77,6 @@ function api_register_func($path, $func, $auth = false, $method = API_METHOD_ANY
$API[$path] = [ $API[$path] = [
'func' => $func, 'func' => $func,
'auth' => $auth,
'method' => $method,
]; ];
} }
@ -102,50 +85,28 @@ function api_register_func($path, $func, $auth = false, $method = API_METHOD_ANY
* *
* Authenticate user, call registered API function, set HTTP headers * Authenticate user, call registered API function, set HTTP headers
* *
* @param App $a App
* @param App\Arguments $args The app arguments (optional, will retrieved by the DI-Container in case of missing) * @param App\Arguments $args The app arguments (optional, will retrieved by the DI-Container in case of missing)
* @return string|array API call result * @return string|array API call result
* @throws Exception * @throws Exception
*/ */
function api_call(App $a, App\Arguments $args = null) function api_call($command, $extension)
{ {
global $API; global $API;
if ($args == null) { Logger::info('Legacy API call', ['command' => $command, 'extension' => $extension]);
$args = DI::args();
}
$type = "json";
if (strpos($args->getCommand(), ".xml") > 0) {
$type = "xml";
}
if (strpos($args->getCommand(), ".json") > 0) {
$type = "json";
}
if (strpos($args->getCommand(), ".rss") > 0) {
$type = "rss";
}
if (strpos($args->getCommand(), ".atom") > 0) {
$type = "atom";
}
try { try {
foreach ($API as $p => $info) { foreach ($API as $p => $info) {
if (strpos($args->getCommand(), $p) === 0) { if (strpos($command, $p) === 0) {
if (!empty($info['auth']) && BaseApi::getCurrentUserID() === false) { Logger::debug(BaseApi::LOG_PREFIX . 'parameters', ['module' => 'api', 'action' => 'call', 'parameters' => $_REQUEST]);
BasicAuth::getCurrentUserID(true);
Logger::info(API_LOG_PREFIX . 'nickname {nickname}', ['module' => 'api', 'action' => 'call', 'nickname' => $a->getLoggedInUserNickname()]);
}
Logger::debug(API_LOG_PREFIX . 'parameters', ['module' => 'api', 'action' => 'call', 'parameters' => $_REQUEST]);
$stamp = microtime(true); $stamp = microtime(true);
$return = call_user_func($info['func'], $type); $return = call_user_func($info['func'], $extension);
$duration = floatval(microtime(true) - $stamp); $duration = floatval(microtime(true) - $stamp);
Logger::info(API_LOG_PREFIX . 'duration {duration}', ['module' => 'api', 'action' => 'call', 'duration' => round($duration, 2)]); Logger::info(BaseApi::LOG_PREFIX . 'duration {duration}', ['module' => 'api', 'action' => 'call', 'duration' => round($duration, 2)]);
DI::profiler()->saveLog(DI::logger(), API_LOG_PREFIX . 'performance'); DI::profiler()->saveLog(DI::logger(), BaseApi::LOG_PREFIX . 'performance');
if (false === $return) { if (false === $return) {
/* /*
@ -155,7 +116,7 @@ function api_call(App $a, App\Arguments $args = null)
throw new InternalServerErrorException(); throw new InternalServerErrorException();
} }
switch ($type) { switch ($extension) {
case "xml": case "xml":
header("Content-Type: text/xml"); header("Content-Type: text/xml");
break; break;
@ -182,11 +143,11 @@ function api_call(App $a, App\Arguments $args = null)
} }
} }
Logger::warning(API_LOG_PREFIX . 'not implemented', ['module' => 'api', 'action' => 'call', 'query' => DI::args()->getQueryString()]); Logger::warning(BaseApi::LOG_PREFIX . 'not implemented', ['module' => 'api', 'action' => 'call', 'query' => DI::args()->getQueryString()]);
throw new NotFoundException(); throw new NotFoundException();
} catch (HTTPException $e) { } catch (HTTPException $e) {
Logger::notice(API_LOG_PREFIX . 'got exception', ['module' => 'api', 'action' => 'call', 'query' => DI::args()->getQueryString(), 'error' => $e]); Logger::notice(BaseApi::LOG_PREFIX . 'got exception', ['module' => 'api', 'action' => 'call', 'query' => DI::args()->getQueryString(), 'error' => $e]);
DI::apiResponse()->error($e->getCode(), $e->getDescription(), $e->getMessage(), $type); DI::apiResponse()->error($e->getCode(), $e->getDescription(), $e->getMessage(), $extension);
} }
} }
@ -733,7 +694,7 @@ function api_statuses_mediap($type)
} }
/// @TODO move this to top of file or somewhere better! /// @TODO move this to top of file or somewhere better!
api_register_func('api/statuses/mediap', 'api_statuses_mediap', true, API_METHOD_POST); api_register_func('api/statuses/mediap', 'api_statuses_mediap', true);
/** /**
* Updates the users current status. * Updates the users current status.
@ -916,8 +877,8 @@ function api_statuses_update($type)
return DI::apiResponse()->formatData('statuses', $type, ['status' => $status_info]); return DI::apiResponse()->formatData('statuses', $type, ['status' => $status_info]);
} }
api_register_func('api/statuses/update', 'api_statuses_update', true, API_METHOD_POST); api_register_func('api/statuses/update', 'api_statuses_update', true);
api_register_func('api/statuses/update_with_media', 'api_statuses_update', true, API_METHOD_POST); api_register_func('api/statuses/update_with_media', 'api_statuses_update', true);
/** /**
* Uploads an image to Friendica. * Uploads an image to Friendica.
@ -959,7 +920,7 @@ function api_media_upload()
return ["media" => $returndata]; return ["media" => $returndata];
} }
api_register_func('api/media/upload', 'api_media_upload', true, API_METHOD_POST); api_register_func('api/media/upload', 'api_media_upload', true);
/** /**
* Updates media meta data (picture descriptions) * Updates media meta data (picture descriptions)
@ -1012,7 +973,7 @@ function api_media_metadata_create($type)
DBA::update('photo', ['desc' => $data['alt_text']['text']], ['resource-id' => $photo['resource-id']]); DBA::update('photo', ['desc' => $data['alt_text']['text']], ['resource-id' => $photo['resource-id']]);
} }
api_register_func('api/media/metadata/create', 'api_media_metadata_create', true, API_METHOD_POST); api_register_func('api/media/metadata/create', 'api_media_metadata_create', true);
/** /**
* Repeats a status. * Repeats a status.
@ -1091,7 +1052,7 @@ function api_statuses_repeat($type)
return DI::apiResponse()->formatData('statuses', $type, ['status' => $status_info]); return DI::apiResponse()->formatData('statuses', $type, ['status' => $status_info]);
} }
api_register_func('api/statuses/retweet', 'api_statuses_repeat', true, API_METHOD_POST); api_register_func('api/statuses/retweet', 'api_statuses_repeat', true);
/** /**
* Star/unstar an item. * Star/unstar an item.
@ -1159,8 +1120,8 @@ function api_favorites_create_destroy($type)
return DI::apiResponse()->formatData("status", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid)); return DI::apiResponse()->formatData("status", $type, ['status' => $ret], Contact::getPublicIdByUserId($uid));
} }
api_register_func('api/favorites/create', 'api_favorites_create_destroy', true, API_METHOD_POST); api_register_func('api/favorites/create', 'api_favorites_create_destroy', true);
api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true, API_METHOD_DELETE); api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true);
/** /**
* Returns all lists the user subscribes to. * Returns all lists the user subscribes to.
@ -1172,6 +1133,7 @@ api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true,
*/ */
function api_lists_list($type) function api_lists_list($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$ret = []; $ret = [];
/// @TODO $ret is not filled here? /// @TODO $ret is not filled here?
return DI::apiResponse()->formatData('lists', $type, ["lists_list" => $ret]); return DI::apiResponse()->formatData('lists', $type, ["lists_list" => $ret]);
@ -1316,6 +1278,7 @@ function api_statuses_f($qtype)
*/ */
function api_statuses_friends($type) function api_statuses_friends($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$data = api_statuses_f("friends"); $data = api_statuses_f("friends");
if ($data === false) { if ($data === false) {
return false; return false;
@ -1337,6 +1300,7 @@ api_register_func('api/statuses/friends', 'api_statuses_friends', true);
*/ */
function api_statuses_followers($type) function api_statuses_followers($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$data = api_statuses_f("followers"); $data = api_statuses_f("followers");
if ($data === false) { if ($data === false) {
return false; return false;
@ -1359,6 +1323,7 @@ api_register_func('api/statuses/followers', 'api_statuses_followers', true);
*/ */
function api_blocks_list($type) function api_blocks_list($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$data = api_statuses_f('blocks'); $data = api_statuses_f('blocks');
if ($data === false) { if ($data === false) {
return false; return false;
@ -1381,6 +1346,7 @@ api_register_func('api/blocks/list', 'api_blocks_list', true);
*/ */
function api_friendships_incoming($type) function api_friendships_incoming($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$data = api_statuses_f('incoming'); $data = api_statuses_f('incoming');
if ($data === false) { if ($data === false) {
return false; return false;
@ -1415,13 +1381,13 @@ function api_direct_messages_new($type)
BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE);
$uid = BaseApi::getCurrentUserID(); $uid = BaseApi::getCurrentUserID();
if (empty($_POST["text"]) || empty($_POST['screen_name']) && empty($_POST['user_id'])) { if (empty($_POST["text"]) || empty($_REQUEST['screen_name']) && empty($_REQUEST['user_id'])) {
return; return;
} }
$sender = DI::twitterUser()->createFromUserId($uid, true)->toArray(); $sender = DI::twitterUser()->createFromUserId($uid, true)->toArray();
$cid = BaseApi::getContactIDForSearchterm($_POST['screen_name'] ?? '', $_POST['user_id'] ?? 0, $uid); $cid = BaseApi::getContactIDForSearchterm($_REQUEST['screen_name'] ?? '', $_REQUEST['profileurl'] ?? '', $_REQUEST['user_id'] ?? 0, 0);
if (empty($cid)) { if (empty($cid)) {
throw new NotFoundException('Recipient not found'); throw new NotFoundException('Recipient not found');
} }
@ -1453,7 +1419,7 @@ function api_direct_messages_new($type)
return DI::apiResponse()->formatData("direct-messages", $type, ['direct_message' => $ret], Contact::getPublicIdByUserId($uid)); return DI::apiResponse()->formatData("direct-messages", $type, ['direct_message' => $ret], Contact::getPublicIdByUserId($uid));
} }
api_register_func('api/direct_messages/new', 'api_direct_messages_new', true, API_METHOD_POST); api_register_func('api/direct_messages/new', 'api_direct_messages_new', true);
/** /**
* delete a direct_message from mail table through api * delete a direct_message from mail table through api
@ -1519,7 +1485,7 @@ function api_direct_messages_destroy($type)
/// @todo return JSON data like Twitter API not yet implemented /// @todo return JSON data like Twitter API not yet implemented
} }
api_register_func('api/direct_messages/destroy', 'api_direct_messages_destroy', true, API_METHOD_DELETE); api_register_func('api/direct_messages/destroy', 'api_direct_messages_destroy', true);
/** /**
* Unfollow Contact * Unfollow Contact
@ -1540,14 +1506,14 @@ function api_friendships_destroy($type)
$owner = User::getOwnerDataById($uid); $owner = User::getOwnerDataById($uid);
if (!$owner) { if (!$owner) {
Logger::notice(API_LOG_PREFIX . 'No owner {uid} found', ['module' => 'api', 'action' => 'friendships_destroy', 'uid' => $uid]); Logger::notice(BaseApi::LOG_PREFIX . 'No owner {uid} found', ['module' => 'api', 'action' => 'friendships_destroy', 'uid' => $uid]);
throw new HTTPException\NotFoundException('Error Processing Request'); throw new HTTPException\NotFoundException('Error Processing Request');
} }
$contact_id = $_REQUEST['user_id'] ?? 0; $contact_id = $_REQUEST['user_id'] ?? 0;
if (empty($contact_id)) { if (empty($contact_id)) {
Logger::notice(API_LOG_PREFIX . 'No user_id specified', ['module' => 'api', 'action' => 'friendships_destroy']); Logger::notice(BaseApi::LOG_PREFIX . 'No user_id specified', ['module' => 'api', 'action' => 'friendships_destroy']);
throw new HTTPException\BadRequestException('no user_id specified'); throw new HTTPException\BadRequestException('no user_id specified');
} }
@ -1555,7 +1521,7 @@ function api_friendships_destroy($type)
$contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id, 'uid' => 0, 'self' => false]); $contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id, 'uid' => 0, 'self' => false]);
if(!DBA::isResult($contact)) { if(!DBA::isResult($contact)) {
Logger::notice(API_LOG_PREFIX . 'No public contact found for ID {contact}', ['module' => 'api', 'action' => 'friendships_destroy', 'contact' => $contact_id]); Logger::notice(BaseApi::LOG_PREFIX . 'No public contact found for ID {contact}', ['module' => 'api', 'action' => 'friendships_destroy', 'contact' => $contact_id]);
throw new HTTPException\NotFoundException('no contact found to given ID'); throw new HTTPException\NotFoundException('no contact found to given ID');
} }
@ -1567,7 +1533,7 @@ function api_friendships_destroy($type)
$contact = DBA::selectFirst('contact', [], $condition); $contact = DBA::selectFirst('contact', [], $condition);
if (!DBA::isResult($contact)) { if (!DBA::isResult($contact)) {
Logger::notice(API_LOG_PREFIX . 'Not following contact', ['module' => 'api', 'action' => 'friendships_destroy']); Logger::notice(BaseApi::LOG_PREFIX . 'Not following contact', ['module' => 'api', 'action' => 'friendships_destroy']);
throw new HTTPException\NotFoundException('Not following Contact'); throw new HTTPException\NotFoundException('Not following Contact');
} }
@ -1575,7 +1541,7 @@ function api_friendships_destroy($type)
$result = Contact::terminateFriendship($owner, $contact); $result = Contact::terminateFriendship($owner, $contact);
if ($result === null) { if ($result === null) {
Logger::notice(API_LOG_PREFIX . 'Not supported for {network}', ['module' => 'api', 'action' => 'friendships_destroy', 'network' => $contact['network']]); Logger::notice(BaseApi::LOG_PREFIX . 'Not supported for {network}', ['module' => 'api', 'action' => 'friendships_destroy', 'network' => $contact['network']]);
throw new HTTPException\ExpectationFailedException('Unfollowing is currently not supported by this contact\'s network.'); throw new HTTPException\ExpectationFailedException('Unfollowing is currently not supported by this contact\'s network.');
} }
@ -1583,7 +1549,7 @@ function api_friendships_destroy($type)
throw new HTTPException\ServiceUnavailableException('Unable to unfollow this contact, please retry in a few minutes or contact your administrator.'); throw new HTTPException\ServiceUnavailableException('Unable to unfollow this contact, please retry in a few minutes or contact your administrator.');
} }
} catch (Exception $e) { } catch (Exception $e) {
Logger::error(API_LOG_PREFIX . $e->getMessage(), ['owner' => $owner, 'contact' => $contact]); Logger::error(BaseApi::LOG_PREFIX . $e->getMessage(), ['owner' => $owner, 'contact' => $contact]);
throw new HTTPException\InternalServerErrorException('Unable to unfollow this contact, please contact your administrator'); throw new HTTPException\InternalServerErrorException('Unable to unfollow this contact, please contact your administrator');
} }
@ -1596,7 +1562,7 @@ function api_friendships_destroy($type)
return DI::apiResponse()->formatData('friendships-destroy', $type, ['user' => $contact]); return DI::apiResponse()->formatData('friendships-destroy', $type, ['user' => $contact]);
} }
api_register_func('api/friendships/destroy', 'api_friendships_destroy', true, API_METHOD_POST); api_register_func('api/friendships/destroy', 'api_friendships_destroy', true);
/** /**
* *
@ -1698,6 +1664,7 @@ function api_direct_messages_box($type, $box, $verbose)
*/ */
function api_direct_messages_sentbox($type) function api_direct_messages_sentbox($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$verbose = !empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false"; $verbose = !empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false";
return api_direct_messages_box($type, "sentbox", $verbose); return api_direct_messages_box($type, "sentbox", $verbose);
} }
@ -1716,6 +1683,7 @@ api_register_func('api/direct_messages/sent', 'api_direct_messages_sentbox', tru
*/ */
function api_direct_messages_inbox($type) function api_direct_messages_inbox($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$verbose = !empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false"; $verbose = !empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false";
return api_direct_messages_box($type, "inbox", $verbose); return api_direct_messages_box($type, "inbox", $verbose);
} }
@ -1732,6 +1700,7 @@ api_register_func('api/direct_messages', 'api_direct_messages_inbox', true);
*/ */
function api_direct_messages_all($type) function api_direct_messages_all($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$verbose = !empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false"; $verbose = !empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false";
return api_direct_messages_box($type, "all", $verbose); return api_direct_messages_box($type, "all", $verbose);
} }
@ -1748,6 +1717,7 @@ api_register_func('api/direct_messages/all', 'api_direct_messages_all', true);
*/ */
function api_direct_messages_conversation($type) function api_direct_messages_conversation($type)
{ {
BaseApi::checkAllowedScope(BaseApi::SCOPE_READ);
$verbose = !empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false"; $verbose = !empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false";
return api_direct_messages_box($type, "conversation", $verbose); return api_direct_messages_box($type, "conversation", $verbose);
} }
@ -1943,8 +1913,8 @@ function api_fr_photo_create_update($type)
throw new InternalServerErrorException("unknown error - this error on uploading or updating a photo should never happen"); throw new InternalServerErrorException("unknown error - this error on uploading or updating a photo should never happen");
} }
api_register_func('api/friendica/photo/create', 'api_fr_photo_create_update', true, API_METHOD_POST); api_register_func('api/friendica/photo/create', 'api_fr_photo_create_update', true);
api_register_func('api/friendica/photo/update', 'api_fr_photo_create_update', true, API_METHOD_POST); api_register_func('api/friendica/photo/update', 'api_fr_photo_create_update', true);
/** /**
* returns the details of a specified photo id, if scale is given, returns the photo data in base 64 * returns the details of a specified photo id, if scale is given, returns the photo data in base 64
@ -2072,7 +2042,7 @@ function api_account_update_profile_image($type)
} }
} }
api_register_func('api/account/update_profile_image', 'api_account_update_profile_image', true, API_METHOD_POST); api_register_func('api/account/update_profile_image', 'api_account_update_profile_image', true);
/** /**
* Return all or a specified group of the user with the containing contacts. * Return all or a specified group of the user with the containing contacts.
@ -2178,7 +2148,7 @@ function api_lists_destroy($type)
} }
} }
api_register_func('api/lists/destroy', 'api_lists_destroy', true, API_METHOD_DELETE); api_register_func('api/lists/destroy', 'api_lists_destroy', true);
/** /**
* Create the specified group with the posted array of contacts. * Create the specified group with the posted array of contacts.
@ -2207,7 +2177,7 @@ function api_friendica_group_create($type)
return DI::apiResponse()->formatData("group_create", $type, ['result' => $success]); return DI::apiResponse()->formatData("group_create", $type, ['result' => $success]);
} }
api_register_func('api/friendica/group_create', 'api_friendica_group_create', true, API_METHOD_POST); api_register_func('api/friendica/group_create', 'api_friendica_group_create', true);
/** /**
* Create a new group. * Create a new group.
@ -2243,7 +2213,7 @@ function api_lists_create($type)
} }
} }
api_register_func('api/lists/create', 'api_lists_create', true, API_METHOD_POST); api_register_func('api/lists/create', 'api_lists_create', true);
/** /**
* Update the specified group with the posted array of contacts. * Update the specified group with the posted array of contacts.
@ -2311,7 +2281,7 @@ function api_friendica_group_update($type)
return DI::apiResponse()->formatData("group_update", $type, ['result' => $success]); return DI::apiResponse()->formatData("group_update", $type, ['result' => $success]);
} }
api_register_func('api/friendica/group_update', 'api_friendica_group_update', true, API_METHOD_POST); api_register_func('api/friendica/group_update', 'api_friendica_group_update', true);
/** /**
* Update information about a group. * Update information about a group.
@ -2359,7 +2329,7 @@ function api_lists_update($type)
} }
} }
api_register_func('api/lists/update', 'api_lists_update', true, API_METHOD_POST); api_register_func('api/lists/update', 'api_lists_update', true);
/** /**
* search for direct_messages containing a searchstring through api * search for direct_messages containing a searchstring through api

View file

@ -44,7 +44,7 @@ class Index extends BaseApi
public function rawContent() public function rawContent()
{ {
echo api_call(DI::app()); echo api_call(DI::args()->getCommand(), $this->parameters['extension'] ?? 'json');
exit(); exit();
} }
} }

View file

@ -52,7 +52,7 @@ class Conversation extends BaseApi
$id = $_REQUEST['id'] ?? 0; $id = $_REQUEST['id'] ?? 0;
} }
Logger::info(API_LOG_PREFIX . '{subaction}', ['module' => 'api', 'action' => 'conversation', 'subaction' => 'show', 'id' => $id]); Logger::info(BaseApi::LOG_PREFIX . '{subaction}', ['module' => 'api', 'action' => 'conversation', 'subaction' => 'show', 'id' => $id]);
// try to fetch the item for the local user - or the public item, if there is no local one // try to fetch the item for the local user - or the public item, if there is no local one
$item = Post::selectFirst(['parent-uri-id'], ['id' => $id]); $item = Post::selectFirst(['parent-uri-id'], ['id' => $id]);

View file

@ -42,7 +42,7 @@ class Favorites extends BaseApi
// in friendica starred item are private // in friendica starred item are private
// return favorites only for self // return favorites only for self
Logger::info(API_LOG_PREFIX . 'for {self}', ['module' => 'api', 'action' => 'favorites']); Logger::info(BaseApi::LOG_PREFIX . 'for {self}', ['module' => 'api', 'action' => 'favorites']);
// params // params
$since_id = $_REQUEST['since_id'] ?? 0; $since_id = $_REQUEST['since_id'] ?? 0;

View file

@ -39,6 +39,7 @@ class Ids extends ContactEndpoint
// Expected value for user_id parameter: public/user contact id // Expected value for user_id parameter: public/user contact id
$contact_id = filter_input(INPUT_GET, 'user_id' , FILTER_VALIDATE_INT); $contact_id = filter_input(INPUT_GET, 'user_id' , FILTER_VALIDATE_INT);
$screen_name = filter_input(INPUT_GET, 'screen_name'); $screen_name = filter_input(INPUT_GET, 'screen_name');
$profile_url = filter_input(INPUT_GET, 'profile_url');
$cursor = filter_input(INPUT_GET, 'cursor' , FILTER_VALIDATE_INT, ['options' => ['default' => -1]]); $cursor = filter_input(INPUT_GET, 'cursor' , FILTER_VALIDATE_INT, ['options' => ['default' => -1]]);
$stringify_ids = filter_input(INPUT_GET, 'stringify_ids', FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]); $stringify_ids = filter_input(INPUT_GET, 'stringify_ids', FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]);
$count = filter_input(INPUT_GET, 'count' , FILTER_VALIDATE_INT, ['options' => [ $count = filter_input(INPUT_GET, 'count' , FILTER_VALIDATE_INT, ['options' => [
@ -51,7 +52,7 @@ class Ids extends ContactEndpoint
$max_id = filter_input(INPUT_GET, 'max_id' , FILTER_VALIDATE_INT); $max_id = filter_input(INPUT_GET, 'max_id' , FILTER_VALIDATE_INT);
$min_id = filter_input(INPUT_GET, 'min_id' , FILTER_VALIDATE_INT); $min_id = filter_input(INPUT_GET, 'min_id' , FILTER_VALIDATE_INT);
$cid = BaseApi::getContactIDForSearchterm($screen_name, $contact_id, $uid); $cid = BaseApi::getContactIDForSearchterm($screen_name, $profile_url, $contact_id, $uid);
$params = ['order' => ['relation-cid' => true], 'limit' => $count]; $params = ['order' => ['relation-cid' => true], 'limit' => $count];

View file

@ -39,6 +39,7 @@ class Lists extends ContactEndpoint
// Expected value for user_id parameter: public/user contact id // Expected value for user_id parameter: public/user contact id
$contact_id = filter_input(INPUT_GET, 'user_id' , FILTER_VALIDATE_INT); $contact_id = filter_input(INPUT_GET, 'user_id' , FILTER_VALIDATE_INT);
$screen_name = filter_input(INPUT_GET, 'screen_name'); $screen_name = filter_input(INPUT_GET, 'screen_name');
$profile_url = filter_input(INPUT_GET, 'profile_url');
$cursor = filter_input(INPUT_GET, 'cursor' , FILTER_VALIDATE_INT, ['options' => ['default' => -1]]); $cursor = filter_input(INPUT_GET, 'cursor' , FILTER_VALIDATE_INT, ['options' => ['default' => -1]]);
$skip_status = filter_input(INPUT_GET, 'skip_status' , FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]); $skip_status = filter_input(INPUT_GET, 'skip_status' , FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]);
$include_user_entities = filter_input(INPUT_GET, 'include_user_entities', FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]); $include_user_entities = filter_input(INPUT_GET, 'include_user_entities', FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]);
@ -52,7 +53,7 @@ class Lists extends ContactEndpoint
$max_id = filter_input(INPUT_GET, 'max_id' , FILTER_VALIDATE_INT); $max_id = filter_input(INPUT_GET, 'max_id' , FILTER_VALIDATE_INT);
$min_id = filter_input(INPUT_GET, 'min_id' , FILTER_VALIDATE_INT); $min_id = filter_input(INPUT_GET, 'min_id' , FILTER_VALIDATE_INT);
$cid = BaseApi::getContactIDForSearchterm($screen_name, $contact_id, $uid); $cid = BaseApi::getContactIDForSearchterm($screen_name, $profile_url, $contact_id, $uid);
$params = ['order' => ['relation-cid' => true], 'limit' => $count]; $params = ['order' => ['relation-cid' => true], 'limit' => $count];

View file

@ -39,6 +39,7 @@ class Ids extends ContactEndpoint
// Expected value for user_id parameter: public/user contact id // Expected value for user_id parameter: public/user contact id
$contact_id = filter_input(INPUT_GET, 'user_id' , FILTER_VALIDATE_INT); $contact_id = filter_input(INPUT_GET, 'user_id' , FILTER_VALIDATE_INT);
$screen_name = filter_input(INPUT_GET, 'screen_name'); $screen_name = filter_input(INPUT_GET, 'screen_name');
$profile_url = filter_input(INPUT_GET, 'profile_url');
$cursor = filter_input(INPUT_GET, 'cursor' , FILTER_VALIDATE_INT, ['options' => ['default' => -1]]); $cursor = filter_input(INPUT_GET, 'cursor' , FILTER_VALIDATE_INT, ['options' => ['default' => -1]]);
$stringify_ids = filter_input(INPUT_GET, 'stringify_ids', FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]); $stringify_ids = filter_input(INPUT_GET, 'stringify_ids', FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]);
$count = filter_input(INPUT_GET, 'count' , FILTER_VALIDATE_INT, ['options' => [ $count = filter_input(INPUT_GET, 'count' , FILTER_VALIDATE_INT, ['options' => [
@ -51,7 +52,7 @@ class Ids extends ContactEndpoint
$max_id = filter_input(INPUT_GET, 'max_id' , FILTER_VALIDATE_INT); $max_id = filter_input(INPUT_GET, 'max_id' , FILTER_VALIDATE_INT);
$min_id = filter_input(INPUT_GET, 'min_id' , FILTER_VALIDATE_INT); $min_id = filter_input(INPUT_GET, 'min_id' , FILTER_VALIDATE_INT);
$cid = BaseApi::getContactIDForSearchterm($screen_name, $contact_id, $uid); $cid = BaseApi::getContactIDForSearchterm($screen_name, $profile_url, $contact_id, $uid);
$params = ['order' => ['cid' => true], 'limit' => $count]; $params = ['order' => ['cid' => true], 'limit' => $count];

View file

@ -39,6 +39,7 @@ class Lists extends ContactEndpoint
// Expected value for user_id parameter: public/user contact id // Expected value for user_id parameter: public/user contact id
$contact_id = filter_input(INPUT_GET, 'user_id' , FILTER_VALIDATE_INT); $contact_id = filter_input(INPUT_GET, 'user_id' , FILTER_VALIDATE_INT);
$screen_name = filter_input(INPUT_GET, 'screen_name'); $screen_name = filter_input(INPUT_GET, 'screen_name');
$profile_url = filter_input(INPUT_GET, 'profile_url');
$cursor = filter_input(INPUT_GET, 'cursor' , FILTER_VALIDATE_INT, ['options' => ['default' => -1]]); $cursor = filter_input(INPUT_GET, 'cursor' , FILTER_VALIDATE_INT, ['options' => ['default' => -1]]);
$skip_status = filter_input(INPUT_GET, 'skip_status' , FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]); $skip_status = filter_input(INPUT_GET, 'skip_status' , FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]);
$include_user_entities = filter_input(INPUT_GET, 'include_user_entities', FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]); $include_user_entities = filter_input(INPUT_GET, 'include_user_entities', FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]);
@ -52,7 +53,7 @@ class Lists extends ContactEndpoint
$max_id = filter_input(INPUT_GET, 'max_id' , FILTER_VALIDATE_INT); $max_id = filter_input(INPUT_GET, 'max_id' , FILTER_VALIDATE_INT);
$min_id = filter_input(INPUT_GET, 'min_id' , FILTER_VALIDATE_INT); $min_id = filter_input(INPUT_GET, 'min_id' , FILTER_VALIDATE_INT);
$cid = BaseApi::getContactIDForSearchterm($screen_name, $contact_id, $uid); $cid = BaseApi::getContactIDForSearchterm($screen_name, $profile_url, $contact_id, $uid);
$params = ['order' => ['cid' => true], 'limit' => $count]; $params = ['order' => ['cid' => true], 'limit' => $count];

View file

@ -42,7 +42,7 @@ class UserTimeline extends BaseApi
Logger::info('api_statuses_user_timeline', ['api_user' => $uid, '_REQUEST' => $_REQUEST]); Logger::info('api_statuses_user_timeline', ['api_user' => $uid, '_REQUEST' => $_REQUEST]);
$cid = BaseApi::getContactIDForSearchterm($_REQUEST['screen_name'] ?? '', $_REQUEST['user_id'] ?? 0, $uid); $cid = BaseApi::getContactIDForSearchterm($_REQUEST['screen_name'] ?? '', $_REQUEST['profileurl'] ?? '', $_REQUEST['user_id'] ?? 0, $uid);
$since_id = $_REQUEST['since_id'] ?? 0; $since_id = $_REQUEST['since_id'] ?? 0;
$max_id = $_REQUEST['max_id'] ?? 0; $max_id = $_REQUEST['max_id'] ?? 0;
$exclude_replies = !empty($_REQUEST['exclude_replies']); $exclude_replies = !empty($_REQUEST['exclude_replies']);

View file

@ -38,7 +38,7 @@ class Show extends BaseApi
$uid = BaseApi::getCurrentUserID(); $uid = BaseApi::getCurrentUserID();
if (empty($this->parameters['id'])) { if (empty($this->parameters['id'])) {
$cid = BaseApi::getContactIDForSearchterm($_REQUEST['screen_name'] ?? '', $_REQUEST['user_id'] ?? 0, $uid); $cid = BaseApi::getContactIDForSearchterm($_REQUEST['screen_name'] ?? '', $_REQUEST['profileurl'] ?? '', $_REQUEST['user_id'] ?? 0, $uid);
} else { } else {
$cid = (int)$this->parameters['id']; $cid = (int)$this->parameters['id'];
} }

View file

@ -36,6 +36,8 @@ use Friendica\Util\HTTPInputData;
class BaseApi extends BaseModule class BaseApi extends BaseModule
{ {
const LOG_PREFIX = 'API {action} - ';
const SCOPE_READ = 'read'; const SCOPE_READ = 'read';
const SCOPE_WRITE = 'write'; const SCOPE_WRITE = 'write';
const SCOPE_FOLLOW = 'follow'; const SCOPE_FOLLOW = 'follow';
@ -293,25 +295,31 @@ class BaseApi extends BaseModule
} }
} }
public static function getContactIDForSearchterm(string $screen_name = null, int $cid = null, int $uid) public static function getContactIDForSearchterm(string $screen_name = null, string $profileurl = null, int $cid = null, int $uid)
{ {
if (!empty($cid)) { if (!empty($cid)) {
return $cid; return $cid;
} }
if (strpos($screen_name, '@') !== false) { if (!empty($profileurl)) {
$cid = Contact::getIdForURL($screen_name, 0, false); return Contact::getIdForURL($profileurl);
} else { }
if (empty($cid) && !empty($screen_name)) {
if (strpos($screen_name, '@') !== false) {
return Contact::getIdForURL($screen_name, 0, false);
}
$user = User::getByNickname($screen_name, ['uid']); $user = User::getByNickname($screen_name, ['uid']);
if (!empty($user['uid'])) { if (!empty($user['uid'])) {
$cid = Contact::getPublicIdByUserId($user['uid']); return Contact::getPublicIdByUserId($user['uid']);
} }
} }
if (empty($cid) && ($uid != 0)) { if ($uid != 0) {
$cid = Contact::getPublicIdByUserId($uid); return Contact::getPublicIdByUserId($uid);
} }
return $cid; return null;
} }
} }

View file

@ -295,8 +295,6 @@ class ApiTest extends FixtureTest
'method' 'method'
) )
); );
self::assertTrue($API['api_path']['auth']);
self::assertEquals('method', $API['api_path']['method']);
self::assertTrue(is_callable($API['api_path']['func'])); self::assertTrue(is_callable($API['api_path']['func']));
} }
@ -397,11 +395,9 @@ class ApiTest extends FixtureTest
$_SERVER['QUERY_STRING'] = 'pagename=api_path'; $_SERVER['QUERY_STRING'] = 'pagename=api_path';
$_GET['callback'] = 'callback_name'; $_GET['callback'] = 'callback_name';
$args = DI::args()->determine($_SERVER, $_GET);
self::assertEquals( self::assertEquals(
'callback_name(["some_data"])', 'callback_name(["some_data"])',
api_call($this->app, $args) api_call('api_path', 'json')
); );
} }
@ -424,8 +420,6 @@ class ApiTest extends FixtureTest
$_SERVER['REQUEST_METHOD'] = 'method'; $_SERVER['REQUEST_METHOD'] = 'method';
$_SERVER['QUERY_STRING'] = 'pagename=api_path'; $_SERVER['QUERY_STRING'] = 'pagename=api_path';
$args = DI::args()->determine($_SERVER, $_GET);
$this->config->set('system', 'profiler', true); $this->config->set('system', 'profiler', true);
$this->config->set('rendertime', 'callstack', true); $this->config->set('rendertime', 'callstack', true);
$this->app->callstack = [ $this->app->callstack = [
@ -438,7 +432,7 @@ class ApiTest extends FixtureTest
self::assertEquals( self::assertEquals(
'["some_data"]', '["some_data"]',
api_call($this->app, $args) api_call('api_path', 'json')
); );
} }
@ -460,11 +454,9 @@ class ApiTest extends FixtureTest
$_SERVER['REQUEST_METHOD'] = 'method'; $_SERVER['REQUEST_METHOD'] = 'method';
$_SERVER['QUERY_STRING'] = 'pagename=api_path.json'; $_SERVER['QUERY_STRING'] = 'pagename=api_path.json';
$args = DI::args()->determine($_SERVER, $_GET);
self::assertEquals( self::assertEquals(
'["some_data"]', '["some_data"]',
api_call($this->app, $args) api_call('api_path.json', 'json')
); );
} }
@ -490,7 +482,7 @@ class ApiTest extends FixtureTest
self::assertEquals( self::assertEquals(
'some_data', 'some_data',
api_call($this->app, $args) api_call('api_path.xml', 'xml')
); );
} }
@ -512,12 +504,10 @@ class ApiTest extends FixtureTest
$_SERVER['REQUEST_METHOD'] = 'method'; $_SERVER['REQUEST_METHOD'] = 'method';
$_SERVER['QUERY_STRING'] = 'pagename=api_path.rss'; $_SERVER['QUERY_STRING'] = 'pagename=api_path.rss';
$args = DI::args()->determine($_SERVER, $_GET);
self::assertEquals( self::assertEquals(
'<?xml version="1.0" encoding="UTF-8"?>' . "\n" . '<?xml version="1.0" encoding="UTF-8"?>' . "\n" .
'some_data', 'some_data',
api_call($this->app, $args) api_call('api_path.rss', 'rss')
); );
} }
@ -539,12 +529,10 @@ class ApiTest extends FixtureTest
$_SERVER['REQUEST_METHOD'] = 'method'; $_SERVER['REQUEST_METHOD'] = 'method';
$_SERVER['QUERY_STRING'] = 'pagename=api_path.atom'; $_SERVER['QUERY_STRING'] = 'pagename=api_path.atom';
$args = DI::args()->determine($_SERVER, $_GET);
self::assertEquals( self::assertEquals(
'<?xml version="1.0" encoding="UTF-8"?>' . "\n" . '<?xml version="1.0" encoding="UTF-8"?>' . "\n" .
'some_data', 'some_data',
api_call($this->app, $args) api_call('api_path.atom', 'atom')
); );
} }
@ -2511,8 +2499,8 @@ class ApiTest extends FixtureTest
*/ */
public function testApiDirectMessagesNewWithUserId() public function testApiDirectMessagesNewWithUserId()
{ {
$_POST['text'] = 'message_text'; $_POST['text'] = 'message_text';
$_POST['user_id'] = $this->otherUser['id']; $_REQUEST['user_id'] = $this->otherUser['id'];
$result = api_direct_messages_new('json'); $result = api_direct_messages_new('json');
self::assertEquals(['direct_message' => ['error' => -1]], $result); self::assertEquals(['direct_message' => ['error' => -1]], $result);
} }
@ -2525,9 +2513,9 @@ class ApiTest extends FixtureTest
public function testApiDirectMessagesNewWithScreenName() public function testApiDirectMessagesNewWithScreenName()
{ {
$this->app->setLoggedInUserNickname($this->selfUser['nick']); $this->app->setLoggedInUserNickname($this->selfUser['nick']);
$_POST['text'] = 'message_text'; $_POST['text'] = 'message_text';
$_POST['user_id'] = $this->friendUser['id']; $_REQUEST['user_id'] = $this->friendUser['id'];
$result = api_direct_messages_new('json'); $result = api_direct_messages_new('json');
self::assertStringContainsString('message_text', $result['direct_message']['text']); self::assertStringContainsString('message_text', $result['direct_message']['text']);
self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']); self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']);
self::assertEquals(1, $result['direct_message']['friendica_seen']); self::assertEquals(1, $result['direct_message']['friendica_seen']);
@ -2541,9 +2529,9 @@ class ApiTest extends FixtureTest
public function testApiDirectMessagesNewWithTitle() public function testApiDirectMessagesNewWithTitle()
{ {
$this->app->setLoggedInUserNickname($this->selfUser['nick']); $this->app->setLoggedInUserNickname($this->selfUser['nick']);
$_POST['text'] = 'message_text'; $_POST['text'] = 'message_text';
$_POST['user_id'] = $this->friendUser['id']; $_REQUEST['user_id'] = $this->friendUser['id'];
$_REQUEST['title'] = 'message_title'; $_REQUEST['title'] = 'message_title';
$result = api_direct_messages_new('json'); $result = api_direct_messages_new('json');
self::assertStringContainsString('message_text', $result['direct_message']['text']); self::assertStringContainsString('message_text', $result['direct_message']['text']);
self::assertStringContainsString('message_title', $result['direct_message']['text']); self::assertStringContainsString('message_title', $result['direct_message']['text']);
@ -2559,9 +2547,9 @@ class ApiTest extends FixtureTest
public function testApiDirectMessagesNewWithRss() public function testApiDirectMessagesNewWithRss()
{ {
$this->app->setLoggedInUserNickname($this->selfUser['nick']); $this->app->setLoggedInUserNickname($this->selfUser['nick']);
$_POST['text'] = 'message_text'; $_POST['text'] = 'message_text';
$_POST['user_id'] = $this->friendUser['id']; $_REQUEST['user_id'] = $this->friendUser['id'];
$result = api_direct_messages_new('rss'); $result = api_direct_messages_new('rss');
self::assertXml($result, 'direct-messages'); self::assertXml($result, 'direct-messages');
} }