apnotice.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <?php
  2. // This file is part of GNU social - https://www.gnu.org/software/social
  3. //
  4. // GNU social is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Affero General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // GNU social is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Affero General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Affero General Public License
  15. // along with GNU social. If not, see <http://www.gnu.org/licenses/>.
  16. /**
  17. * ActivityPub implementation for GNU social
  18. *
  19. * @package GNUsocial
  20. * @author Diogo Cordeiro <diogo@fc.up.pt>
  21. * @copyright 2018-2019 Free Software Foundation, Inc http://www.fsf.org
  22. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  23. * @link http://www.gnu.org/software/social/
  24. */
  25. defined('GNUSOCIAL') || die();
  26. /**
  27. * Notice (Local notices only)
  28. *
  29. * @category Plugin
  30. * @package GNUsocial
  31. * @author Diogo Cordeiro <diogo@fc.up.pt>
  32. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  33. */
  34. class apNoticeAction extends ManagedAction
  35. {
  36. protected $needLogin = false;
  37. protected $canPost = true;
  38. /**
  39. * Notice id
  40. * @var int
  41. */
  42. public $notice_id;
  43. /**
  44. * Notice object to show
  45. */
  46. public $notice = null;
  47. /**
  48. * Profile of the notice object
  49. */
  50. public $profile = null;
  51. /**
  52. * Avatar of the profile of the notice object
  53. */
  54. public $avatar = null;
  55. /**
  56. * Load attributes based on database arguments
  57. *
  58. * Loads all the DB stuff
  59. *
  60. * @param array $args $_REQUEST array
  61. *
  62. * @return bool success flag
  63. */
  64. protected function prepare(array $args = []): bool
  65. {
  66. parent::prepare($args);
  67. $this->notice_id = (int)$this->trimmed('id');
  68. try {
  69. $this->notice = $this->getNotice();
  70. } catch (ClientException $e) {
  71. //ActivityPubReturn::error('Activity deleted.', 410);
  72. ActivityPubReturn::answer(Activitypub_tombstone::tombstone_to_array($this->notice_id), 410);
  73. }
  74. $this->target = $this->notice;
  75. if (!$this->notice->inScope($this->scoped)) {
  76. // TRANS: Client exception thrown when trying a view a notice the user has no access to.
  77. throw new ClientException(_m('Access restricted.'), 403);
  78. }
  79. $this->profile = $this->notice->getProfile();
  80. if (!$this->profile instanceof Profile) {
  81. // TRANS: Server error displayed trying to show a notice without a connected profile.
  82. $this->serverError(_m('Notice has no profile.'), 500);
  83. }
  84. try {
  85. $this->avatar = $this->profile->getAvatar(AVATAR_PROFILE_SIZE);
  86. } catch (Exception $e) {
  87. $this->avatar = null;
  88. }
  89. return true;
  90. }
  91. /**
  92. * Is this action read-only?
  93. *
  94. * @return bool true
  95. */
  96. public function isReadOnly($args): bool
  97. {
  98. return true;
  99. }
  100. /**
  101. * Last-modified date for page
  102. *
  103. * When was the content of this page last modified? Based on notice,
  104. * profile, avatar.
  105. *
  106. * @return int last-modified date as unix timestamp
  107. */
  108. public function lastModified(): int
  109. {
  110. return max(strtotime($this->notice->modified),
  111. strtotime($this->profile->modified),
  112. ($this->avatar) ? strtotime($this->avatar->modified) : 0);
  113. }
  114. /**
  115. * Handle the Notice request
  116. *
  117. * @return void
  118. * @throws EmptyPkeyValueException
  119. * @throws InvalidUrlException
  120. * @throws ServerException
  121. * @author Diogo Cordeiro <diogo@fc.up.pt>
  122. */
  123. protected function handle(): void
  124. {
  125. if (is_null($this->notice)) {
  126. ActivityPubReturn::error('Invalid Activity URI.', 404);
  127. }
  128. if (!$this->notice->isLocal()) {
  129. // We have no authority on the requested activity.
  130. ActivityPubReturn::error("This is not a local activity.", 403);
  131. }
  132. $res = Activitypub_notice::notice_to_array($this->notice);
  133. ActivityPubReturn::answer($res);
  134. }
  135. /**
  136. * Fetch the notice to show. This may be overridden by child classes to
  137. * customize what we fetch without duplicating all of the prepare() method.
  138. *
  139. * @return null|Notice null if not found
  140. * @throws ClientException If GONE
  141. */
  142. protected function getNotice(): ?Notice
  143. {
  144. $notice = null;
  145. try {
  146. $notice = Notice::getByID($this->notice_id);
  147. // Alright, got it!
  148. return $notice;
  149. } catch (NoResultException $e) {
  150. // Hm, not found.
  151. $deleted = null;
  152. Event::handle('IsNoticeDeleted', [$this->notice_id, &$deleted]);
  153. if ($deleted === true) {
  154. // TRANS: Client error displayed trying to show a deleted notice.
  155. throw new ClientException(_m('Notice deleted.'), 410);
  156. }
  157. }
  158. // No such notice.
  159. return null;
  160. }
  161. }