diff --git a/include/api.php b/include/api.php index afd28b6155..86792cde50 100644 --- a/include/api.php +++ b/include/api.php @@ -35,7 +35,6 @@ use Friendica\Model\Contact; use Friendica\Model\Group; use Friendica\Model\Item; use Friendica\Model\Mail; -use Friendica\Model\Notification; use Friendica\Model\Photo; use Friendica\Model\Post; use Friendica\Model\Profile; @@ -49,7 +48,6 @@ use Friendica\Network\HTTPException\NotFoundException; use Friendica\Network\HTTPException\TooManyRequestsException; use Friendica\Network\HTTPException\UnauthorizedException; use Friendica\Object\Image; -use Friendica\Security\BasicAuth; use Friendica\Util\DateTimeFormat; use Friendica\Util\Images; use Friendica\Util\Network; @@ -58,13 +56,6 @@ use Friendica\Util\Strings; require_once __DIR__ . '/../mod/item.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 = []; /** @@ -72,19 +63,13 @@ $API = []; * * @param string $path API URL path, relative to DI::baseUrl() * @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; $API[$path] = [ 'func' => $func, - 'auth' => $auth, - 'method' => $method, ]; // Workaround for hotot @@ -92,8 +77,6 @@ function api_register_func($path, $func, $auth = false, $method = API_METHOD_ANY $API[$path] = [ '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 * - * @param App $a App * @param App\Arguments $args The app arguments (optional, will retrieved by the DI-Container in case of missing) * @return string|array API call result * @throws Exception */ -function api_call(App $a, App\Arguments $args = null) +function api_call($command, $extension) { global $API; - if ($args == null) { - $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"; - } + Logger::info('Legacy API call', ['command' => $command, 'extension' => $extension]); try { foreach ($API as $p => $info) { - if (strpos($args->getCommand(), $p) === 0) { - if (!empty($info['auth']) && BaseApi::getCurrentUserID() === false) { - 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]); + if (strpos($command, $p) === 0) { + Logger::debug(BaseApi::LOG_PREFIX . 'parameters', ['module' => 'api', 'action' => 'call', 'parameters' => $_REQUEST]); $stamp = microtime(true); - $return = call_user_func($info['func'], $type); + $return = call_user_func($info['func'], $extension); $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) { /* @@ -155,7 +116,7 @@ function api_call(App $a, App\Arguments $args = null) throw new InternalServerErrorException(); } - switch ($type) { + switch ($extension) { case "xml": header("Content-Type: text/xml"); 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(); } catch (HTTPException $e) { - Logger::notice(API_LOG_PREFIX . 'got exception', ['module' => 'api', 'action' => 'call', 'query' => DI::args()->getQueryString(), 'error' => $e]); - DI::apiResponse()->error($e->getCode(), $e->getDescription(), $e->getMessage(), $type); + 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(), $extension); } } @@ -733,7 +694,7 @@ function api_statuses_mediap($type) } /// @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 user’s current status. @@ -916,8 +877,8 @@ function api_statuses_update($type) 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_with_media', '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); /** * Uploads an image to Friendica. @@ -959,7 +920,7 @@ function api_media_upload() 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) @@ -1012,7 +973,7 @@ function api_media_metadata_create($type) 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. @@ -1091,7 +1052,7 @@ function api_statuses_repeat($type) 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. @@ -1159,8 +1120,8 @@ function api_favorites_create_destroy($type) 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/destroy', 'api_favorites_create_destroy', true, API_METHOD_DELETE); +api_register_func('api/favorites/create', 'api_favorites_create_destroy', true); +api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true); /** * 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) { + BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); $ret = []; /// @TODO $ret is not filled here? return DI::apiResponse()->formatData('lists', $type, ["lists_list" => $ret]); @@ -1316,6 +1278,7 @@ function api_statuses_f($qtype) */ function api_statuses_friends($type) { + BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); $data = api_statuses_f("friends"); if ($data === false) { return false; @@ -1337,6 +1300,7 @@ api_register_func('api/statuses/friends', 'api_statuses_friends', true); */ function api_statuses_followers($type) { + BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); $data = api_statuses_f("followers"); if ($data === false) { return false; @@ -1359,6 +1323,7 @@ api_register_func('api/statuses/followers', 'api_statuses_followers', true); */ function api_blocks_list($type) { + BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); $data = api_statuses_f('blocks'); if ($data === false) { return false; @@ -1381,6 +1346,7 @@ api_register_func('api/blocks/list', 'api_blocks_list', true); */ function api_friendships_incoming($type) { + BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); $data = api_statuses_f('incoming'); if ($data === false) { return false; @@ -1415,13 +1381,13 @@ function api_direct_messages_new($type) BaseApi::checkAllowedScope(BaseApi::SCOPE_WRITE); $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; } $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)) { 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)); } -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 @@ -1519,7 +1485,7 @@ function api_direct_messages_destroy($type) /// @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 @@ -1540,14 +1506,14 @@ function api_friendships_destroy($type) $owner = User::getOwnerDataById($uid); 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'); } $contact_id = $_REQUEST['user_id'] ?? 0; 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'); } @@ -1555,7 +1521,7 @@ function api_friendships_destroy($type) $contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id, 'uid' => 0, 'self' => false]); 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'); } @@ -1567,7 +1533,7 @@ function api_friendships_destroy($type) $contact = DBA::selectFirst('contact', [], $condition); 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'); } @@ -1575,7 +1541,7 @@ function api_friendships_destroy($type) $result = Contact::terminateFriendship($owner, $contact); 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.'); } @@ -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.'); } } 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'); } @@ -1596,7 +1562,7 @@ function api_friendships_destroy($type) 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) { + BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); $verbose = !empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false"; 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) { + BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); $verbose = !empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false"; 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) { + BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); $verbose = !empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false"; 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) { + BaseApi::checkAllowedScope(BaseApi::SCOPE_READ); $verbose = !empty($_GET['friendica_verbose']) ? strtolower($_GET['friendica_verbose']) : "false"; 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"); } -api_register_func('api/friendica/photo/create', 'api_fr_photo_create_update', true, API_METHOD_POST); -api_register_func('api/friendica/photo/update', '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); /** * 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. @@ -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. @@ -2207,7 +2177,7 @@ function api_friendica_group_create($type) 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. @@ -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. @@ -2311,7 +2281,7 @@ function api_friendica_group_update($type) 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. @@ -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 diff --git a/src/Module/Api/Friendica/Index.php b/src/Module/Api/Friendica/Index.php index 5806f2e481..cc0428ae1e 100644 --- a/src/Module/Api/Friendica/Index.php +++ b/src/Module/Api/Friendica/Index.php @@ -44,7 +44,7 @@ class Index extends BaseApi public function rawContent() { - echo api_call(DI::app()); + echo api_call(DI::args()->getCommand(), $this->parameters['extension'] ?? 'json'); exit(); } } diff --git a/src/Module/Api/GNUSocial/Statusnet/Conversation.php b/src/Module/Api/GNUSocial/Statusnet/Conversation.php index e330bddc9a..e81cd3d1fe 100644 --- a/src/Module/Api/GNUSocial/Statusnet/Conversation.php +++ b/src/Module/Api/GNUSocial/Statusnet/Conversation.php @@ -52,7 +52,7 @@ class Conversation extends BaseApi $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 $item = Post::selectFirst(['parent-uri-id'], ['id' => $id]); diff --git a/src/Module/Api/Twitter/Favorites.php b/src/Module/Api/Twitter/Favorites.php index 6a901574e5..4376b5b086 100644 --- a/src/Module/Api/Twitter/Favorites.php +++ b/src/Module/Api/Twitter/Favorites.php @@ -42,7 +42,7 @@ class Favorites extends BaseApi // in friendica starred item are private // 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 $since_id = $_REQUEST['since_id'] ?? 0; diff --git a/src/Module/Api/Twitter/Followers/Ids.php b/src/Module/Api/Twitter/Followers/Ids.php index 7dfdcd76f9..f529fc926b 100644 --- a/src/Module/Api/Twitter/Followers/Ids.php +++ b/src/Module/Api/Twitter/Followers/Ids.php @@ -39,6 +39,7 @@ class Ids extends ContactEndpoint // Expected value for user_id parameter: public/user contact id $contact_id = filter_input(INPUT_GET, 'user_id' , FILTER_VALIDATE_INT); $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]]); $stringify_ids = filter_input(INPUT_GET, 'stringify_ids', FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]); $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); $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]; diff --git a/src/Module/Api/Twitter/Followers/Lists.php b/src/Module/Api/Twitter/Followers/Lists.php index ae8b36fb99..0bd3addd59 100644 --- a/src/Module/Api/Twitter/Followers/Lists.php +++ b/src/Module/Api/Twitter/Followers/Lists.php @@ -39,6 +39,7 @@ class Lists extends ContactEndpoint // Expected value for user_id parameter: public/user contact id $contact_id = filter_input(INPUT_GET, 'user_id' , FILTER_VALIDATE_INT); $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]]); $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]]); @@ -52,7 +53,7 @@ class Lists extends ContactEndpoint $max_id = filter_input(INPUT_GET, 'max_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]; diff --git a/src/Module/Api/Twitter/Friends/Ids.php b/src/Module/Api/Twitter/Friends/Ids.php index c790dfea51..0c25700ccf 100644 --- a/src/Module/Api/Twitter/Friends/Ids.php +++ b/src/Module/Api/Twitter/Friends/Ids.php @@ -39,6 +39,7 @@ class Ids extends ContactEndpoint // Expected value for user_id parameter: public/user contact id $contact_id = filter_input(INPUT_GET, 'user_id' , FILTER_VALIDATE_INT); $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]]); $stringify_ids = filter_input(INPUT_GET, 'stringify_ids', FILTER_VALIDATE_BOOLEAN, ['options' => ['default' => false]]); $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); $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]; diff --git a/src/Module/Api/Twitter/Friends/Lists.php b/src/Module/Api/Twitter/Friends/Lists.php index c77ee66bbc..25bd32969a 100644 --- a/src/Module/Api/Twitter/Friends/Lists.php +++ b/src/Module/Api/Twitter/Friends/Lists.php @@ -39,6 +39,7 @@ class Lists extends ContactEndpoint // Expected value for user_id parameter: public/user contact id $contact_id = filter_input(INPUT_GET, 'user_id' , FILTER_VALIDATE_INT); $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]]); $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]]); @@ -52,7 +53,7 @@ class Lists extends ContactEndpoint $max_id = filter_input(INPUT_GET, 'max_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]; diff --git a/src/Module/Api/Twitter/Statuses/UserTimeline.php b/src/Module/Api/Twitter/Statuses/UserTimeline.php index 64365e5ab2..29fbc4fef6 100644 --- a/src/Module/Api/Twitter/Statuses/UserTimeline.php +++ b/src/Module/Api/Twitter/Statuses/UserTimeline.php @@ -42,7 +42,7 @@ class UserTimeline extends BaseApi 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; $max_id = $_REQUEST['max_id'] ?? 0; $exclude_replies = !empty($_REQUEST['exclude_replies']); diff --git a/src/Module/Api/Twitter/Users/Show.php b/src/Module/Api/Twitter/Users/Show.php index 1550b29ecc..1ace54880a 100644 --- a/src/Module/Api/Twitter/Users/Show.php +++ b/src/Module/Api/Twitter/Users/Show.php @@ -38,7 +38,7 @@ class Show extends BaseApi $uid = BaseApi::getCurrentUserID(); 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 { $cid = (int)$this->parameters['id']; } diff --git a/src/Module/BaseApi.php b/src/Module/BaseApi.php index f38b928a2a..03c8467a43 100644 --- a/src/Module/BaseApi.php +++ b/src/Module/BaseApi.php @@ -36,6 +36,8 @@ use Friendica\Util\HTTPInputData; class BaseApi extends BaseModule { + const LOG_PREFIX = 'API {action} - '; + const SCOPE_READ = 'read'; const SCOPE_WRITE = 'write'; 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)) { return $cid; } - if (strpos($screen_name, '@') !== false) { - $cid = Contact::getIdForURL($screen_name, 0, false); - } else { + if (!empty($profileurl)) { + return Contact::getIdForURL($profileurl); + } + + if (empty($cid) && !empty($screen_name)) { + if (strpos($screen_name, '@') !== false) { + return Contact::getIdForURL($screen_name, 0, false); + } + $user = User::getByNickname($screen_name, ['uid']); if (!empty($user['uid'])) { - $cid = Contact::getPublicIdByUserId($user['uid']); + return Contact::getPublicIdByUserId($user['uid']); } } - if (empty($cid) && ($uid != 0)) { - $cid = Contact::getPublicIdByUserId($uid); + if ($uid != 0) { + return Contact::getPublicIdByUserId($uid); } - return $cid; + return null; } } diff --git a/tests/legacy/ApiTest.php b/tests/legacy/ApiTest.php index 5133386e81..d1c2f25ebf 100644 --- a/tests/legacy/ApiTest.php +++ b/tests/legacy/ApiTest.php @@ -295,8 +295,6 @@ class ApiTest extends FixtureTest 'method' ) ); - self::assertTrue($API['api_path']['auth']); - self::assertEquals('method', $API['api_path']['method']); self::assertTrue(is_callable($API['api_path']['func'])); } @@ -397,11 +395,9 @@ class ApiTest extends FixtureTest $_SERVER['QUERY_STRING'] = 'pagename=api_path'; $_GET['callback'] = 'callback_name'; - $args = DI::args()->determine($_SERVER, $_GET); - self::assertEquals( '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['QUERY_STRING'] = 'pagename=api_path'; - $args = DI::args()->determine($_SERVER, $_GET); - $this->config->set('system', 'profiler', true); $this->config->set('rendertime', 'callstack', true); $this->app->callstack = [ @@ -438,7 +432,7 @@ class ApiTest extends FixtureTest self::assertEquals( '["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['QUERY_STRING'] = 'pagename=api_path.json'; - $args = DI::args()->determine($_SERVER, $_GET); - self::assertEquals( '["some_data"]', - api_call($this->app, $args) + api_call('api_path.json', 'json') ); } @@ -490,7 +482,7 @@ class ApiTest extends FixtureTest self::assertEquals( '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['QUERY_STRING'] = 'pagename=api_path.rss'; - $args = DI::args()->determine($_SERVER, $_GET); - self::assertEquals( '' . "\n" . '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['QUERY_STRING'] = 'pagename=api_path.atom'; - $args = DI::args()->determine($_SERVER, $_GET); - self::assertEquals( '' . "\n" . 'some_data', - api_call($this->app, $args) + api_call('api_path.atom', 'atom') ); } @@ -2511,8 +2499,8 @@ class ApiTest extends FixtureTest */ public function testApiDirectMessagesNewWithUserId() { - $_POST['text'] = 'message_text'; - $_POST['user_id'] = $this->otherUser['id']; + $_POST['text'] = 'message_text'; + $_REQUEST['user_id'] = $this->otherUser['id']; $result = api_direct_messages_new('json'); self::assertEquals(['direct_message' => ['error' => -1]], $result); } @@ -2525,9 +2513,9 @@ class ApiTest extends FixtureTest public function testApiDirectMessagesNewWithScreenName() { $this->app->setLoggedInUserNickname($this->selfUser['nick']); - $_POST['text'] = 'message_text'; - $_POST['user_id'] = $this->friendUser['id']; - $result = api_direct_messages_new('json'); + $_POST['text'] = 'message_text'; + $_REQUEST['user_id'] = $this->friendUser['id']; + $result = api_direct_messages_new('json'); self::assertStringContainsString('message_text', $result['direct_message']['text']); self::assertEquals('selfcontact', $result['direct_message']['sender_screen_name']); self::assertEquals(1, $result['direct_message']['friendica_seen']); @@ -2541,9 +2529,9 @@ class ApiTest extends FixtureTest public function testApiDirectMessagesNewWithTitle() { $this->app->setLoggedInUserNickname($this->selfUser['nick']); - $_POST['text'] = 'message_text'; - $_POST['user_id'] = $this->friendUser['id']; - $_REQUEST['title'] = 'message_title'; + $_POST['text'] = 'message_text'; + $_REQUEST['user_id'] = $this->friendUser['id']; + $_REQUEST['title'] = 'message_title'; $result = api_direct_messages_new('json'); self::assertStringContainsString('message_text', $result['direct_message']['text']); self::assertStringContainsString('message_title', $result['direct_message']['text']); @@ -2559,9 +2547,9 @@ class ApiTest extends FixtureTest public function testApiDirectMessagesNewWithRss() { $this->app->setLoggedInUserNickname($this->selfUser['nick']); - $_POST['text'] = 'message_text'; - $_POST['user_id'] = $this->friendUser['id']; - $result = api_direct_messages_new('rss'); + $_POST['text'] = 'message_text'; + $_REQUEST['user_id'] = $this->friendUser['id']; + $result = api_direct_messages_new('rss'); self::assertXml($result, 'direct-messages'); }