11 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. |
11 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. |
12 */ |
12 */ |
13 |
13 |
14 class Namespace_File extends Namespace_Default |
14 class Namespace_File extends Namespace_Default |
15 { |
15 { |
16 function send() |
16 function send() |
17 { |
17 { |
18 global $output; |
18 global $output; |
19 |
19 |
20 $output->add_before_footer($this->show_info()); |
20 $output->add_before_footer($this->show_info()); |
21 $output->add_before_footer($this->display_categories()); |
21 $output->add_before_footer($this->display_categories()); |
22 |
22 |
23 if ( $this->exists ) |
23 if ( $this->exists ) |
24 { |
24 { |
25 $this->send_from_db(); |
25 $this->send_from_db(); |
26 } |
26 } |
27 else |
27 else |
28 { |
28 { |
29 $output->header(); |
29 $output->header(); |
30 $this->error_404(); |
30 $this->error_404(); |
31 $output->footer(); |
31 $output->footer(); |
32 } |
32 } |
33 } |
33 } |
34 |
34 |
35 function show_info() |
35 function show_info() |
36 { |
36 { |
37 global $db, $session, $paths, $template, $plugins; // Common objects |
37 global $db, $session, $paths, $template, $plugins; // Common objects |
38 global $lang; |
38 global $lang; |
39 |
39 |
40 require_once(ENANO_ROOT . '/includes/log.php'); |
40 require_once(ENANO_ROOT . '/includes/log.php'); |
41 |
41 |
42 $local_page_id = $this->page_id; |
42 $local_page_id = $this->page_id; |
43 $local_namespace = $this->namespace; |
43 $local_namespace = $this->namespace; |
44 $html = ''; |
44 $html = ''; |
45 |
45 |
46 // Prevent unnecessary work |
46 // Prevent unnecessary work |
47 if ( $local_namespace != 'File' ) |
47 if ( $local_namespace != 'File' ) |
48 return null; |
48 return null; |
49 |
49 |
50 $selfn = $db->escape($this->page_id); |
50 $selfn = $db->escape($this->page_id); |
51 $q = $db->sql_query('SELECT f.mimetype,f.time_id,f.size,l.log_id FROM ' . table_prefix . "files AS f\n" |
51 $q = $db->sql_query('SELECT f.mimetype,f.time_id,f.size,l.log_id FROM ' . table_prefix . "files AS f\n" |
52 . " LEFT JOIN " . table_prefix . "logs AS l\n" |
52 . " LEFT JOIN " . table_prefix . "logs AS l\n" |
53 . " ON ( l.time_id = f.time_id AND ( l.action = 'reupload' OR l.action IS NULL ) )\n" |
53 . " ON ( l.time_id = f.time_id AND ( l.action = 'reupload' OR l.action IS NULL ) )\n" |
54 . " WHERE f.page_id = '$selfn'\n" |
54 . " WHERE f.page_id = '$selfn'\n" |
55 . " ORDER BY f.time_id DESC;"); |
55 . " ORDER BY f.time_id DESC;"); |
56 if ( !$q ) |
56 if ( !$q ) |
57 { |
57 { |
58 $db->_die('The file type could not be fetched.'); |
58 $db->_die('The file type could not be fetched.'); |
59 } |
59 } |
60 |
60 |
61 if ( $db->numrows() < 1 ) |
61 if ( $db->numrows() < 1 ) |
62 { |
62 { |
63 $html .= '<div class="mdg-comment" style="margin-left: 0;"> |
63 $html .= '<div class="mdg-comment" style="margin-left: 0;"> |
64 <h3>' . $lang->get('onpage_filebox_heading') . '</h3> |
64 <h3>' . $lang->get('onpage_filebox_heading') . '</h3> |
65 <p>' . $lang->get('onpage_filebox_msg_not_found', array('upload_link' => makeUrlNS('Special', 'UploadFile/'.$local_page_id))) . '</p> |
65 <p>' . $lang->get('onpage_filebox_msg_not_found', array('upload_link' => makeUrlNS('Special', 'UploadFile/'.$local_page_id))) . '</p> |
66 </div> |
66 </div> |
67 <br />'; |
67 <br />'; |
68 return $html; |
68 return $html; |
69 } |
69 } |
70 $r = $db->fetchrow(); |
70 $r = $db->fetchrow(); |
71 $mimetype = $r['mimetype']; |
71 $mimetype = $r['mimetype']; |
72 $datestring = enano_date(ED_DATE | ED_TIME, (int)$r['time_id']); |
72 $datestring = enano_date(ED_DATE | ED_TIME, (int)$r['time_id']); |
73 $html .= '<div class="mdg-comment" style="margin-left: 0;"> |
73 $html .= '<div class="mdg-comment" style="margin-left: 0;"> |
74 <h3>' . $lang->get('onpage_filebox_heading') . '</h3> |
74 <h3>' . $lang->get('onpage_filebox_heading') . '</h3> |
75 <p>' . $lang->get('onpage_filebox_lbl_type') . ' '.$r['mimetype'].'<br />'; |
75 <p>' . $lang->get('onpage_filebox_lbl_type') . ' '.$r['mimetype'].'<br />'; |
76 |
76 |
77 $size = $r['size'] . ' ' . $lang->get('etc_unit_bytes'); |
77 $size = $r['size'] . ' ' . $lang->get('etc_unit_bytes'); |
78 if ( $r['size'] >= 1048576 ) |
78 if ( $r['size'] >= 1048576 ) |
79 { |
79 { |
80 $size .= ' (' . ( round($r['size'] / 1048576, 1) ) . ' ' . $lang->get('etc_unit_megabytes_short') . ')'; |
80 $size .= ' (' . ( round($r['size'] / 1048576, 1) ) . ' ' . $lang->get('etc_unit_megabytes_short') . ')'; |
81 } |
81 } |
82 else if ( $r['size'] >= 1024 ) |
82 else if ( $r['size'] >= 1024 ) |
83 { |
83 { |
84 $size .= ' (' . ( round($r['size'] / 1024, 1) ) . ' ' . $lang->get('etc_unit_kilobytes_short') . ')'; |
84 $size .= ' (' . ( round($r['size'] / 1024, 1) ) . ' ' . $lang->get('etc_unit_kilobytes_short') . ')'; |
85 } |
85 } |
86 |
86 |
87 $html .= $lang->get('onpage_filebox_lbl_size', array('size' => $size)); |
87 $html .= $lang->get('onpage_filebox_lbl_size', array('size' => $size)); |
88 |
88 |
89 $html .= '<br />' . $lang->get('onpage_filebox_lbl_uploaded') . ' ' . $datestring . '</p>'; |
89 $html .= '<br />' . $lang->get('onpage_filebox_lbl_uploaded') . ' ' . $datestring . '</p>'; |
90 // are we dealing with an image? |
90 // are we dealing with an image? |
91 $is_image = substr($mimetype, 0, 6) == 'image/'; |
91 $is_image = substr($mimetype, 0, 6) == 'image/'; |
92 |
92 |
93 // for anything other than plain text and |
93 // for anything other than plain text and |
94 if ( !$is_image && ( substr($mimetype, 0, 5) != 'text/' || $mimetype == 'text/html' || $mimetype == 'text/javascript' ) ) |
94 if ( !$is_image && ( substr($mimetype, 0, 5) != 'text/' || $mimetype == 'text/html' || $mimetype == 'text/javascript' ) ) |
95 { |
95 { |
96 $html .= '<div class="warning-box"> |
96 $html .= '<div class="warning-box"> |
97 ' . $lang->get('onpage_filebox_msg_virus_warning') . ' |
97 ' . $lang->get('onpage_filebox_msg_virus_warning') . ' |
98 </div>'; |
98 </div>'; |
99 } |
99 } |
100 if ( $is_image ) |
100 if ( $is_image ) |
101 { |
101 { |
102 // show a thumbnail of the image |
102 // show a thumbnail of the image |
103 $html .= '<p> |
103 $html .= '<p> |
104 <a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn).'"> |
104 <a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn).'"> |
105 <img style="border: 0;" alt="' . htmlspecialchars($paths->page) . '" src="' . makeUrlNS('Special', "DownloadFile/$selfn/{$r['time_id']}", 'preview', true) . '" /> |
105 <img style="border: 0;" alt="' . htmlspecialchars($paths->page) . '" src="' . makeUrlNS('Special', "DownloadFile/$selfn/{$r['time_id']}", 'preview', true) . '" /> |
106 </a> |
106 </a> |
107 </p>'; |
107 </p>'; |
108 } |
108 } |
109 $html .= '<p> |
109 $html .= '<p> |
110 <a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.'/'.$r['time_id'].htmlspecialchars(urlSeparator).'download').'"> |
110 <a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.'/'.$r['time_id'].htmlspecialchars(urlSeparator).'download').'"> |
111 ' . $lang->get('onpage_filebox_btn_download') . ' |
111 ' . $lang->get('onpage_filebox_btn_download') . ' |
112 </a>'; |
112 </a>'; |
113 // allow reupload if: |
113 // allow reupload if: |
114 // * we are allowed to upload new versions, and |
114 // * we are allowed to upload new versions, and |
115 // - the file is unprotected, or |
115 // - the file is unprotected, or |
116 // - we have permission to override protection |
116 // - we have permission to override protection |
117 |
117 |
118 if ( !$this->perms ) |
118 if ( !$this->perms ) |
119 $this->perms = $session->fetch_page_acl($this->page_id, $this->namespace); |
119 $this->perms = $session->fetch_page_acl($this->page_id, $this->namespace); |
120 |
120 |
121 if ( $this->perms->get_permissions('upload_new_version') && ( !$this->page_protected || $this->perms->get_permissions('even_when_protected') ) ) |
121 if ( $this->perms->get_permissions('upload_new_version') && ( !$this->page_protected || $this->perms->get_permissions('even_when_protected') ) ) |
122 { |
122 { |
123 // upload new version link |
123 // upload new version link |
124 $html .= ' | <a href="'.makeUrlNS('Special', "UploadFile/$selfn", false, true).'"> |
124 $html .= ' | <a href="'.makeUrlNS('Special', "UploadFile/$selfn", false, true).'"> |
125 ' . $lang->get('onpage_filebox_btn_upload_new') . ' |
125 ' . $lang->get('onpage_filebox_btn_upload_new') . ' |
126 </a>'; |
126 </a>'; |
127 } |
127 } |
128 // close off paragraph |
128 // close off paragraph |
129 $html .= '</p>'; |
129 $html .= '</p>'; |
130 // only show this if there's more than one revision |
130 // only show this if there's more than one revision |
131 if ( $db->numrows() > 1 ) |
131 if ( $db->numrows() > 1 ) |
132 { |
132 { |
133 // requery, sql_result_seek() doesn't work on postgres |
133 // requery, sql_result_seek() doesn't work on postgres |
134 $db->free_result(); |
134 $db->free_result(); |
135 $q = $db->sql_query('SELECT f.mimetype,f.time_id,f.size,l.log_id FROM ' . table_prefix . "files AS f\n" |
135 $q = $db->sql_query('SELECT f.mimetype,f.time_id,f.size,l.log_id FROM ' . table_prefix . "files AS f\n" |
136 . " LEFT JOIN " . table_prefix . "logs AS l\n" |
136 . " LEFT JOIN " . table_prefix . "logs AS l\n" |
137 . " ON ( l.time_id = f.time_id AND ( l.action = 'reupload' OR l.action IS NULL ) )\n" |
137 . " ON ( l.time_id = f.time_id AND ( l.action = 'reupload' OR l.action IS NULL ) )\n" |
138 . " WHERE f.page_id = '$selfn'\n" |
138 . " WHERE f.page_id = '$selfn'\n" |
139 . " ORDER BY f.time_id DESC;"); |
139 . " ORDER BY f.time_id DESC;"); |
140 if ( !$q ) |
140 if ( !$q ) |
141 $db->_die(); |
141 $db->_die(); |
142 |
142 |
143 $log = new LogDisplay(); |
143 $log = new LogDisplay(); |
144 $log->add_criterion('page', $paths->nslist['File'] . $this->page_id); |
144 $log->add_criterion('page', $paths->nslist['File'] . $this->page_id); |
145 $log->add_criterion('action', 'reupload'); |
145 $log->add_criterion('action', 'reupload'); |
146 $data = $log->get_data(); |
146 $data = $log->get_data(); |
147 $i = -1; |
147 $i = -1; |
148 |
148 |
149 $html .= '<h3>' . $lang->get('onpage_filebox_heading_history') . '</h3><p>'; |
149 $html .= '<h3>' . $lang->get('onpage_filebox_heading_history') . '</h3><p>'; |
150 $last_rollback_id = false; |
150 $last_rollback_id = false; |
151 $download_flag = $is_image ? false : 'download'; |
151 $download_flag = $is_image ? false : 'download'; |
152 while ( $r = $db->fetchrow($q) ) |
152 while ( $r = $db->fetchrow($q) ) |
153 { |
153 { |
154 $html .= '(<a href="'.makeUrlNS('Special', "DownloadFile/$selfn/{$r['time_id']}", $download_flag, true).'">' . $lang->get('onpage_filebox_btn_this_version') . '</a>) '; |
154 $html .= '(<a href="'.makeUrlNS('Special', "DownloadFile/$selfn/{$r['time_id']}", $download_flag, true).'">' . $lang->get('onpage_filebox_btn_this_version') . '</a>) '; |
155 if ( $session->get_permissions('history_rollback') && $last_rollback_id ) |
155 if ( $session->get_permissions('history_rollback') && $last_rollback_id ) |
156 $html .= ' (<a href="#rollback:' . $last_rollback_id . '" onclick="ajaxRollback(\''.$last_rollback_id.'\'); return false;">' . $lang->get('onpage_filebox_btn_revert') . '</a>) '; |
156 $html .= ' (<a href="#rollback:' . $last_rollback_id . '" onclick="ajaxRollback(\''.$last_rollback_id.'\'); return false;">' . $lang->get('onpage_filebox_btn_revert') . '</a>) '; |
157 else if ( $session->get_permissions('history_rollback') && !$last_rollback_id ) |
157 else if ( $session->get_permissions('history_rollback') && !$last_rollback_id ) |
158 $html .= ' (' . $lang->get('onpage_filebox_btn_current') . ') '; |
158 $html .= ' (' . $lang->get('onpage_filebox_btn_current') . ') '; |
159 $last_rollback_id = $r['log_id']; |
159 $last_rollback_id = $r['log_id']; |
160 |
160 |
161 $html .= $r['mimetype'].', '; |
161 $html .= $r['mimetype'].', '; |
162 |
162 |
163 $fs = $r['size']; |
163 $fs = $r['size']; |
164 $fs = (int)$fs; |
164 $fs = (int)$fs; |
165 |
165 |
166 if($fs >= 1048576) |
166 if($fs >= 1048576) |
167 { |
167 { |
168 $fs = round($fs / 1048576, 1); |
168 $fs = round($fs / 1048576, 1); |
169 $size = $fs . ' ' . $lang->get('etc_unit_megabytes_short'); |
169 $size = $fs . ' ' . $lang->get('etc_unit_megabytes_short'); |
170 } |
170 } |
171 else |
171 else |
172 if ( $fs >= 1024 ) |
172 if ( $fs >= 1024 ) |
173 { |
173 { |
174 $fs = round($fs / 1024, 1); |
174 $fs = round($fs / 1024, 1); |
175 $size = $fs . ' ' . $lang->get('etc_unit_kilobytes_short'); |
175 $size = $fs . ' ' . $lang->get('etc_unit_kilobytes_short'); |
176 } |
176 } |
177 else |
177 else |
178 { |
178 { |
179 $size = $fs . ' ' . $lang->get('etc_unit_bytes'); |
179 $size = $fs . ' ' . $lang->get('etc_unit_bytes'); |
180 } |
180 } |
181 |
181 |
182 $html .= $size; |
182 $html .= $size; |
183 if ( isset($data[++$i]) ) |
183 if ( isset($data[++$i]) ) |
184 $html .= ': ' . LogDisplay::render_row($data[$i], false, false); |
184 $html .= ': ' . LogDisplay::render_row($data[$i], false, false); |
185 |
185 |
186 $html .= '<br />'; |
186 $html .= '<br />'; |
187 } |
187 } |
188 $html .= '</p>'; |
188 $html .= '</p>'; |
189 } |
189 } |
190 $db->free_result(); |
190 $db->free_result(); |
191 $html .= '</div><br />'; |
191 $html .= '</div><br />'; |
192 return $html; |
192 return $html; |
193 } |
193 } |
194 |
194 |
195 /** |
195 /** |
196 * Delete a file from the database and filesystem based on file ID. |
196 * Delete a file from the database and filesystem based on file ID. |
197 * @param int File ID |
197 * @param int File ID |
198 * @return null |
198 * @return null |
199 */ |
199 */ |
200 |
200 |
201 public static function delete_file($file_id) |
201 public static function delete_file($file_id) |
202 { |
202 { |
203 global $db, $session, $paths, $template, $plugins; // Common objects |
203 global $db, $session, $paths, $template, $plugins; // Common objects |
204 |
204 |
205 if ( !is_int($file_id) ) |
205 if ( !is_int($file_id) ) |
206 // seriously? |
206 // seriously? |
207 return null; |
207 return null; |
208 |
208 |
209 // pull file info |
209 // pull file info |
210 $q = $db->sql_query('SELECT filename, page_id, time_id, file_extension, file_key FROM ' . table_prefix . "files WHERE file_id = $file_id;"); |
210 $q = $db->sql_query('SELECT filename, page_id, time_id, file_extension, file_key FROM ' . table_prefix . "files WHERE file_id = $file_id;"); |
211 if ( !$q ) |
211 if ( !$q ) |
212 $db->_die(); |
212 $db->_die(); |
213 |
213 |
214 if ( $db->numrows() < 1 ) |
214 if ( $db->numrows() < 1 ) |
215 { |
215 { |
216 $db->free_result(); |
216 $db->free_result(); |
217 return null; |
217 return null; |
218 } |
218 } |
219 |
219 |
220 $row = $db->fetchrow(); |
220 $row = $db->fetchrow(); |
221 $db->free_result(); |
221 $db->free_result(); |
222 |
222 |
223 // make sure the image isn't used by multiple revisions |
223 // make sure the image isn't used by multiple revisions |
224 $q = $db->sql_query('SELECT 1 FROM ' . table_prefix . "files WHERE file_key = '{$row['file_key']}';"); |
224 $q = $db->sql_query('SELECT 1 FROM ' . table_prefix . "files WHERE file_key = '{$row['file_key']}';"); |
225 if ( !$q ) |
225 if ( !$q ) |
226 $db->_die(); |
226 $db->_die(); |
227 if ( $db->numrows() < 1 ) |
227 if ( $db->numrows() < 1 ) |
228 { |
228 { |
229 // remove from filesystem |
229 // remove from filesystem |
230 $file_path = ENANO_ROOT . "/files/{$row['file_key']}{$row['file_extension']}"; |
230 $file_path = ENANO_ROOT . "/files/{$row['file_key']}{$row['file_extension']}"; |
231 @unlink($file_path); |
231 @unlink($file_path); |
232 // old filename standard |
232 // old filename standard |
233 $file_path = ENANO_ROOT . "/files/{$row['file_key']}-{$row['time_id']}{$row['file_extension']}"; |
233 $file_path = ENANO_ROOT . "/files/{$row['file_key']}-{$row['time_id']}{$row['file_extension']}"; |
234 @unlink($file_path); |
234 @unlink($file_path); |
235 } |
235 } |
236 $db->free_result(); |
236 $db->free_result(); |
237 |
237 |
238 // remove from cache |
238 // remove from cache |
239 if ( $dp = @opendir(ENANO_ROOT . '/cache/') ) |
239 if ( $dp = @opendir(ENANO_ROOT . '/cache/') ) |
240 { |
240 { |
241 $regexp = '#' . preg_quote($row['filename']) . '-' . $row['time_id'] . '-[0-9]+x[0-9]+' . preg_quote($row['file_extension']) . '#'; |
241 $regexp = '#' . preg_quote($row['filename']) . '-' . $row['time_id'] . '-[0-9]+x[0-9]+' . preg_quote($row['file_extension']) . '#'; |
242 while ( $dh = @readdir($dp) ) |
242 while ( $dh = @readdir($dp) ) |
243 { |
243 { |
244 if ( preg_match($regexp, $dh) ) |
244 if ( preg_match($regexp, $dh) ) |
245 { |
245 { |
246 // it's a match, delete the cached thumbnail |
246 // it's a match, delete the cached thumbnail |
247 @unlink(ENANO_ROOT . "/cache/$dh"); |
247 @unlink(ENANO_ROOT . "/cache/$dh"); |
248 } |
248 } |
249 } |
249 } |
250 closedir($dp); |
250 closedir($dp); |
251 } |
251 } |
252 |
252 |
253 // remove from database |
253 // remove from database |
254 $q = $db->sql_query('DELETE FROM ' . table_prefix . "files WHERE file_id = $file_id;"); |
254 $q = $db->sql_query('DELETE FROM ' . table_prefix . "files WHERE file_id = $file_id;"); |
255 if ( !$q ) |
255 if ( !$q ) |
256 $db->_die(); |
256 $db->_die(); |
257 |
257 |
258 // remove from logs |
258 // remove from logs |
259 $page_id_db = $db->escape($row['page_id']); |
259 $page_id_db = $db->escape($row['page_id']); |
260 $q = $db->sql_query('DELETE FROM ' . table_prefix . "logs WHERE page_id = '{$page_id_db}' AND namespace = 'File' AND action = 'reupload' AND time_id = {$row['time_id']};"); |
260 $q = $db->sql_query('DELETE FROM ' . table_prefix . "logs WHERE page_id = '{$page_id_db}' AND namespace = 'File' AND action = 'reupload' AND time_id = {$row['time_id']};"); |
261 if ( !$q ) |
261 if ( !$q ) |
262 $db->_die(); |
262 $db->_die(); |
263 |
263 |
264 return true; |
264 return true; |
265 } |
265 } |
266 } |
266 } |
267 |
267 |