X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=include%2Fapi.php;h=a69bd01b4971edfcea66cb166a3542111c3cd931;hb=9827e933a2a1b8e93f293d4e6293384126e5784c;hp=8220e7bb1640c1c2cb9dd5b8a4f4950895bed6c0;hpb=800694e9b36bc261a671a80b7ca787f27564a7ac;p=friendica.git diff --git a/include/api.php b/include/api.php index 8220e7bb16..a69bd01b49 100644 --- a/include/api.php +++ b/include/api.php @@ -11,9 +11,7 @@ use Friendica\Content\ContactSelector; use Friendica\Content\Feature; use Friendica\Content\Text\BBCode; use Friendica\Content\Text\HTML; -use Friendica\Core\Config; use Friendica\Core\Hook; -use Friendica\Core\L10n; use Friendica\Core\Logger; use Friendica\Core\Protocol; use Friendica\Core\Session; @@ -25,6 +23,7 @@ use Friendica\Model\Contact; use Friendica\Model\Group; use Friendica\Model\Item; use Friendica\Model\Mail; +use Friendica\Model\Notify; use Friendica\Model\Photo; use Friendica\Model\Profile; use Friendica\Model\User; @@ -65,11 +64,11 @@ $API = []; $called_api = []; /** + * Auth API user + * * It is not sufficient to use local_user() to check whether someone is allowed to use the API, * because this will open CSRF holes (just embed an image with src=friendicasite.com/api/statuses/update?status=CSRF * into a page, and visitors will post something without noticing it). - * - * @brief Auth API user */ function api_user() { @@ -81,13 +80,13 @@ function api_user() } /** + * Get source name from API client + * * Clients can send 'source' parameter to be show in post metadata * as "sent via ". * Some clients doesn't send a source param, we support ones we know * (only Twidere, atm) * - * @brief Get source name from API client - * * @return string * Client source name, default to "api" if unset/unknown * @throws Exception @@ -113,7 +112,7 @@ function api_source() } /** - * @brief Format date for API + * Format date for API * * @param string $str Source date, as UTC * @return string Date in UTC formatted as "D M d H:i:s +0000 Y" @@ -128,8 +127,6 @@ function api_date($str) /** * Register a function to be the endpoint for defined API path. * - * @brief Register API endpoint - * * @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 @@ -161,8 +158,6 @@ function api_register_func($path, $func, $auth = false, $method = API_METHOD_ANY * Log in user via OAuth1 or Simple HTTP Auth. * Simple Auth allow username in form of
user@server
, ignoring server part * - * @brief Login API user - * * @param App $a App * @throws ForbiddenException * @throws InternalServerErrorException @@ -260,12 +255,12 @@ function api_login(App $a) } /** + * Check HTTP method of called API + * * API endpoints can define which HTTP method to accept when called. * This function check the current HTTP method agains endpoint * registered method. * - * @brief Check HTTP method of called API - * * @param string $method Required methods, uppercase, separated by comma * @return bool */ @@ -278,9 +273,9 @@ function api_check_method($method) } /** - * Authenticate user, call registered API function, set HTTP headers + * Main API entry point * - * @brief Main API entry point + * 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) @@ -317,9 +312,7 @@ function api_call(App $a, App\Arguments $args = null) } $called_api = explode("/", $p); - //unset($_SERVER['PHP_AUTH_USER']); - /// @TODO should be "true ==[=] $info['auth']", if you miss only one = character, you assign a variable (only with ==). Let's make all this even. if (!empty($info['auth']) && api_user() === false) { api_login($a); } @@ -379,7 +372,7 @@ function api_call(App $a, App\Arguments $args = null) } /** - * @brief Format API error string + * Format API error string * * @param string $type Return type (xml, json, rss, as) * @param object $e HTTPException Error object @@ -417,7 +410,7 @@ function api_error($type, $e, App\Arguments $args) } /** - * @brief Set values for RSS template + * Set values for RSS template * * @param App $a * @param array $arr Array to be passed to template @@ -451,7 +444,7 @@ function api_rss_extra(App $a, $arr, $user_info) /** - * @brief Unique contact to contact url. + * Unique contact to contact url. * * @param int $id Contact id * @return bool|string @@ -470,7 +463,7 @@ function api_unique_id_to_nurl($id) } /** - * @brief Get user info array. + * Get user info array. * * @param App $a App * @param int|string $contact_id Contact ID or URL @@ -759,7 +752,7 @@ function api_get_user(App $a, $contact_id = null) } /** - * @brief return api-formatted array for item's author and owner + * return api-formatted array for item's author and owner * * @param App $a App * @param array $item item from db @@ -787,7 +780,7 @@ function api_item_get_user(App $a, $item) } /** - * @brief walks recursively through an array with the possibility to change value and key + * walks recursively through an array with the possibility to change value and key * * @param array $array The array to walk through * @param callable $callback The callback function @@ -815,7 +808,7 @@ function api_walk_recursive(array &$array, callable $callback) } /** - * @brief Callback function to transform the array in an array that can be transformed in a XML file + * Callback function to transform the array in an array that can be transformed in a XML file * * @param mixed $item Array item value * @param string $key Array key @@ -841,7 +834,7 @@ function api_reformat_xml(&$item, &$key) } /** - * @brief Creates the XML from a JSON style array + * Creates the XML from a JSON style array * * @param array $data JSON style array * @param string $root_element Name of the root element @@ -886,7 +879,7 @@ function api_create_xml(array $data, $root_element) } /** - * @brief Formats the data according to the data type + * Formats the data according to the data type * * @param string $root_element Name of the root element * @param string $type Return type (atom, rss, xml, json) @@ -1101,7 +1094,7 @@ function api_statuses_update($type) if (!$parent) { // Check for throttling (maximum posts per day, week and month) - $throttle_day = Config::get('system', 'throttle_limit_day'); + $throttle_day = DI::config()->get('system', 'throttle_limit_day'); if ($throttle_day > 0) { $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60); @@ -1110,12 +1103,12 @@ function api_statuses_update($type) if ($posts_day > $throttle_day) { Logger::log('Daily posting limit reached for user '.api_user(), Logger::DEBUG); - // die(api_error($type, L10n::t("Daily posting limit of %d posts reached. The post was rejected.", $throttle_day)); - throw new TooManyRequestsException(L10n::tt("Daily posting limit of %d post reached. The post was rejected.", "Daily posting limit of %d posts reached. The post was rejected.", $throttle_day)); + // die(api_error($type, DI::l10n()->t("Daily posting limit of %d posts reached. The post was rejected.", $throttle_day)); + throw new TooManyRequestsException(DI::l10n()->tt("Daily posting limit of %d post reached. The post was rejected.", "Daily posting limit of %d posts reached. The post was rejected.", $throttle_day)); } } - $throttle_week = Config::get('system', 'throttle_limit_week'); + $throttle_week = DI::config()->get('system', 'throttle_limit_week'); if ($throttle_week > 0) { $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*7); @@ -1124,12 +1117,12 @@ function api_statuses_update($type) if ($posts_week > $throttle_week) { Logger::log('Weekly posting limit reached for user '.api_user(), Logger::DEBUG); - // die(api_error($type, L10n::t("Weekly posting limit of %d posts reached. The post was rejected.", $throttle_week))); - throw new TooManyRequestsException(L10n::tt("Weekly posting limit of %d post reached. The post was rejected.", "Weekly posting limit of %d posts reached. The post was rejected.", $throttle_week)); + // die(api_error($type, DI::l10n()->t("Weekly posting limit of %d posts reached. The post was rejected.", $throttle_week))); + throw new TooManyRequestsException(DI::l10n()->tt("Weekly posting limit of %d post reached. The post was rejected.", "Weekly posting limit of %d posts reached. The post was rejected.", $throttle_week)); } } - $throttle_month = Config::get('system', 'throttle_limit_month'); + $throttle_month = DI::config()->get('system', 'throttle_limit_month'); if ($throttle_month > 0) { $datefrom = date(DateTimeFormat::MYSQL, time() - 24*60*60*30); @@ -1138,8 +1131,8 @@ function api_statuses_update($type) if ($posts_month > $throttle_month) { Logger::log('Monthly posting limit reached for user '.api_user(), Logger::DEBUG); - // die(api_error($type, L10n::t("Monthly posting limit of %d posts reached. The post was rejected.", $throttle_month)); - throw new TooManyRequestsException(L10n::t("Monthly posting limit of %d post reached. The post was rejected.", "Monthly posting limit of %d posts reached. The post was rejected.", $throttle_month)); + // die(api_error($type, DI::l10n()->t("Monthly posting limit of %d posts reached. The post was rejected.", $throttle_month)); + throw new TooManyRequestsException(DI::l10n()->t("Monthly posting limit of %d post reached. The post was rejected.", "Monthly posting limit of %d posts reached. The post was rejected.", $throttle_month)); } } } @@ -1777,8 +1770,6 @@ api_register_func('api/statuses/public_timeline', 'api_statuses_public_timeline' /** * Returns the most recent statuses posted by users this node knows about. * - * @brief Returns the list of public federated posts this node knows about - * * @param string $type Return format: json, xml, atom, rss * @return array|string * @throws BadRequestException @@ -2209,8 +2200,6 @@ api_register_func('api/statuses/replies', 'api_statuses_mentions', true); /** * Returns the most recent statuses posted by the user. * - * @brief Returns a user's public timeline - * * @param string $type Either "json" or "xml" * @return string|array * @throws BadRequestException @@ -2748,7 +2737,7 @@ function api_get_entitities(&$text, $bbcode) if ($image) { // If image cache is activated, then use the following sizes: // thumb (150), small (340), medium (600) and large (1024) - if (!Config::get("system", "proxy_disabled")) { + if (!DI::config()->get("system", "proxy_disabled")) { $media_url = ProxyUtils::proxifyUrl($url); $sizes = []; @@ -2812,7 +2801,7 @@ function api_format_items_embeded_images($item, $text) } /** - * @brief return name as array + * return name as array * * @param string $txt text * @return array @@ -2839,7 +2828,7 @@ function api_contactlink_to_array($txt) /** - * @brief return likes, dislikes and attend status for item + * return likes, dislikes and attend status for item * * @param array $item array * @param string $type Return type (atom, rss, xml, json) @@ -2919,7 +2908,7 @@ function api_format_items_activities($item, $type = "json") /** - * @brief return data from profiles + * return data from profiles * * @param array $profile_row array containing data from db table 'profile' * @return array @@ -2972,7 +2961,7 @@ function api_format_items_profiles($profile_row) } /** - * @brief format items to be returned by api + * format items to be returned by api * * @param array $items array of items * @param array $user_info @@ -3387,11 +3376,11 @@ function api_lists_statuses($type) api_register_func('api/lists/statuses', 'api_lists_statuses', true); /** + * Returns either the friends of the follower list + * * Considers friends and followers lists to be private and won't return * anything if any user_id parameter is passed. * - * @brief Returns either the friends of the follower list - * * @param string $qtype Either "friends" or "followers" * @return boolean|array * @throws BadRequestException @@ -3478,9 +3467,7 @@ function api_statuses_f($qtype) /** - * Returns the user's friends. - * - * @brief Returns the list of friends of the provided user + * Returns the list of friends of the provided user * * @deprecated By Twitter API in favor of friends/list * @@ -3499,9 +3486,7 @@ function api_statuses_friends($type) } /** - * Returns the user's followers. - * - * @brief Returns the list of followers of the provided user + * Returns the list of followers of the provided user * * @deprecated By Twitter API in favor of friends/list * @@ -3585,15 +3570,15 @@ api_register_func('api/friendships/incoming', 'api_friendships_incoming', true); */ function api_statusnet_config($type) { - $name = Config::get('config', 'sitename'); + $name = DI::config()->get('config', 'sitename'); $server = DI::baseUrl()->getHostname(); $logo = DI::baseUrl() . '/images/friendica-64.png'; - $email = Config::get('config', 'admin_email'); - $closed = intval(Config::get('config', 'register_policy')) === \Friendica\Module\Register::CLOSED ? 'true' : 'false'; - $private = Config::get('system', 'block_public') ? 'true' : 'false'; - $textlimit = (string) Config::get('config', 'api_import_size', Config::get('config', 'max_import_size', 200000)); - $ssl = Config::get('system', 'have_ssl') ? 'true' : 'false'; - $sslserver = Config::get('system', 'have_ssl') ? str_replace('http:', 'https:', DI::baseUrl()) : ''; + $email = DI::config()->get('config', 'admin_email'); + $closed = intval(DI::config()->get('config', 'register_policy')) === \Friendica\Module\Register::CLOSED ? 'true' : 'false'; + $private = DI::config()->get('system', 'block_public') ? 'true' : 'false'; + $textlimit = (string) DI::config()->get('config', 'api_import_size', DI::config()->get('config', 'max_import_size', 200000)); + $ssl = DI::config()->get('system', 'have_ssl') ? 'true' : 'false'; + $sslserver = DI::config()->get('system', 'have_ssl') ? str_replace('http:', 'https:', DI::baseUrl()) : ''; $config = [ 'site' => ['name' => $name,'server' => $server, 'theme' => 'default', 'path' => '', @@ -3818,9 +3803,7 @@ function api_direct_messages_new($type) api_register_func('api/direct_messages/new', 'api_direct_messages_new', true, API_METHOD_POST); /** - * Destroys a direct message. - * - * @brief delete a direct_message from mail table through api + * delete a direct_message from mail table through api * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @return string|array @@ -3906,8 +3889,6 @@ api_register_func('api/direct_messages/destroy', 'api_direct_messages_destroy', /** * Unfollow Contact * - * @brief unfollow contact - * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @return string|array * @throws BadRequestException @@ -4203,7 +4184,7 @@ api_register_func('api/oauth/access_token', 'api_oauth_access_token', false); /** - * @brief delete a complete photoalbum with all containing photos from database through api + * delete a complete photoalbum with all containing photos from database through api * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @return string|array @@ -4258,7 +4239,7 @@ function api_fr_photoalbum_delete($type) } /** - * @brief update the name of the album for all photos of an album + * update the name of the album for all photos of an album * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @return string|array @@ -4300,7 +4281,7 @@ function api_fr_photoalbum_update($type) /** - * @brief list all photos of the authenticated user + * list all photos of the authenticated user * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @return string|array @@ -4348,7 +4329,7 @@ function api_fr_photos_list($type) } /** - * @brief upload a new photo or change an existing photo + * upload a new photo or change an existing photo * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @return string|array @@ -4487,7 +4468,7 @@ function api_fr_photo_create_update($type) } /** - * @brief delete a single photo from the database through api + * delete a single photo from the database through api * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @return string|array @@ -4540,7 +4521,7 @@ function api_fr_photo_delete($type) /** - * @brief 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 * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @return string|array @@ -4569,9 +4550,7 @@ function api_fr_photo_detail($type) /** - * Updates the user’s profile image. - * - * @brief updates the profile image for the user (either a specified profile or the default profile) + * updates the profile image for the user (either a specified profile or the default profile) * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @@ -4616,7 +4595,7 @@ function api_account_update_profile_image($type) $media = $_FILES['media']; } // save new profile image - $data = save_media_to_database("profileimage", $media, $type, L10n::t('Profile Photos'), "", "", "", "", "", $is_default_profile); + $data = save_media_to_database("profileimage", $media, $type, DI::l10n()->t('Profile Photos'), "", "", "", "", "", $is_default_profile); // get filetype if (is_array($media['type'])) { @@ -4646,7 +4625,7 @@ function api_account_update_profile_image($type) // Update global directory in background $url = DI::baseUrl() . '/profile/' . DI::app()->user['nickname']; - if ($url && strlen(Config::get('system', 'directory'))) { + if ($url && strlen(DI::config()->get('system', 'directory'))) { Worker::add(PRIORITY_LOW, "Directory", $url); } @@ -4703,7 +4682,7 @@ function api_account_update_profile($type) Worker::add(PRIORITY_LOW, 'ProfileUpdate', $local_user); // Update global directory in background - if ($api_user['url'] && strlen(Config::get('system', 'directory'))) { + if ($api_user['url'] && strlen(DI::config()->get('system', 'directory'))) { Worker::add(PRIORITY_LOW, "Directory", $api_user['url']); } @@ -4811,7 +4790,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $ throw new InternalServerErrorException("image size exceeds PHP config settings, file was rejected by server"); } // check against max upload size within Friendica instance - $maximagesize = Config::get('system', 'maximagesize'); + $maximagesize = DI::config()->get('system', 'maximagesize'); if ($maximagesize && ($filesize > $maximagesize)) { $formattedBytes = Strings::formatBytes($maximagesize); throw new InternalServerErrorException("image size exceeds Friendica config setting (uploaded size: $formattedBytes)"); @@ -4829,7 +4808,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $ @unlink($src); // check max length of images on server - $max_length = Config::get('system', 'max_image_length'); + $max_length = DI::config()->get('system', 'max_image_length'); if (!$max_length) { $max_length = MAX_IMAGE_LENGTH; } @@ -5047,6 +5026,9 @@ function prepare_photo_data($type, $scale, $photo_id) // retrieve item element for getting activities (like, dislike etc.) related to photo $condition = ['uid' => local_user(), 'resource-id' => $photo_id, 'type' => 'photo']; $item = Item::selectFirstForUser(local_user(), ['id'], $condition); + if (!DBA::isResult($item)) { + throw new NotFoundException('Photo-related item not found.'); + } $data['photo']['friendica_activities'] = api_format_items_activities($item, $type); @@ -5180,7 +5162,7 @@ function api_get_announce($item) } /** - * @brief Return the item shared, if the item contains only the [share] tag + * Return the item shared, if the item contains only the [share] tag * * @param array $item Sharer item * @return array|false Shared item or false if not a reshare @@ -5907,7 +5889,7 @@ api_register_func('api/friendica/activity/unattendno', 'api_friendica_activity', api_register_func('api/friendica/activity/unattendmaybe', 'api_friendica_activity', true, API_METHOD_POST); /** - * @brief Returns notifications + * Returns notifications * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @return string|array @@ -5925,25 +5907,31 @@ function api_friendica_notification($type) if ($a->argc!==3) { throw new BadRequestException("Invalid argument count"); } - $notes = DI::notify()->getAll([], ['seen' => 'ASC', 'date' => 'DESC'], 50); + + $notifications = DI::notify()->select(['uid' => api_user()], ['order' => ['seen' => 'ASC', 'date' => 'DESC'], 'limit' => 50]); if ($type == "xml") { - $xmlnotes = []; - if (!empty($notes)) { - foreach ($notes as $note) { - $xmlnotes[] = ["@attributes" => $note]; + $xmlnotes = false; + if (!empty($notifications)) { + foreach ($notifications as $notification) { + $xmlnotes[] = ["@attributes" => $notification->toArray()]; } } - $notes = $xmlnotes; + $result = $xmlnotes; + } elseif (count($notifications) > 0) { + $result = $notifications->getArrayCopy(); + } else { + $result = false; } - return api_format_data("notes", $type, ['note' => $notes]); + + return api_format_data("notes", $type, ['note' => $result]); } /** - * POST request with 'id' param as notification id + * Set notification as seen and returns associated item (if possible) * - * @brief Set notification as seen and returns associated item (if possible) + * POST request with 'id' param as notification id * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @return string|array @@ -5955,37 +5943,36 @@ function api_friendica_notification($type) */ function api_friendica_notification_seen($type) { - $a = DI::app(); + $a = DI::app(); $user_info = api_get_user($a); if (api_user() === false || $user_info === false) { throw new ForbiddenException(); } - if ($a->argc!==4) { + if ($a->argc !== 4) { throw new BadRequestException("Invalid argument count"); } $id = (!empty($_REQUEST['id']) ? intval($_REQUEST['id']) : 0); - $nm = DI::notify(); - $note = $nm->getByID($id); - if (is_null($note)) { - throw new BadRequestException("Invalid argument"); - } - - $nm->setSeen($note); - if ($note['otype']=='item') { - // would be really better with an ItemsManager and $im->getByID() :-P - $item = Item::selectFirstForUser(api_user(), [], ['id' => $note['iid'], 'uid' => api_user()]); - if (DBA::isResult($item)) { - // we found the item, return it to the user - $ret = api_format_items([$item], $user_info, false, $type); - $data = ['status' => $ret]; - return api_format_data("status", $type, $data); + try { + $notification = DI::notify()->getByID($id); + $notification->setSeen(); + + if ($notification->otype === Notify::OTYPE_ITEM) { + $item = Item::selectFirstForUser(api_user(), [], ['id' => $notification->iid, 'uid' => api_user()]); + if (DBA::isResult($item)) { + // we found the item, return it to the user + $ret = api_format_items([$item], $user_info, false, $type); + $data = ['status' => $ret]; + return api_format_data("status", $type, $data); + } + // the item can't be found, but we set the notification as seen, so we count this as a success } - // the item can't be found, but we set the note as seen, so we count this as a success + return api_format_data('result', $type, ['result' => "success"]); + } catch (NotFoundException $e) { + throw new BadRequestException('Invalid argument'); } - return api_format_data('result', $type, ['result' => "success"]); } /// @TODO move to top of file or somewhere better @@ -5993,7 +5980,7 @@ api_register_func('api/friendica/notification/seen', 'api_friendica_notification api_register_func('api/friendica/notification', 'api_friendica_notification', true, API_METHOD_GET); /** - * @brief update a direct_message to seen state + * update a direct_message to seen state * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @return string|array (success result=ok, error result=error with error message) @@ -6044,7 +6031,7 @@ function api_friendica_direct_messages_setseen($type) api_register_func('api/friendica/direct_messages_setseen', 'api_friendica_direct_messages_setseen', true); /** - * @brief search for direct_messages containing a searchstring through api + * search for direct_messages containing a searchstring through api * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @param string $box @@ -6115,7 +6102,7 @@ function api_friendica_direct_messages_search($type, $box = "") api_register_func('api/friendica/direct_messages_search', 'api_friendica_direct_messages_search', true); /** - * @brief return data of all the profiles a user has to the client + * return data of all the profiles a user has to the client * * @param string $type Known types are 'atom', 'rss', 'xml' and 'json' * @return string|array @@ -6138,7 +6125,7 @@ function api_friendica_profile_show($type) // retrieve general information about profiles for user $multi_profiles = Feature::isEnabled(api_user(), 'multi_profiles'); - $directory = Config::get('system', 'directory'); + $directory = DI::config()->get('system', 'directory'); // get data of the specified profile id or all profiles of the user if not specified if ($profile_id != 0) { @@ -6221,9 +6208,9 @@ function api_saved_searches_list($type) api_register_func('api/saved_searches/list', 'api_saved_searches_list', true); /* - * Bind comment numbers(friendica_comments: Int) on each statuses page of *_timeline / favorites / search + * Number of comments * - * @brief Number of comments + * Bind comment numbers(friendica_comments: Int) on each statuses page of *_timeline / favorites / search * * @param object $data [Status, Status] *