fixup_files.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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. defined('GNUSOCIAL');
  27. define('INSTALLDIR', realpath(__DIR__ . '/../../..'));
  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. $sql = "UPDATE file " .
  100. "SET mimetype=null, title=null,size=null,protected=null " .
  101. "WHERE id={$f->id}";
  102. $f->query($sql);
  103. $f->decache();
  104. if ($data instanceof File_embed) {
  105. $fetch = true;
  106. echo " (ok)\n";
  107. } else {
  108. echo " (ok, but embedding lookup failed)\n";
  109. }
  110. }
  111. } elseif ($broken &&
  112. (!$data instanceof File_embed ||
  113. empty($data->title) ||
  114. empty($f->title)
  115. ||
  116. ($thumb instanceof File_thumbnail && empty($thumb->filename))
  117. )) {
  118. // print_r($thumb);
  119. if (!$dry) {
  120. echo "Will refetch for file with ";
  121. } else {
  122. echo "Found broken file with ";
  123. }
  124. echo "ID: {$f->id}, URL {$f->url}\n";
  125. if (!$dry) {
  126. $fetch = true;
  127. $sql = "UPDATE file SET title=null, size=null, protected=null " .
  128. "WHERE id={$f->id}";
  129. $f->query($sql);
  130. $f->decache();
  131. if ($data instanceof File_embed) {
  132. $data->delete();
  133. $data->decache();
  134. }
  135. if ($thumb instanceof File_thumbnail) {
  136. // Delete all thumbnails, not just this one
  137. $f->query("DELETE from file_thumbnail WHERE file_id = {$f->id}");
  138. $thumb->decache();
  139. }
  140. }
  141. }
  142. if (isset($fetch) && $fetch === true && !$dry) {
  143. $fetch = false;
  144. echo "Attempting to fetch Embed data\n";
  145. Event::handle('EndFileSaveNew', array($f));
  146. }
  147. }
  148. echo "Done.\n";