fixup_files.php 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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. $query = "
  47. SELECT DISTINCT
  48. file_to_post.file_id
  49. FROM
  50. file_to_post
  51. INNER JOIN
  52. file ON file.id = file_to_post.file_id
  53. INNER JOIN
  54. notice ON notice.id = file_to_post.post_id
  55. WHERE";
  56. $f = new File();
  57. if ($h_bug) {
  58. $query .= " file.title = 'h'
  59. AND file.mimetype = 'h'
  60. AND file.size = 0
  61. AND file.protected = 0";
  62. } elseif ($broken) {
  63. $query .= " file.filename is NULL";
  64. }
  65. $query .= empty($limit) ? "" : " AND notice.modified >= '{$limit}' ORDER BY notice.modified ASC";
  66. // echo $query;
  67. $fn = new DB_DataObject();
  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 ($broken &&
  117. (!$data instanceof File_embed ||
  118. empty($data->title) ||
  119. empty($f->title)
  120. ||
  121. ($thumb instanceof File_thumbnail && empty($thumb->filename))
  122. )) {
  123. // print_r($thumb);
  124. if (!$dry) {
  125. echo "Will refetch for file with ";
  126. } else {
  127. echo "Found broken file with ";
  128. }
  129. echo "ID: {$f->getID()}, URL {$f->url}\n";
  130. if (!$dry) {
  131. $fetch = true;
  132. $f->query(sprintf(
  133. <<<'END'
  134. UPDATE file
  135. SET title = NULL, size = NULL,
  136. protected = NULL, modified = CURRENT_TIMESTAMP
  137. WHERE id = %d;
  138. END,
  139. $f->getID()
  140. ));
  141. $f->decache();
  142. if ($data instanceof File_embed) {
  143. $data->delete();
  144. $data->decache();
  145. }
  146. if ($thumb instanceof File_thumbnail) {
  147. // Delete all thumbnails, not just this one
  148. $f->query("DELETE FROM file_thumbnail WHERE file_id = {$f->getID()}");
  149. $thumb->decache();
  150. }
  151. }
  152. }
  153. if (isset($fetch) && $fetch === true && !$dry) {
  154. $fetch = false;
  155. echo "Attempting to fetch Embed data\n";
  156. Event::handle('EndFileSaveNew', array($f));
  157. }
  158. }
  159. echo "Done.\n";