fixup_files.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #!/usr/bin/env php
  2. <?php
  3. // This file is part of GNU social - https://www.gnu.org/software/social
  4. //
  5. // GNU social is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU Affero General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // GNU social is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU Affero General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU Affero General Public License
  16. // along with GNU social. If not, see <http://www.gnu.org/licenses/>.
  17. /**
  18. * EmbedPlugin implementation for GNU social
  19. *
  20. * @package GNUsocial
  21. * @author Mikael Nordfeldth
  22. * @author Diogo Cordeiro <diogo@fc.up.pt>
  23. * @copyright 2019 Free Software Foundation, Inc http://www.fsf.org
  24. * @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
  25. */
  26. define('INSTALLDIR', dirname(__DIR__, 3));
  27. define('PUBLICDIR', INSTALLDIR . DIRECTORY_SEPARATOR . 'public');
  28. $longoptions = ['dry-run', 'h-bug', 'broken-oembed', 'limit='];
  29. $helptext = <<<END_OF_USERROLE_HELP
  30. fixup_files.php [options]
  31. Patches attachments with broken oembed.
  32. --dry-run look but don't touch
  33. --h-bug Patches up file entries with corrupted types and titles (the "h bug")
  34. --broken-oembed Attempts refecting info for broken attachments
  35. --limit [date] Only affect files from after this date. This is a timestamp, format is: yyyy-mm-dd (optional time hh:mm:ss may be provided)
  36. END_OF_USERROLE_HELP;
  37. require_once INSTALLDIR.'/scripts/commandline.inc';
  38. $dry = have_option('dry-run');
  39. $h_bug = have_option('h-bug');
  40. $broken = have_option('broken-oembed');
  41. $limit = get_option_value('limit');
  42. if (!($broken ^ $h_bug)) {
  43. echo "Exactly one of --h-bug and --broken-oembed are required\n";
  44. die();
  45. }
  46. $fn = new DB_DataObject();
  47. $query = <<<'END'
  48. SELECT file_to_post.file_id
  49. FROM file_to_post
  50. INNER JOIN file ON file_to_post.file_id = file.id
  51. INNER JOIN notice ON file_to_post.post_id = notice.id
  52. WHERE
  53. END;
  54. if ($h_bug) {
  55. $query .= <<<'END'
  56. file.title = 'h'
  57. AND file.mimetype = 'h'
  58. AND file.size = 0
  59. AND file.protected = 0
  60. END;
  61. } elseif ($broken) {
  62. $query .= ' file.filename IS NULL';
  63. }
  64. if (!empty($limit)) {
  65. $query .= " AND notice.modified >= '{$fn->escape($limit)}'";
  66. }
  67. $query .= ' GROUP BY file_to_post.file_id ORDER BY MAX(notice.modified)';
  68. $fn->query($query);
  69. if ($h_bug) {
  70. echo "Found {$fn->N} bad items:\n";
  71. } else {
  72. echo "Found {$fn->N} files.\n";
  73. }
  74. while ($fn->fetch()) {
  75. $f = File::getByID($fn->file_id);
  76. try {
  77. $data = File_embed::getByFile($f);
  78. } catch (Exception $e) {
  79. // Carry on
  80. }
  81. if ($broken && $data instanceof File_embed) {
  82. try {
  83. $thumb = File_thumbnail::byFile($f, true /* not null url */);
  84. $thumb->getPath(); // Check we have the file
  85. } catch (Exception $e) {
  86. $no_thumb = true;
  87. // Doesn't exist, no problem
  88. }
  89. }
  90. if ($h_bug) {
  91. echo "ID: {$f->id}, URL {$f->url}";
  92. if ($dry) {
  93. if ($data instanceof File_embed) {
  94. echo " (unchanged)\n";
  95. } else {
  96. echo " (unchanged, but embedding lookup failed)\n";
  97. }
  98. } elseif (!$dry) {
  99. $f->query(sprintf(
  100. <<<'END'
  101. UPDATE file
  102. SET mimetype = NULL, title = NULL, size = NULL,
  103. protected = NULL, modified = CURRENT_TIMESTAMP
  104. WHERE id = %d;
  105. END,
  106. $f->getID()
  107. ));
  108. $f->decache();
  109. if ($data instanceof File_embed) {
  110. $fetch = true;
  111. echo " (ok)\n";
  112. } else {
  113. echo " (ok, but embedding lookup failed)\n";
  114. }
  115. }
  116. } elseif (
  117. $broken
  118. && (
  119. !($data instanceof File_embed)
  120. || empty($data->title)
  121. || empty($f->title)
  122. || ($thumb instanceof File_thumbnail && empty($thumb->filename))
  123. )
  124. ) {
  125. // print_r($thumb);
  126. if (!$dry) {
  127. echo "Will refetch for file with ";
  128. } else {
  129. echo "Found broken file with ";
  130. }
  131. echo "ID: {$f->getID()}, URL {$f->url}\n";
  132. if (!$dry) {
  133. $fetch = true;
  134. $f->query(sprintf(
  135. <<<'END'
  136. UPDATE file
  137. SET title = NULL, size = NULL,
  138. protected = NULL, modified = CURRENT_TIMESTAMP
  139. WHERE id = %d;
  140. END,
  141. $f->getID()
  142. ));
  143. $f->decache();
  144. if ($data instanceof File_embed) {
  145. $data->delete();
  146. $data->decache();
  147. }
  148. if ($thumb instanceof File_thumbnail) {
  149. // Delete all thumbnails, not just this one
  150. $f->query("DELETE FROM file_thumbnail WHERE file_id = {$f->getID()}");
  151. $thumb->decache();
  152. }
  153. }
  154. }
  155. if (isset($fetch) && $fetch === true && !$dry) {
  156. $fetch = false;
  157. echo "Attempting to fetch Embed data\n";
  158. Event::handle('EndFileSaveNew', array($f));
  159. }
  160. }
  161. echo "Done.\n";