attachment.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <?php
  2. /**
  3. * StatusNet, the distributed open-source microblogging tool
  4. *
  5. * Show notice attachments
  6. *
  7. * PHP version 5
  8. *
  9. * LICENCE: This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Affero General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. * @category Personal
  23. * @package StatusNet
  24. * @author Evan Prodromou <evan@status.net>
  25. * @copyright 2008-2009 StatusNet, Inc.
  26. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  27. * @link http://status.net/
  28. */
  29. if (!defined('GNUSOCIAL')) { exit(1); }
  30. /**
  31. * Show notice attachments
  32. *
  33. * @category Personal
  34. * @package StatusNet
  35. * @author Evan Prodromou <evan@status.net>
  36. * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  37. * @link http://status.net/
  38. */
  39. class AttachmentAction extends ManagedAction
  40. {
  41. /**
  42. * Attachment File object to show
  43. */
  44. var $attachment = null;
  45. /**
  46. * Load attributes based on database arguments
  47. *
  48. * Loads all the DB stuff
  49. *
  50. * @param array $args $_REQUEST array
  51. *
  52. * @return success flag
  53. */
  54. protected function prepare(array $args=array())
  55. {
  56. parent::prepare($args);
  57. if (!empty($id = $this->trimmed('attachment'))) {
  58. $this->attachment = File::getKV($id);
  59. } elseif (!empty($filehash = $this->trimmed('filehash'))) {
  60. $this->attachment = File::getByHash($filehash);
  61. }
  62. if (!$this->attachment instanceof File) {
  63. // TRANS: Client error displayed trying to get a non-existing attachment.
  64. $this->clientError(_('No such attachment.'), 404);
  65. }
  66. return true;
  67. }
  68. /**
  69. * Is this action read-only?
  70. *
  71. * @return boolean true
  72. */
  73. function isReadOnly($args)
  74. {
  75. return true;
  76. }
  77. /**
  78. * Title of the page
  79. *
  80. * @return string title of the page
  81. */
  82. function title()
  83. {
  84. $a = new Attachment($this->attachment);
  85. return $a->title();
  86. }
  87. public function showPage()
  88. {
  89. if (empty($this->attachment->filename)) {
  90. // if it's not a local file, gtfo
  91. common_redirect($this->attachment->getUrl(), 303);
  92. }
  93. parent::showPage();
  94. }
  95. /**
  96. * Fill the content area of the page
  97. *
  98. * Shows a single notice list item.
  99. *
  100. * @return void
  101. */
  102. function showContent()
  103. {
  104. $ali = new Attachment($this->attachment, $this);
  105. $cnt = $ali->show();
  106. }
  107. /**
  108. * Don't show page notice
  109. *
  110. * @return void
  111. */
  112. function showPageNoticeBlock()
  113. {
  114. }
  115. /**
  116. * Show aside: this attachments appears in what notices
  117. *
  118. * @return void
  119. */
  120. function showSections() {
  121. $ns = new AttachmentNoticeSection($this);
  122. $ns->show();
  123. }
  124. /**
  125. * Last-modified date for file
  126. *
  127. * @return int last-modified date as unix timestamp
  128. */
  129. public function lastModified()
  130. {
  131. if (common_config('site', 'use_x_sendfile')) {
  132. return null;
  133. }
  134. return filemtime($this->path);
  135. }
  136. /**
  137. * etag header for file
  138. *
  139. * This returns the same data (inode, size, mtime) as Apache would,
  140. * but in decimal instead of hex.
  141. *
  142. * @return string etag http header
  143. */
  144. function etag()
  145. {
  146. if (common_config('site', 'use_x_sendfile')) {
  147. return null;
  148. }
  149. $cache = Cache::instance();
  150. if($cache) {
  151. $key = Cache::key('attachments:etag:' . $this->path);
  152. $etag = $cache->get($key);
  153. if($etag === false) {
  154. $etag = crc32(file_get_contents($this->path));
  155. $cache->set($key,$etag);
  156. }
  157. return $etag;
  158. }
  159. $stat = stat($this->path);
  160. return '"' . $stat['ino'] . '-' . $stat['size'] . '-' . $stat['mtime'] . '"';
  161. }
  162. /**
  163. * Include $this as a file read from $filepath, for viewing and downloading
  164. */
  165. public function sendFile(string $filepath) {
  166. if (common_config('site', 'use_x_sendfile')) {
  167. header('X-Sendfile: ' . $filepath);
  168. } else {
  169. $filesize = $this->attachment->size;
  170. // 'if available', it says, so ensure we have it
  171. if (empty($filesize)) {
  172. $filesize = filesize($filepath);
  173. }
  174. header("Content-Length: {$filesize}");
  175. // header('Cache-Control: private, no-transform, no-store, must-revalidate');
  176. $ret = @readfile($filepath);
  177. if ($ret === false || $ret !== $filesize) {
  178. common_log(LOG_ERR, "The lengths of the file as recorded on the DB (or on disk) for the file " .
  179. "{$filepath}, with id={$this->attachment->id} differ from what was sent to the user.");
  180. }
  181. }
  182. }
  183. }