| 1 | #! /usr/bin/env php |
|---|
| 2 | <?php |
|---|
| 3 | |
|---|
| 4 | require_once(dirname($argv[0]) . "/utilities.php"); |
|---|
| 5 | require_once(IA_ROOT_DIR . "common/attachment.php"); |
|---|
| 6 | require_once(IA_ROOT_DIR . "common/db/attachment.php"); |
|---|
| 7 | db_connect(); |
|---|
| 8 | |
|---|
| 9 | log_print("Checking attachment dir..."); |
|---|
| 10 | log_warn("This script consumes tons of memory so errors might occur"); |
|---|
| 11 | |
|---|
| 12 | $res = db_query("SELECT `id`, `name`, `page`, `size` FROM ia_file"); |
|---|
| 13 | |
|---|
| 14 | $extra_files = array_flip(glob(IA_ROOT_DIR . "attach/*")); |
|---|
| 15 | $extra_atts = array(); |
|---|
| 16 | $total_files = count($extra_files); |
|---|
| 17 | $total_atts = 0; |
|---|
| 18 | $mismatched_sizes = array(); |
|---|
| 19 | |
|---|
| 20 | // Check attachments. |
|---|
| 21 | while ($att = db_next_row($res)) { |
|---|
| 22 | ++$total_atts; |
|---|
| 23 | $fname = attachment_get_filepath($att); |
|---|
| 24 | if (array_key_exists($fname, $extra_files)) { |
|---|
| 25 | unset($extra_files[$fname]); |
|---|
| 26 | } else { |
|---|
| 27 | $extra_atts[] = $att; |
|---|
| 28 | continue; |
|---|
| 29 | } |
|---|
| 30 | if (filesize($fname) != $att['size']) { |
|---|
| 31 | $att['file_size'] = filesize($fname); |
|---|
| 32 | $mismatched_sizes[] = $att; |
|---|
| 33 | } |
|---|
| 34 | } |
|---|
| 35 | |
|---|
| 36 | // FIXME: check cache. |
|---|
| 37 | $extra_files = array_keys($extra_files); |
|---|
| 38 | |
|---|
| 39 | if (count($extra_files) == 0 && count($extra_atts) == 0) { |
|---|
| 40 | log_print("Database and attach dir are in perfect sync, $total_files total files."); |
|---|
| 41 | } else { |
|---|
| 42 | log_print("There are ".count($extra_files)." out of ".$total_files." disk files with no db entry."); |
|---|
| 43 | if (count($extra_files)) { |
|---|
| 44 | if (read_bool("Do you want to see a list?", false)) { |
|---|
| 45 | foreach ($extra_files as $file) { |
|---|
| 46 | log_print($file); |
|---|
| 47 | } |
|---|
| 48 | } |
|---|
| 49 | if (read_bool("Want to delete them?", false)) { |
|---|
| 50 | foreach ($extra_files as $file) { |
|---|
| 51 | unlink($file); |
|---|
| 52 | } |
|---|
| 53 | } |
|---|
| 54 | } |
|---|
| 55 | |
|---|
| 56 | log_print("There are ".count($extra_atts)." out of ".$total_atts." db files with no disk file."); |
|---|
| 57 | if (count($extra_atts)) { |
|---|
| 58 | if (read_bool("Do you want to see a list?", false)) { |
|---|
| 59 | foreach ($extra_atts as $att) { |
|---|
| 60 | log_print("page ".$att['page']." name ".$att['name']); |
|---|
| 61 | } |
|---|
| 62 | } |
|---|
| 63 | if (read_bool("Want to delete them?", false)) { |
|---|
| 64 | foreach ($extra_atts as $att) { |
|---|
| 65 | attachment_delete_by_id($att['id']); |
|---|
| 66 | } |
|---|
| 67 | } |
|---|
| 68 | } |
|---|
| 69 | } |
|---|
| 70 | |
|---|
| 71 | unset($extra_atts); |
|---|
| 72 | unset($extra_files); |
|---|
| 73 | |
|---|
| 74 | if (count($mismatched_sizes) != 0) { |
|---|
| 75 | log_print('There are ' . count($mismatched_sizes) . ' files with ' . |
|---|
| 76 | 'mismatching sizes on disk and in the db'); |
|---|
| 77 | if (read_bool('Do you want to see a list?', false)) { |
|---|
| 78 | foreach ($mismatched_sizes as $att) { |
|---|
| 79 | log_print(sprintf('page %s name %s file_size %s db_size %s', |
|---|
| 80 | $att['page'], $att['name'], |
|---|
| 81 | $att['file_size'], $att['size'])); |
|---|
| 82 | } |
|---|
| 83 | } |
|---|
| 84 | if (read_bool('Do you want to try to fix this?', false)) { |
|---|
| 85 | foreach ($mismatched_sizes as $att) { |
|---|
| 86 | if ($att['file_size'] == 0 && $att['size'] != 0) { |
|---|
| 87 | // File was likely uploaded when disk was out of space. |
|---|
| 88 | // Nothing we can do, delete it. |
|---|
| 89 | log_print(sprintf('Deleting attachment page %s name %s', |
|---|
| 90 | $att['page'], $att['name'])); |
|---|
| 91 | attachment_delete_by_id($att['id']); |
|---|
| 92 | continue; |
|---|
| 93 | } |
|---|
| 94 | |
|---|
| 95 | $safe_update = false; |
|---|
| 96 | if (starts_with($att['name'], 'grader_test') && |
|---|
| 97 | $att['file_size'] == $att['size'] + 1) { |
|---|
| 98 | // A script was run that added missing trailing endlines |
|---|
| 99 | // to grader tests. |
|---|
| 100 | $safe_update = true; |
|---|
| 101 | } |
|---|
| 102 | if ($att['file_size'] != 0 && $att['size'] == 0) { |
|---|
| 103 | $safe_update = true; |
|---|
| 104 | } |
|---|
| 105 | |
|---|
| 106 | if ($safe_update) { |
|---|
| 107 | $new_att = attachment_get_by_id($att['id']); |
|---|
| 108 | $new_att['size'] = $att['file_size']; |
|---|
| 109 | attachment_update($new_att['id'], $new_att['name'], |
|---|
| 110 | $new_att['size'], $new_att['mime_type'], |
|---|
| 111 | $new_att['page'], $new_att['user_id'], |
|---|
| 112 | $new_att['remote_ip_info']); |
|---|
| 113 | continue; |
|---|
| 114 | } |
|---|
| 115 | log_print(sprintf('I don\'t know how to handle attachment page ' . |
|---|
| 116 | $att['page'] . ' name ' . $att['name'])); |
|---|
| 117 | } |
|---|
| 118 | } |
|---|
| 119 | } else { |
|---|
| 120 | log_print('Stored file sizes match those of the files on disk.'); |
|---|
| 121 | } |
|---|
| 122 | |
|---|
| 123 | if (read_bool("Check mimetypes (could take a long time)?", false)) { |
|---|
| 124 | $res = db_query("SELECT `id`, `name`, `page`, `mime_type` FROM ia_file"); |
|---|
| 125 | $mismatched_mimetypes = array(); |
|---|
| 126 | while ($att = db_next_row($res)) { |
|---|
| 127 | $fname = attachment_get_filepath($att); |
|---|
| 128 | if (!is_file($fname)) { |
|---|
| 129 | continue; |
|---|
| 130 | } |
|---|
| 131 | if (get_mime_type($fname) != $att['mime_type']) { |
|---|
| 132 | $att['file_mime_type'] = get_mime_type($fname); |
|---|
| 133 | $mismatched_mimetypes[] = $att; |
|---|
| 134 | } |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | if (count($mismatched_mimetypes) != 0) { |
|---|
| 138 | log_print('There are ' . count($mismatched_mimetypes) . ' files with ' . |
|---|
| 139 | 'mismatching mimetypes on disk and in the db'); |
|---|
| 140 | if (read_bool('Do you want to see a list?', false)) { |
|---|
| 141 | foreach ($mismatched_mimetypes as $att) { |
|---|
| 142 | log_print( |
|---|
| 143 | sprintf('page %s name %s file_mime_type %s db_mime_type %s', |
|---|
| 144 | $att['page'], $att['name'], |
|---|
| 145 | $att['file_mime_type'], $att['mime_type'])); |
|---|
| 146 | } |
|---|
| 147 | } |
|---|
| 148 | if (read_bool('Do you want to update them?', false)) { |
|---|
| 149 | foreach ($mismatched_mimetypes as $att) { |
|---|
| 150 | $new_att = attachment_get_by_id($att['id']); |
|---|
| 151 | $new_att['mime_type'] = $att['file_mime_type']; |
|---|
| 152 | attachment_update($new_att['id'], $new_att['name'], |
|---|
| 153 | $new_att['size'], $new_att['mime_type'], |
|---|
| 154 | $new_att['page'], $new_att['user_id'], |
|---|
| 155 | $new_att['remote_ip_info']); |
|---|
| 156 | } |
|---|
| 157 | } |
|---|
| 158 | } else { |
|---|
| 159 | log_print('Stored mime_types match those of the files on disk.'); |
|---|
| 160 | } |
|---|
| 161 | } |
|---|
| 162 | |
|---|
| 163 | if (read_bool("Enforce permissions?", false)) { |
|---|
| 164 | $defowner = null; |
|---|
| 165 | if (preg_match('/\/home\/([^\/]*)/', IA_ROOT_DIR, $matches)) { |
|---|
| 166 | $defowner = $matches[1]; |
|---|
| 167 | } |
|---|
| 168 | $userown = read_line("Owning user?", $defowner); |
|---|
| 169 | $groupown = read_line("Owning group?", $defowner); |
|---|
| 170 | $errs = false; |
|---|
| 171 | $files = glob(IA_ROOT_DIR . "attach/*"); |
|---|
| 172 | foreach ($files as $file) { |
|---|
| 173 | $err = array(); |
|---|
| 174 | if (@chmod($file, 0640) == false) { |
|---|
| 175 | $err[] = "chmod"; |
|---|
| 176 | } |
|---|
| 177 | if (@chown($file, $userown) == false) { |
|---|
| 178 | $err[] = "chown"; |
|---|
| 179 | } |
|---|
| 180 | if (@chgrp($file, $groupown) == false) { |
|---|
| 181 | $err[] = "chgrp"; |
|---|
| 182 | } |
|---|
| 183 | $errs |= $err; |
|---|
| 184 | if ($err) { |
|---|
| 185 | log_print("Failed ".implode(', ', $err)." on $file"); |
|---|
| 186 | } |
|---|
| 187 | } |
|---|
| 188 | if ($errs) { |
|---|
| 189 | log_print("There were some errors. You should run this as root."); |
|---|
| 190 | } |
|---|
| 191 | } |
|---|
| 192 | |
|---|
| 193 | ?> |
|---|