|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* This file doing the job of attachments and avatars maintenance and management. |
|
5
|
|
|
* @todo refactor as controller-model |
|
6
|
|
|
* |
|
7
|
|
|
* Simple Machines Forum (SMF) |
|
8
|
|
|
* |
|
9
|
|
|
* @package SMF |
|
10
|
|
|
* @author Simple Machines http://www.simplemachines.org |
|
11
|
|
|
* @copyright 2016 Simple Machines and individual contributors |
|
12
|
|
|
* @license http://www.simplemachines.org/about/smf/license.php BSD |
|
13
|
|
|
* |
|
14
|
|
|
* @version 2.1 Beta 3 |
|
15
|
|
|
*/ |
|
16
|
|
|
|
|
17
|
|
|
if (!defined('SMF')) |
|
18
|
|
|
die('No direct access...'); |
|
19
|
|
|
|
|
20
|
|
|
/** |
|
21
|
|
|
* The main 'Attachments and Avatars' management function. |
|
22
|
|
|
* This function is the entry point for index.php?action=admin;area=manageattachments |
|
23
|
|
|
* and it calls a function based on the sub-action. |
|
24
|
|
|
* It requires the manage_attachments permission. |
|
25
|
|
|
* |
|
26
|
|
|
* @uses ManageAttachments template. |
|
27
|
|
|
* @uses Admin language file. |
|
28
|
|
|
* @uses template layer 'manage_files' for showing the tab bar. |
|
29
|
|
|
* |
|
30
|
|
|
*/ |
|
31
|
|
|
function ManageAttachments() |
|
32
|
|
|
{ |
|
33
|
|
|
global $txt, $context; |
|
34
|
|
|
|
|
35
|
|
|
// You have to be able to moderate the forum to do this. |
|
36
|
|
|
isAllowedTo('manage_attachments'); |
|
37
|
|
|
|
|
38
|
|
|
// Setup the template stuff we'll probably need. |
|
39
|
|
|
loadTemplate('ManageAttachments'); |
|
40
|
|
|
|
|
41
|
|
|
// If they want to delete attachment(s), delete them. (otherwise fall through..) |
|
42
|
|
|
$subActions = array( |
|
43
|
|
|
'attachments' => 'ManageAttachmentSettings', |
|
44
|
|
|
'attachpaths' => 'ManageAttachmentPaths', |
|
45
|
|
|
'avatars' => 'ManageAvatarSettings', |
|
46
|
|
|
'browse' => 'BrowseFiles', |
|
47
|
|
|
'byAge' => 'RemoveAttachmentByAge', |
|
48
|
|
|
'bySize' => 'RemoveAttachmentBySize', |
|
49
|
|
|
'maintenance' => 'MaintainFiles', |
|
50
|
|
|
'repair' => 'RepairAttachments', |
|
51
|
|
|
'remove' => 'RemoveAttachment', |
|
52
|
|
|
'removeall' => 'RemoveAllAttachments', |
|
53
|
|
|
'transfer' => 'TransferAttachments', |
|
54
|
|
|
); |
|
55
|
|
|
|
|
56
|
|
|
// This uses admin tabs - as it should! |
|
57
|
|
|
$context[$context['admin_menu_name']]['tab_data'] = array( |
|
58
|
|
|
'title' => $txt['attachments_avatars'], |
|
59
|
|
|
'help' => 'manage_files', |
|
60
|
|
|
'description' => $txt['attachments_desc'], |
|
61
|
|
|
); |
|
62
|
|
|
|
|
63
|
|
|
call_integration_hook('integrate_manage_attachments', array(&$subActions)); |
|
64
|
|
|
|
|
65
|
|
|
// Pick the correct sub-action. |
|
66
|
|
|
if (isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']])) |
|
67
|
|
|
$context['sub_action'] = $_REQUEST['sa']; |
|
68
|
|
|
else |
|
69
|
|
|
$context['sub_action'] = 'browse'; |
|
70
|
|
|
|
|
71
|
|
|
// Default page title is good. |
|
72
|
|
|
$context['page_title'] = $txt['attachments_avatars']; |
|
73
|
|
|
|
|
74
|
|
|
// Finally fall through to what we are doing. |
|
75
|
|
|
call_helper($subActions[$context['sub_action']]); |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
/** |
|
79
|
|
|
* Allows to show/change attachment settings. |
|
80
|
|
|
* This is the default sub-action of the 'Attachments and Avatars' center. |
|
81
|
|
|
* Called by index.php?action=admin;area=manageattachments;sa=attachments. |
|
82
|
|
|
* |
|
83
|
|
|
* @param bool $return_config Whether to return the array of config variables (used for admin search) |
|
84
|
|
|
* @return void|array If $return_config is true, simply returns the config_vars array, otherwise returns nothing |
|
85
|
|
|
* @uses 'attachments' sub template. |
|
86
|
|
|
*/ |
|
87
|
|
|
|
|
88
|
|
|
function ManageAttachmentSettings($return_config = false) |
|
89
|
|
|
{ |
|
90
|
|
|
global $txt, $modSettings, $scripturl, $context, $sourcedir, $boarddir; |
|
91
|
|
|
|
|
92
|
|
|
require_once($sourcedir . '/Subs-Attachments.php'); |
|
93
|
|
|
|
|
94
|
|
|
$context['attachmentUploadDir'] = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']]; |
|
95
|
|
|
|
|
96
|
|
|
// If not set, show a default path for the base directory |
|
97
|
|
|
if (!isset($_GET['save']) && empty($modSettings['basedirectory_for_attachments'])) |
|
98
|
|
View Code Duplication |
if (is_dir($modSettings['attachmentUploadDir'][1])) |
|
|
|
|
|
|
99
|
|
|
$modSettings['basedirectory_for_attachments'] = $modSettings['attachmentUploadDir'][1]; |
|
100
|
|
|
|
|
101
|
|
|
else |
|
102
|
|
|
$modSettings['basedirectory_for_attachments'] = $context['attachmentUploadDir']; |
|
103
|
|
|
|
|
104
|
|
|
$context['valid_upload_dir'] = is_dir($context['attachmentUploadDir']) && is_writable($context['attachmentUploadDir']); |
|
105
|
|
|
|
|
106
|
|
|
if (!empty($modSettings['automanage_attachments'])) |
|
107
|
|
|
$context['valid_basedirectory'] = !empty($modSettings['basedirectory_for_attachments']) && is_writable($modSettings['basedirectory_for_attachments']); |
|
108
|
|
|
|
|
109
|
|
|
else |
|
110
|
|
|
$context['valid_basedirectory'] = true; |
|
111
|
|
|
|
|
112
|
|
|
// A bit of razzle dazzle with the $txt strings. :) |
|
113
|
|
|
$txt['attachment_path'] = $context['attachmentUploadDir']; |
|
114
|
|
|
$txt['basedirectory_for_attachments_path']= isset($modSettings['basedirectory_for_attachments']) ? $modSettings['basedirectory_for_attachments'] : ''; |
|
115
|
|
|
$txt['use_subdirectories_for_attachments_note'] = empty($modSettings['attachment_basedirectories']) || empty($modSettings['use_subdirectories_for_attachments']) ? $txt['use_subdirectories_for_attachments_note'] : ''; |
|
116
|
|
|
$txt['attachmentUploadDir_multiple_configure'] = '<a href="' . $scripturl . '?action=admin;area=manageattachments;sa=attachpaths">[' . $txt['attachmentUploadDir_multiple_configure'] . ']</a>'; |
|
117
|
|
|
$txt['attach_current_dir'] = empty($modSettings['automanage_attachments']) ? $txt['attach_current_dir'] : $txt['attach_last_dir']; |
|
118
|
|
|
$txt['attach_current_dir_warning'] = $txt['attach_current_dir'] . $txt['attach_current_dir_warning']; |
|
119
|
|
|
$txt['basedirectory_for_attachments_warning'] = $txt['basedirectory_for_attachments_current'] . $txt['basedirectory_for_attachments_warning']; |
|
120
|
|
|
|
|
121
|
|
|
// Perform a test to see if the GD module or ImageMagick are installed. |
|
122
|
|
|
$testImg = get_extension_funcs('gd') || class_exists('Imagick') || get_extension_funcs('MagickWand'); |
|
123
|
|
|
|
|
124
|
|
|
// See if we can find if the server is set up to support the attachment limits |
|
125
|
|
|
$post_max_size = ini_get('post_max_size'); |
|
126
|
|
|
$upload_max_filesize = ini_get('upload_max_filesize'); |
|
127
|
|
|
$testPM = !empty($post_max_size) ? (memoryReturnBytes($post_max_size) >= (isset($modSettings['attachmentPostLimit']) ? $modSettings['attachmentPostLimit'] * 1024 : 0)) : true; |
|
128
|
|
|
$testUM = !empty($upload_max_filesize) ? (memoryReturnBytes($upload_max_filesize) >= (isset($modSettings['attachmentSizeLimit']) ? $modSettings['attachmentSizeLimit'] * 1024 : 0)) : true; |
|
129
|
|
|
|
|
130
|
|
|
$config_vars = array( |
|
131
|
|
|
array('title', 'attachment_manager_settings'), |
|
132
|
|
|
// Are attachments enabled? |
|
133
|
|
|
array('select', 'attachmentEnable', array($txt['attachmentEnable_deactivate'], $txt['attachmentEnable_enable_all'], $txt['attachmentEnable_disable_new'])), |
|
134
|
|
|
'', |
|
135
|
|
|
// Directory and size limits. |
|
136
|
|
|
array('select', 'automanage_attachments', array(0 => $txt['attachments_normal'], 1 => $txt['attachments_auto_space'], 2 => $txt['attachments_auto_years'], 3 => $txt['attachments_auto_months'], 4 => $txt['attachments_auto_16'])), |
|
137
|
|
|
array('check', 'use_subdirectories_for_attachments', 'subtext' => $txt['use_subdirectories_for_attachments_note']), |
|
138
|
|
|
(empty($modSettings['attachment_basedirectories']) ? array('text', 'basedirectory_for_attachments', 40,) : array('var_message', 'basedirectory_for_attachments', 'message' => 'basedirectory_for_attachments_path', 'invalid' => empty($context['valid_basedirectory']), 'text_label' => (!empty($context['valid_basedirectory']) ? $txt['basedirectory_for_attachments_current'] : $txt['basedirectory_for_attachments_warning']))), |
|
139
|
|
|
empty($modSettings['attachment_basedirectories']) && $modSettings['currentAttachmentUploadDir'] == 1 && count($modSettings['attachmentUploadDir']) == 1 ? array('json', 'attachmentUploadDir', 'subtext' => $txt['attachmentUploadDir_multiple_configure'], 40, 'invalid' => !$context['valid_upload_dir'], 'disabled' => true) : array('var_message', 'attach_current_directory', 'subtext' => $txt['attachmentUploadDir_multiple_configure'], 'message' => 'attachment_path', 'invalid' => empty($context['valid_upload_dir']), 'text_label' => (!empty($context['valid_upload_dir']) ? $txt['attach_current_dir'] : $txt['attach_current_dir_warning'])), |
|
140
|
|
|
array('int', 'attachmentDirFileLimit', 'subtext' => $txt['zero_for_no_limit'], 6), |
|
141
|
|
|
array('int', 'attachmentDirSizeLimit', 'subtext' => $txt['zero_for_no_limit'], 6, 'postinput' => $txt['kilobyte']), |
|
142
|
|
|
array('check', 'dont_show_attach_under_post', 'subtext' => $txt['dont_show_attach_under_post_sub']), |
|
143
|
|
|
'', |
|
144
|
|
|
// Posting limits |
|
145
|
|
|
array('int', 'attachmentPostLimit', 'subtext' => $txt['zero_for_no_limit'], 6, 'postinput' => $txt['kilobyte']), |
|
146
|
|
|
array('warning', empty($testPM) ? 'attachment_postsize_warning' : ''), |
|
147
|
|
|
array('int', 'attachmentSizeLimit', 'subtext' => $txt['zero_for_no_limit'], 6, 'postinput' => $txt['kilobyte']), |
|
148
|
|
|
array('warning', empty($testUM) ? 'attachment_filesize_warning' : ''), |
|
149
|
|
|
array('int', 'attachmentNumPerPostLimit', 'subtext' => $txt['zero_for_no_limit'], 6), |
|
150
|
|
|
// Security Items |
|
151
|
|
|
array('title', 'attachment_security_settings'), |
|
152
|
|
|
// Extension checks etc. |
|
153
|
|
|
array('check', 'attachmentCheckExtensions'), |
|
154
|
|
|
array('text', 'attachmentExtensions', 40), |
|
155
|
|
|
'', |
|
156
|
|
|
// Image checks. |
|
157
|
|
|
array('warning', empty($testImg) ? 'attachment_img_enc_warning' : ''), |
|
158
|
|
|
array('check', 'attachment_image_reencode'), |
|
159
|
|
|
'', |
|
160
|
|
|
array('warning', 'attachment_image_paranoid_warning'), |
|
161
|
|
|
array('check', 'attachment_image_paranoid'), |
|
162
|
|
|
// Thumbnail settings. |
|
163
|
|
|
array('title', 'attachment_thumbnail_settings'), |
|
164
|
|
|
array('check', 'attachmentShowImages'), |
|
165
|
|
|
array('check', 'attachmentThumbnails'), |
|
166
|
|
|
array('check', 'attachment_thumb_png'), |
|
167
|
|
|
array('check', 'attachment_thumb_memory'), |
|
168
|
|
|
array('warning', 'attachment_thumb_memory_note'), |
|
169
|
|
|
array('text', 'attachmentThumbWidth', 6), |
|
170
|
|
|
array('text', 'attachmentThumbHeight', 6), |
|
171
|
|
|
'', |
|
172
|
|
|
array('int', 'max_image_width', 'subtext' => $txt['zero_for_no_limit']), |
|
173
|
|
|
array('int', 'max_image_height', 'subtext' => $txt['zero_for_no_limit']), |
|
174
|
|
|
); |
|
175
|
|
|
|
|
176
|
|
|
$context['settings_post_javascript'] = ' |
|
177
|
|
|
var storing_type = document.getElementById(\'automanage_attachments\'); |
|
178
|
|
|
var base_dir = document.getElementById(\'use_subdirectories_for_attachments\'); |
|
179
|
|
|
|
|
180
|
|
|
createEventListener(storing_type) |
|
181
|
|
|
storing_type.addEventListener("change", toggleSubDir, false); |
|
182
|
|
|
createEventListener(base_dir) |
|
183
|
|
|
base_dir.addEventListener("change", toggleSubDir, false); |
|
184
|
|
|
toggleSubDir();'; |
|
185
|
|
|
|
|
186
|
|
|
call_integration_hook('integrate_modify_attachment_settings', array(&$config_vars)); |
|
187
|
|
|
|
|
188
|
|
|
if ($return_config) |
|
189
|
|
|
return $config_vars; |
|
190
|
|
|
|
|
191
|
|
|
// These are very likely to come in handy! (i.e. without them we're doomed!) |
|
192
|
|
|
require_once($sourcedir . '/ManagePermissions.php'); |
|
193
|
|
|
require_once($sourcedir . '/ManageServer.php'); |
|
194
|
|
|
|
|
195
|
|
|
// Saving settings? |
|
196
|
|
|
if (isset($_GET['save'])) |
|
197
|
|
|
{ |
|
198
|
|
|
checkSession(); |
|
199
|
|
|
|
|
200
|
|
|
if (isset($_POST['attachmentUploadDir'])) |
|
201
|
|
|
unset($_POST['attachmentUploadDir']); |
|
202
|
|
|
|
|
203
|
|
|
if (!empty($_POST['use_subdirectories_for_attachments'])) |
|
204
|
|
|
{ |
|
205
|
|
|
if (isset($_POST['use_subdirectories_for_attachments']) && empty($_POST['basedirectory_for_attachments'])) |
|
206
|
|
|
$_POST['basedirectory_for_attachments'] = (!empty($modSettings['basedirectory_for_attachments']) ? ($modSettings['basedirectory_for_attachments']) : $boarddir); |
|
207
|
|
|
|
|
208
|
|
View Code Duplication |
if (!empty($_POST['use_subdirectories_for_attachments']) && !empty($modSettings['attachment_basedirectories'])) |
|
|
|
|
|
|
209
|
|
|
{ |
|
210
|
|
|
if (!is_array($modSettings['attachment_basedirectories'])) |
|
211
|
|
|
$modSettings['attachment_basedirectories'] = smf_json_decode($modSettings['attachment_basedirectories'], true); |
|
212
|
|
|
} |
|
213
|
|
|
else |
|
214
|
|
|
$modSettings['attachment_basedirectories'] = array(); |
|
215
|
|
|
|
|
216
|
|
|
if (!empty($_POST['use_subdirectories_for_attachments']) && !empty($_POST['basedirectory_for_attachments']) && !in_array($_POST['basedirectory_for_attachments'], $modSettings['attachment_basedirectories'])) |
|
217
|
|
|
{ |
|
218
|
|
|
$currentAttachmentUploadDir = $modSettings['currentAttachmentUploadDir']; |
|
219
|
|
|
|
|
220
|
|
|
if (!in_array($_POST['basedirectory_for_attachments'], $modSettings['attachmentUploadDir'])) |
|
221
|
|
|
{ |
|
222
|
|
|
if (!automanage_attachments_create_directory($_POST['basedirectory_for_attachments'])) |
|
223
|
|
|
$_POST['basedirectory_for_attachments'] = $modSettings['basedirectory_for_attachments']; |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
if (!in_array($_POST['basedirectory_for_attachments'], $modSettings['attachment_basedirectories'])) |
|
227
|
|
|
{ |
|
228
|
|
|
$modSettings['attachment_basedirectories'][$modSettings['currentAttachmentUploadDir']] = $_POST['basedirectory_for_attachments']; |
|
229
|
|
|
updateSettings(array( |
|
230
|
|
|
'attachment_basedirectories' => json_encode($modSettings['attachment_basedirectories']), |
|
231
|
|
|
'currentAttachmentUploadDir' => $currentAttachmentUploadDir, |
|
232
|
|
|
)); |
|
233
|
|
|
|
|
234
|
|
|
$_POST['use_subdirectories_for_attachments'] = 1; |
|
235
|
|
|
$_POST['attachmentUploadDir'] = json_encode($modSettings['attachmentUploadDir']); |
|
236
|
|
|
|
|
237
|
|
|
} |
|
238
|
|
|
} |
|
239
|
|
|
} |
|
240
|
|
|
|
|
241
|
|
|
call_integration_hook('integrate_save_attachment_settings'); |
|
242
|
|
|
|
|
243
|
|
|
saveDBSettings($config_vars); |
|
244
|
|
|
$_SESSION['adm-save'] = true; |
|
245
|
|
|
redirectexit('action=admin;area=manageattachments;sa=attachments'); |
|
246
|
|
|
} |
|
247
|
|
|
|
|
248
|
|
|
$context['post_url'] = $scripturl . '?action=admin;area=manageattachments;save;sa=attachments'; |
|
249
|
|
|
prepareDBSettingContext($config_vars); |
|
250
|
|
|
|
|
251
|
|
|
$context['sub_template'] = 'show_settings'; |
|
252
|
|
|
} |
|
253
|
|
|
|
|
254
|
|
|
/** |
|
255
|
|
|
* This allows to show/change avatar settings. |
|
256
|
|
|
* Called by index.php?action=admin;area=manageattachments;sa=avatars. |
|
257
|
|
|
* Show/set permissions for permissions: 'profile_server_avatar', |
|
258
|
|
|
* 'profile_upload_avatar' and 'profile_remote_avatar'. |
|
259
|
|
|
* |
|
260
|
|
|
* @param bool $return_config Whether to return the config_vars array (used for admin search) |
|
261
|
|
|
* @return void|array Returns the config_vars array if $return_config is true, otherwise returns nothing |
|
262
|
|
|
* @uses 'avatars' sub template. |
|
263
|
|
|
*/ |
|
264
|
|
|
function ManageAvatarSettings($return_config = false) |
|
265
|
|
|
{ |
|
266
|
|
|
global $txt, $context, $modSettings, $sourcedir, $scripturl; |
|
267
|
|
|
global $boarddir, $boardurl; |
|
268
|
|
|
|
|
269
|
|
|
// Perform a test to see if the GD module or ImageMagick are installed. |
|
270
|
|
|
$testImg = get_extension_funcs('gd') || class_exists('Imagick'); |
|
271
|
|
|
|
|
272
|
|
|
$context['valid_avatar_dir'] = is_dir($modSettings['avatar_directory']); |
|
273
|
|
|
$context['valid_custom_avatar_dir'] = !empty($modSettings['custom_avatar_dir']) && is_dir($modSettings['custom_avatar_dir']) && is_writable($modSettings['custom_avatar_dir']); |
|
274
|
|
|
|
|
275
|
|
|
$config_vars = array( |
|
276
|
|
|
// Server stored avatars! |
|
277
|
|
|
array('title', 'avatar_server_stored'), |
|
278
|
|
|
array('warning', empty($testImg) ? 'avatar_img_enc_warning' : ''), |
|
279
|
|
|
array('permissions', 'profile_server_avatar', 0, $txt['avatar_server_stored_groups']), |
|
280
|
|
|
array('warning', !$context['valid_avatar_dir'] ? 'avatar_directory_wrong' : ''), |
|
281
|
|
|
array('text', 'avatar_directory', 40, 'invalid' => !$context['valid_avatar_dir']), |
|
282
|
|
|
array('text', 'avatar_url', 40), |
|
283
|
|
|
// External avatars? |
|
284
|
|
|
array('title', 'avatar_external'), |
|
285
|
|
|
array('permissions', 'profile_remote_avatar', 0, $txt['avatar_external_url_groups']), |
|
286
|
|
|
array('check', 'avatar_download_external', 0, 'onchange' => 'fUpdateStatus();'), |
|
287
|
|
|
array('text', 'avatar_max_width_external', 'subtext' => $txt['zero_for_no_limit'], 6), |
|
288
|
|
|
array('text', 'avatar_max_height_external', 'subtext' => $txt['zero_for_no_limit'], 6), |
|
289
|
|
|
array('select', 'avatar_action_too_large', |
|
290
|
|
|
array( |
|
291
|
|
|
'option_refuse' => $txt['option_refuse'], |
|
292
|
|
|
'option_css_resize' => $txt['option_css_resize'], |
|
293
|
|
|
'option_download_and_resize' => $txt['option_download_and_resize'], |
|
294
|
|
|
), |
|
295
|
|
|
), |
|
296
|
|
|
// Uploadable avatars? |
|
297
|
|
|
array('title', 'avatar_upload'), |
|
298
|
|
|
array('permissions', 'profile_upload_avatar', 0, $txt['avatar_upload_groups']), |
|
299
|
|
|
array('text', 'avatar_max_width_upload', 'subtext' => $txt['zero_for_no_limit'], 6), |
|
300
|
|
|
array('text', 'avatar_max_height_upload', 'subtext' => $txt['zero_for_no_limit'], 6), |
|
301
|
|
|
array('check', 'avatar_resize_upload', 'subtext' => $txt['avatar_resize_upload_note']), |
|
302
|
|
|
array('check', 'avatar_download_png'), |
|
303
|
|
|
array('check', 'avatar_reencode'), |
|
304
|
|
|
'', |
|
305
|
|
|
array('warning', 'avatar_paranoid_warning'), |
|
306
|
|
|
array('check', 'avatar_paranoid'), |
|
307
|
|
|
'', |
|
308
|
|
|
array('warning', !$context['valid_custom_avatar_dir'] ? 'custom_avatar_dir_wrong' : ''), |
|
309
|
|
|
array('text', 'custom_avatar_dir', 40, 'subtext' => $txt['custom_avatar_dir_desc'], 'invalid' => !$context['valid_custom_avatar_dir']), |
|
310
|
|
|
array('text', 'custom_avatar_url', 40), |
|
311
|
|
|
// Grvatars? |
|
312
|
|
|
array('title', 'gravatar_settings'), |
|
313
|
|
|
array('check', 'gravatarEnabled'), |
|
314
|
|
|
array('check', 'gravatarOverride'), |
|
315
|
|
|
array('check', 'gravatarAllowExtraEmail'), |
|
316
|
|
|
'', |
|
317
|
|
|
array('select', 'gravatarMaxRating', |
|
318
|
|
|
array( |
|
319
|
|
|
'G' => $txt['gravatar_maxG'], |
|
320
|
|
|
'PG' => $txt['gravatar_maxPG'], |
|
321
|
|
|
'R' => $txt['gravatar_maxR'], |
|
322
|
|
|
'X' => $txt['gravatar_maxX'], |
|
323
|
|
|
), |
|
324
|
|
|
), |
|
325
|
|
|
array('select', 'gravatarDefault', |
|
326
|
|
|
array( |
|
327
|
|
|
'mm' => $txt['gravatar_mm'], |
|
328
|
|
|
'identicon' => $txt['gravatar_identicon'], |
|
329
|
|
|
'monsterid' => $txt['gravatar_monsterid'], |
|
330
|
|
|
'wavatar' => $txt['gravatar_wavatar'], |
|
331
|
|
|
'retro' => $txt['gravatar_retro'], |
|
332
|
|
|
'blank' => $txt['gravatar_blank'], |
|
333
|
|
|
), |
|
334
|
|
|
), |
|
335
|
|
|
); |
|
336
|
|
|
|
|
337
|
|
|
call_integration_hook('integrate_modify_avatar_settings', array(&$config_vars)); |
|
338
|
|
|
|
|
339
|
|
|
if ($return_config) |
|
340
|
|
|
return $config_vars; |
|
341
|
|
|
|
|
342
|
|
|
// We need this file for the settings template. |
|
343
|
|
|
require_once($sourcedir . '/ManageServer.php'); |
|
344
|
|
|
|
|
345
|
|
|
// Saving avatar settings? |
|
346
|
|
|
if (isset($_GET['save'])) |
|
347
|
|
|
{ |
|
348
|
|
|
checkSession(); |
|
349
|
|
|
|
|
350
|
|
|
// These settings cannot be left empty! |
|
351
|
|
|
if (empty($_POST['custom_avatar_dir'])) |
|
352
|
|
|
$_POST['custom_avatar_dir'] = $boarddir .'/custom_avatar'; |
|
353
|
|
|
|
|
354
|
|
|
if (empty($_POST['custom_avatar_url'])) |
|
355
|
|
|
$_POST['custom_avatar_url'] = $boardurl .'/custom_avatar'; |
|
356
|
|
|
|
|
357
|
|
|
if (empty($_POST['avatar_directory'])) |
|
358
|
|
|
$_POST['avatar_directory'] = $boarddir .'/avatars'; |
|
359
|
|
|
|
|
360
|
|
|
if (empty($_POST['avatar_url'])) |
|
361
|
|
|
$_POST['avatar_url'] = $boardurl .'/avatars'; |
|
362
|
|
|
|
|
363
|
|
|
call_integration_hook('integrate_save_avatar_settings'); |
|
364
|
|
|
|
|
365
|
|
|
saveDBSettings($config_vars); |
|
366
|
|
|
$_SESSION['adm-save'] = true; |
|
367
|
|
|
redirectexit('action=admin;area=manageattachments;sa=avatars'); |
|
368
|
|
|
} |
|
369
|
|
|
|
|
370
|
|
|
// Attempt to figure out if the admin is trying to break things. |
|
371
|
|
|
$context['settings_save_onclick'] = 'return (document.getElementById(\'custom_avatar_dir\').value == \'\' || document.getElementById(\'custom_avatar_url\').value == \'\') ? confirm(\'' . $txt['custom_avatar_check_empty'] . '\') : true;'; |
|
372
|
|
|
|
|
373
|
|
|
// We need this for the in-line permissions |
|
374
|
|
|
createToken('admin-mp'); |
|
375
|
|
|
|
|
376
|
|
|
// Prepare the context. |
|
377
|
|
|
$context['post_url'] = $scripturl . '?action=admin;area=manageattachments;save;sa=avatars'; |
|
378
|
|
|
prepareDBSettingContext($config_vars); |
|
379
|
|
|
|
|
380
|
|
|
// Add a layer for the javascript. |
|
381
|
|
|
$context['template_layers'][] = 'avatar_settings'; |
|
382
|
|
|
$context['sub_template'] = 'show_settings'; |
|
383
|
|
|
} |
|
384
|
|
|
|
|
385
|
|
|
/** |
|
386
|
|
|
* Show a list of attachment or avatar files. |
|
387
|
|
|
* Called by ?action=admin;area=manageattachments;sa=browse for attachments |
|
388
|
|
|
* and ?action=admin;area=manageattachments;sa=browse;avatars for avatars. |
|
389
|
|
|
* Allows sorting by name, date, size and member. |
|
390
|
|
|
* Paginates results. |
|
391
|
|
|
*/ |
|
392
|
|
|
function BrowseFiles() |
|
393
|
|
|
{ |
|
394
|
|
|
global $context, $txt, $scripturl, $modSettings; |
|
395
|
|
|
global $smcFunc, $sourcedir, $settings; |
|
396
|
|
|
|
|
397
|
|
|
// Attachments or avatars? |
|
398
|
|
|
$context['browse_type'] = isset($_REQUEST['avatars']) ? 'avatars' : (isset($_REQUEST['thumbs']) ? 'thumbs' : 'attachments'); |
|
399
|
|
|
|
|
400
|
|
|
$titles = array( |
|
401
|
|
|
'attachments' => array('?action=admin;area=manageattachments;sa=browse', $txt['attachment_manager_attachments']), |
|
402
|
|
|
'avatars' => array('?action=admin;area=manageattachments;sa=browse;avatars', $txt['attachment_manager_avatars']), |
|
403
|
|
|
'thumbs' => array('?action=admin;area=manageattachments;sa=browse;thumbs', $txt['attachment_manager_thumbs']), |
|
404
|
|
|
); |
|
405
|
|
|
|
|
406
|
|
|
$list_title = $txt['attachment_manager_browse_files'] . ': '; |
|
407
|
|
|
foreach ($titles as $browse_type => $details) |
|
408
|
|
|
{ |
|
409
|
|
|
if ($browse_type != 'attachments') |
|
410
|
|
|
$list_title .= ' | '; |
|
411
|
|
|
|
|
412
|
|
|
if ($context['browse_type'] == $browse_type) |
|
413
|
|
|
$list_title .= '<img src="' . $settings['images_url'] . '/selected.png" alt=">"> '; |
|
414
|
|
|
|
|
415
|
|
|
$list_title .= '<a href="' . $scripturl . $details[0] . '">' . $details[1] . '</a>'; |
|
416
|
|
|
} |
|
417
|
|
|
|
|
418
|
|
|
// Set the options for the list component. |
|
419
|
|
|
$listOptions = array( |
|
420
|
|
|
'id' => 'file_list', |
|
421
|
|
|
'title' => $list_title, |
|
422
|
|
|
'items_per_page' => $modSettings['defaultMaxListItems'], |
|
423
|
|
|
'base_href' => $scripturl . '?action=admin;area=manageattachments;sa=browse' . ($context['browse_type'] === 'avatars' ? ';avatars' : ($context['browse_type'] === 'thumbs' ? ';thumbs' : '')), |
|
424
|
|
|
'default_sort_col' => 'name', |
|
425
|
|
|
'no_items_label' => $txt['attachment_manager_' . ($context['browse_type'] === 'avatars' ? 'avatars' : ( $context['browse_type'] === 'thumbs' ? 'thumbs' : 'attachments')) . '_no_entries'], |
|
426
|
|
|
'get_items' => array( |
|
427
|
|
|
'function' => 'list_getFiles', |
|
428
|
|
|
'params' => array( |
|
429
|
|
|
$context['browse_type'], |
|
430
|
|
|
), |
|
431
|
|
|
), |
|
432
|
|
|
'get_count' => array( |
|
433
|
|
|
'function' => 'list_getNumFiles', |
|
434
|
|
|
'params' => array( |
|
435
|
|
|
$context['browse_type'], |
|
436
|
|
|
), |
|
437
|
|
|
), |
|
438
|
|
|
'columns' => array( |
|
439
|
|
|
'name' => array( |
|
440
|
|
|
'header' => array( |
|
441
|
|
|
'value' => $txt['attachment_name'], |
|
442
|
|
|
), |
|
443
|
|
|
'data' => array( |
|
444
|
|
|
'function' => function ($rowData) use ($modSettings, $context, $scripturl, $smcFunc) |
|
445
|
|
|
{ |
|
446
|
|
|
$link = '<a href="'; |
|
447
|
|
|
|
|
448
|
|
|
// In case of a custom avatar URL attachments have a fixed directory. |
|
449
|
|
|
if ($rowData['attachment_type'] == 1) |
|
450
|
|
|
$link .= sprintf('%1$s/%2$s', $modSettings['custom_avatar_url'], $rowData['filename']); |
|
451
|
|
|
|
|
452
|
|
|
// By default avatars are downloaded almost as attachments. |
|
453
|
|
|
elseif ($context['browse_type'] == 'avatars') |
|
454
|
|
|
$link .= sprintf('%1$s?action=dlattach;type=avatar;attach=%2$d', $scripturl, $rowData['id_attach']); |
|
455
|
|
|
|
|
456
|
|
|
// Normal attachments are always linked to a topic ID. |
|
457
|
|
|
else |
|
458
|
|
|
$link .= sprintf('%1$s?action=dlattach;topic=%2$d.0;attach=%3$d', $scripturl, $rowData['id_topic'], $rowData['id_attach']); |
|
459
|
|
|
|
|
460
|
|
|
$link .= '"'; |
|
461
|
|
|
|
|
462
|
|
|
// Show a popup on click if it's a picture and we know its dimensions. |
|
463
|
|
|
if (!empty($rowData['width']) && !empty($rowData['height'])) |
|
464
|
|
|
$link .= sprintf(' onclick="return reqWin(this.href' . ($rowData['attachment_type'] == 1 ? '' : ' + \';image\'') . ', %1$d, %2$d, true);"', $rowData['width'] + 20, $rowData['height'] + 20); |
|
465
|
|
|
|
|
466
|
|
|
$link .= sprintf('>%1$s</a>', preg_replace('~&#(\\\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\\\1;', $smcFunc['htmlspecialchars']($rowData['filename']))); |
|
467
|
|
|
|
|
468
|
|
|
// Show the dimensions. |
|
469
|
|
|
if (!empty($rowData['width']) && !empty($rowData['height'])) |
|
470
|
|
|
$link .= sprintf(' <span class="smalltext">%1$dx%2$d</span>', $rowData['width'], $rowData['height']); |
|
471
|
|
|
|
|
472
|
|
|
return $link; |
|
473
|
|
|
}, |
|
474
|
|
|
), |
|
475
|
|
|
'sort' => array( |
|
476
|
|
|
'default' => 'a.filename', |
|
477
|
|
|
'reverse' => 'a.filename DESC', |
|
478
|
|
|
), |
|
479
|
|
|
), |
|
480
|
|
|
'filesize' => array( |
|
481
|
|
|
'header' => array( |
|
482
|
|
|
'value' => $txt['attachment_file_size'], |
|
483
|
|
|
), |
|
484
|
|
|
'data' => array( |
|
485
|
|
|
'function' => function ($rowData) use ($txt) |
|
486
|
|
|
{ |
|
487
|
|
|
return sprintf('%1$s%2$s', round($rowData['size'] / 1024, 2), $txt['kilobyte']); |
|
488
|
|
|
}, |
|
489
|
|
|
), |
|
490
|
|
|
'sort' => array( |
|
491
|
|
|
'default' => 'a.size', |
|
492
|
|
|
'reverse' => 'a.size DESC', |
|
493
|
|
|
), |
|
494
|
|
|
), |
|
495
|
|
|
'member' => array( |
|
496
|
|
|
'header' => array( |
|
497
|
|
|
'value' => $context['browse_type'] == 'avatars' ? $txt['attachment_manager_member'] : $txt['posted_by'], |
|
498
|
|
|
), |
|
499
|
|
|
'data' => array( |
|
500
|
|
|
'function' => function ($rowData) use ($scripturl, $smcFunc) |
|
501
|
|
|
{ |
|
502
|
|
|
// In case of an attachment, return the poster of the attachment. |
|
503
|
|
|
if (empty($rowData['id_member'])) |
|
504
|
|
|
return $smcFunc['htmlspecialchars']($rowData['poster_name']); |
|
505
|
|
|
|
|
506
|
|
|
// Otherwise it must be an avatar, return the link to the owner of it. |
|
507
|
|
|
else |
|
508
|
|
|
return sprintf('<a href="%1$s?action=profile;u=%2$d">%3$s</a>', $scripturl, $rowData['id_member'], $rowData['poster_name']); |
|
509
|
|
|
}, |
|
510
|
|
|
), |
|
511
|
|
|
'sort' => array( |
|
512
|
|
|
'default' => 'mem.real_name', |
|
513
|
|
|
'reverse' => 'mem.real_name DESC', |
|
514
|
|
|
), |
|
515
|
|
|
), |
|
516
|
|
|
'date' => array( |
|
517
|
|
|
'header' => array( |
|
518
|
|
|
'value' => $context['browse_type'] == 'avatars' ? $txt['attachment_manager_last_active'] : $txt['date'], |
|
519
|
|
|
), |
|
520
|
|
|
'data' => array( |
|
521
|
|
|
'function' => function ($rowData) use ($txt, $context, $scripturl) |
|
522
|
|
|
{ |
|
523
|
|
|
// The date the message containing the attachment was posted or the owner of the avatar was active. |
|
524
|
|
|
$date = empty($rowData['poster_time']) ? $txt['never'] : timeformat($rowData['poster_time']); |
|
525
|
|
|
|
|
526
|
|
|
// Add a link to the topic in case of an attachment. |
|
527
|
|
|
if ($context['browse_type'] !== 'avatars') |
|
528
|
|
|
$date .= sprintf('<br>%1$s <a href="%2$s?topic=%3$d.msg%4$d#msg%4$d">%5$s</a>', $txt['in'], $scripturl, $rowData['id_topic'], $rowData['id_msg'], $rowData['subject']); |
|
529
|
|
|
|
|
530
|
|
|
return $date; |
|
531
|
|
|
}, |
|
532
|
|
|
), |
|
533
|
|
|
'sort' => array( |
|
534
|
|
|
'default' => $context['browse_type'] === 'avatars' ? 'mem.last_login' : 'm.id_msg', |
|
535
|
|
|
'reverse' => $context['browse_type'] === 'avatars' ? 'mem.last_login DESC' : 'm.id_msg DESC', |
|
536
|
|
|
), |
|
537
|
|
|
), |
|
538
|
|
|
'downloads' => array( |
|
539
|
|
|
'header' => array( |
|
540
|
|
|
'value' => $txt['downloads'], |
|
541
|
|
|
), |
|
542
|
|
|
'data' => array( |
|
543
|
|
|
'db' => 'downloads', |
|
544
|
|
|
'comma_format' => true, |
|
545
|
|
|
), |
|
546
|
|
|
'sort' => array( |
|
547
|
|
|
'default' => 'a.downloads', |
|
548
|
|
|
'reverse' => 'a.downloads DESC', |
|
549
|
|
|
), |
|
550
|
|
|
), |
|
551
|
|
|
'check' => array( |
|
552
|
|
|
'header' => array( |
|
553
|
|
|
'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check">', |
|
554
|
|
|
'class' => 'centercol', |
|
555
|
|
|
), |
|
556
|
|
|
'data' => array( |
|
557
|
|
|
'sprintf' => array( |
|
558
|
|
|
'format' => '<input type="checkbox" name="remove[%1$d]" class="input_check">', |
|
559
|
|
|
'params' => array( |
|
560
|
|
|
'id_attach' => false, |
|
561
|
|
|
), |
|
562
|
|
|
), |
|
563
|
|
|
'class' => 'centercol', |
|
564
|
|
|
), |
|
565
|
|
|
), |
|
566
|
|
|
), |
|
567
|
|
|
'form' => array( |
|
568
|
|
|
'href' => $scripturl . '?action=admin;area=manageattachments;sa=remove' . ($context['browse_type'] === 'avatars' ? ';avatars' : ($context['browse_type'] === 'thumbs' ? ';thumbs' : '')), |
|
569
|
|
|
'include_sort' => true, |
|
570
|
|
|
'include_start' => true, |
|
571
|
|
|
'hidden_fields' => array( |
|
572
|
|
|
'type' => $context['browse_type'], |
|
573
|
|
|
), |
|
574
|
|
|
), |
|
575
|
|
|
'additional_rows' => array( |
|
576
|
|
|
array( |
|
577
|
|
|
'position' => 'above_table_headers', |
|
578
|
|
|
'value' => '<input type="submit" name="remove_submit" class="button_submit you_sure" value="' . $txt['quickmod_delete_selected'] . '" data-confirm="' . $txt['confirm_delete_attachments'] . '">', |
|
579
|
|
|
), |
|
580
|
|
|
array( |
|
581
|
|
|
'position' => 'below_table_data', |
|
582
|
|
|
'value' => '<input type="submit" name="remove_submit" class="button_submit you_sure" value="' . $txt['quickmod_delete_selected'] . '" data-confirm="' . $txt['confirm_delete_attachments'] . '">', |
|
583
|
|
|
), |
|
584
|
|
|
), |
|
585
|
|
|
); |
|
586
|
|
|
|
|
587
|
|
|
// Does a hook want to display their attachments better? |
|
588
|
|
|
call_integration_hook('integrate_attachments_browse', array(&$listOptions, &$titles, &$list_title)); |
|
589
|
|
|
|
|
590
|
|
|
// Create the list. |
|
591
|
|
|
require_once($sourcedir . '/Subs-List.php'); |
|
592
|
|
|
createList($listOptions); |
|
593
|
|
|
|
|
594
|
|
|
$context['sub_template'] = 'show_list'; |
|
595
|
|
|
$context['default_list'] = 'file_list'; |
|
596
|
|
|
} |
|
597
|
|
|
|
|
598
|
|
|
/** |
|
599
|
|
|
* Returns the list of attachments files (avatars or not), recorded |
|
600
|
|
|
* in the database, per the parameters received. |
|
601
|
|
|
* |
|
602
|
|
|
* @param int $start The item to start with |
|
603
|
|
|
* @param int $items_per_page How many items to show per page |
|
604
|
|
|
* @param string $sort A string indicating how to sort results |
|
605
|
|
|
* @param string $browse_type can be one of 'avatars' or ... not. :P |
|
606
|
|
|
* @return array An array of file info |
|
607
|
|
|
*/ |
|
608
|
|
|
function list_getFiles($start, $items_per_page, $sort, $browse_type) |
|
609
|
|
|
{ |
|
610
|
|
|
global $smcFunc, $txt; |
|
611
|
|
|
|
|
612
|
|
|
// Choose a query depending on what we are viewing. |
|
613
|
|
|
if ($browse_type === 'avatars') |
|
614
|
|
|
$request = $smcFunc['db_query']('', ' |
|
615
|
|
|
SELECT |
|
616
|
|
|
{string:blank_text} AS id_msg, COALESCE(mem.real_name, {string:not_applicable_text}) AS poster_name, |
|
617
|
|
|
mem.last_login AS poster_time, 0 AS id_topic, a.id_member, a.id_attach, a.filename, a.file_hash, a.attachment_type, |
|
618
|
|
|
a.size, a.width, a.height, a.downloads, {string:blank_text} AS subject, 0 AS id_board |
|
619
|
|
|
FROM {db_prefix}attachments AS a |
|
620
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = a.id_member) |
|
621
|
|
|
WHERE a.id_member != {int:guest_id} |
|
622
|
|
|
ORDER BY {raw:sort} |
|
623
|
|
|
LIMIT {int:start}, {int:per_page}', |
|
624
|
|
|
array( |
|
625
|
|
|
'guest_id' => 0, |
|
626
|
|
|
'blank_text' => '', |
|
627
|
|
|
'not_applicable_text' => $txt['not_applicable'], |
|
628
|
|
|
'sort' => $sort, |
|
629
|
|
|
'start' => $start, |
|
630
|
|
|
'per_page' => $items_per_page, |
|
631
|
|
|
) |
|
632
|
|
|
); |
|
633
|
|
|
else |
|
634
|
|
|
$request = $smcFunc['db_query']('', ' |
|
635
|
|
|
SELECT |
|
636
|
|
|
m.id_msg, COALESCE(mem.real_name, m.poster_name) AS poster_name, m.poster_time, m.id_topic, m.id_member, |
|
637
|
|
|
a.id_attach, a.filename, a.file_hash, a.attachment_type, a.size, a.width, a.height, a.downloads, mf.subject, t.id_board |
|
638
|
|
|
FROM {db_prefix}attachments AS a |
|
639
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg) |
|
640
|
|
|
INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) |
|
641
|
|
|
INNER JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg) |
|
642
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) |
|
643
|
|
|
WHERE a.attachment_type = {int:attachment_type} |
|
644
|
|
|
ORDER BY {raw:sort} |
|
645
|
|
|
LIMIT {int:start}, {int:per_page}', |
|
646
|
|
|
array( |
|
647
|
|
|
'attachment_type' => $browse_type == 'thumbs' ? '3' : '0', |
|
648
|
|
|
'sort' => $sort, |
|
649
|
|
|
'start' => $start, |
|
650
|
|
|
'per_page' => $items_per_page, |
|
651
|
|
|
) |
|
652
|
|
|
); |
|
653
|
|
|
$files = array(); |
|
654
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
655
|
|
|
$files[] = $row; |
|
656
|
|
|
$smcFunc['db_free_result']($request); |
|
657
|
|
|
|
|
658
|
|
|
return $files; |
|
659
|
|
|
} |
|
660
|
|
|
|
|
661
|
|
|
/** |
|
662
|
|
|
* Return the number of files of the specified type recorded in the database. |
|
663
|
|
|
* (the specified type being attachments or avatars). |
|
664
|
|
|
* |
|
665
|
|
|
* @param string $browse_type can be one of 'avatars' or not. (in which case they're attachments) |
|
666
|
|
|
* @return int The number of files |
|
667
|
|
|
*/ |
|
668
|
|
|
function list_getNumFiles($browse_type) |
|
669
|
|
|
{ |
|
670
|
|
|
global $smcFunc; |
|
671
|
|
|
|
|
672
|
|
|
// Depending on the type of file, different queries are used. |
|
673
|
|
|
if ($browse_type === 'avatars') |
|
674
|
|
|
$request = $smcFunc['db_query']('', ' |
|
675
|
|
|
SELECT COUNT(*) |
|
676
|
|
|
FROM {db_prefix}attachments |
|
677
|
|
|
WHERE id_member != {int:guest_id_member}', |
|
678
|
|
|
array( |
|
679
|
|
|
'guest_id_member' => 0, |
|
680
|
|
|
) |
|
681
|
|
|
); |
|
682
|
|
|
else |
|
683
|
|
|
$request = $smcFunc['db_query']('', ' |
|
684
|
|
|
SELECT COUNT(*) AS num_attach |
|
685
|
|
|
FROM {db_prefix}attachments AS a |
|
686
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg) |
|
687
|
|
|
INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) |
|
688
|
|
|
INNER JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg) |
|
689
|
|
|
WHERE a.attachment_type = {int:attachment_type} |
|
690
|
|
|
AND a.id_member = {int:guest_id_member}', |
|
691
|
|
|
array( |
|
692
|
|
|
'attachment_type' => $browse_type === 'thumbs' ? '3' : '0', |
|
693
|
|
|
'guest_id_member' => 0, |
|
694
|
|
|
) |
|
695
|
|
|
); |
|
696
|
|
|
|
|
697
|
|
|
list ($num_files) = $smcFunc['db_fetch_row']($request); |
|
698
|
|
|
$smcFunc['db_free_result']($request); |
|
699
|
|
|
|
|
700
|
|
|
return $num_files; |
|
701
|
|
|
} |
|
702
|
|
|
|
|
703
|
|
|
/** |
|
704
|
|
|
* Show several file maintenance options. |
|
705
|
|
|
* Called by ?action=admin;area=manageattachments;sa=maintain. |
|
706
|
|
|
* Calculates file statistics (total file size, number of attachments, |
|
707
|
|
|
* number of avatars, attachment space available). |
|
708
|
|
|
* |
|
709
|
|
|
* @uses the 'maintain' sub template. |
|
710
|
|
|
*/ |
|
711
|
|
|
function MaintainFiles() |
|
712
|
|
|
{ |
|
713
|
|
|
global $context, $modSettings, $smcFunc; |
|
714
|
|
|
|
|
715
|
|
|
$context['sub_template'] = 'maintenance'; |
|
716
|
|
|
|
|
717
|
|
|
$attach_dirs = smf_json_decode($modSettings['attachmentUploadDir'], true); |
|
718
|
|
|
|
|
719
|
|
|
// Get the number of attachments.... |
|
720
|
|
|
$request = $smcFunc['db_query']('', ' |
|
721
|
|
|
SELECT COUNT(*) |
|
722
|
|
|
FROM {db_prefix}attachments |
|
723
|
|
|
WHERE attachment_type = {int:attachment_type} |
|
724
|
|
|
AND id_member = {int:guest_id_member}', |
|
725
|
|
|
array( |
|
726
|
|
|
'attachment_type' => 0, |
|
727
|
|
|
'guest_id_member' => 0, |
|
728
|
|
|
) |
|
729
|
|
|
); |
|
730
|
|
|
list ($context['num_attachments']) = $smcFunc['db_fetch_row']($request); |
|
731
|
|
|
$smcFunc['db_free_result']($request); |
|
732
|
|
|
$context['num_attachments'] = comma_format($context['num_attachments'], 0); |
|
733
|
|
|
|
|
734
|
|
|
// Also get the avatar amount.... |
|
735
|
|
|
$request = $smcFunc['db_query']('', ' |
|
736
|
|
|
SELECT COUNT(*) |
|
737
|
|
|
FROM {db_prefix}attachments |
|
738
|
|
|
WHERE id_member != {int:guest_id_member}', |
|
739
|
|
|
array( |
|
740
|
|
|
'guest_id_member' => 0, |
|
741
|
|
|
) |
|
742
|
|
|
); |
|
743
|
|
|
list ($context['num_avatars']) = $smcFunc['db_fetch_row']($request); |
|
744
|
|
|
$smcFunc['db_free_result']($request); |
|
745
|
|
|
$context['num_avatars'] = comma_format($context['num_avatars'], 0); |
|
746
|
|
|
|
|
747
|
|
|
// Check the size of all the directories. |
|
748
|
|
|
$request = $smcFunc['db_query']('', ' |
|
749
|
|
|
SELECT SUM(size) |
|
750
|
|
|
FROM {db_prefix}attachments |
|
751
|
|
|
WHERE attachment_type != {int:type}', |
|
752
|
|
|
array( |
|
753
|
|
|
'type' => 1, |
|
754
|
|
|
) |
|
755
|
|
|
); |
|
756
|
|
|
list ($attachmentDirSize) = $smcFunc['db_fetch_row']($request); |
|
757
|
|
|
$smcFunc['db_free_result']($request); |
|
758
|
|
|
|
|
759
|
|
|
// Divide it into kilobytes. |
|
760
|
|
|
$attachmentDirSize /= 1024; |
|
761
|
|
|
$context['attachment_total_size'] = comma_format($attachmentDirSize, 2); |
|
762
|
|
|
|
|
763
|
|
|
$request = $smcFunc['db_query']('', ' |
|
764
|
|
|
SELECT COUNT(*), SUM(size) |
|
765
|
|
|
FROM {db_prefix}attachments |
|
766
|
|
|
WHERE id_folder = {int:folder_id} |
|
767
|
|
|
AND attachment_type != {int:type}', |
|
768
|
|
|
array( |
|
769
|
|
|
'folder_id' => $modSettings['currentAttachmentUploadDir'], |
|
770
|
|
|
'type' => 1, |
|
771
|
|
|
) |
|
772
|
|
|
); |
|
773
|
|
|
list ($current_dir_files, $current_dir_size) = $smcFunc['db_fetch_row']($request); |
|
774
|
|
|
$smcFunc['db_free_result']($request); |
|
775
|
|
|
$current_dir_size /= 1024; |
|
776
|
|
|
|
|
777
|
|
|
// If they specified a limit only.... |
|
778
|
|
|
if (!empty($modSettings['attachmentDirSizeLimit'])) |
|
779
|
|
|
$context['attachment_space'] = comma_format(max($modSettings['attachmentDirSizeLimit'] - $current_dir_size, 0), 2); |
|
780
|
|
|
$context['attachment_current_size'] = comma_format($current_dir_size, 2); |
|
781
|
|
|
|
|
782
|
|
|
if (!empty($modSettings['attachmentDirFileLimit'])) |
|
783
|
|
|
$context['attachment_files'] = comma_format(max($modSettings['attachmentDirFileLimit'] - $current_dir_files, 0), 0); |
|
784
|
|
|
$context['attachment_current_files'] = comma_format($current_dir_files, 0); |
|
785
|
|
|
|
|
786
|
|
|
$context['attach_multiple_dirs'] = count($attach_dirs) > 1 ? true : false; |
|
787
|
|
|
$context['attach_dirs'] = $attach_dirs; |
|
788
|
|
|
$context['base_dirs'] = !empty($modSettings['attachment_basedirectories']) ? smf_json_decode($modSettings['attachment_basedirectories'], true) : array(); |
|
789
|
|
|
$context['checked'] = isset($_SESSION['checked']) ? $_SESSION['checked'] : true; |
|
790
|
|
|
if (!empty($_SESSION['results'])) |
|
791
|
|
|
{ |
|
792
|
|
|
$context['results'] = implode('<br>', $_SESSION['results']); |
|
793
|
|
|
unset($_SESSION['results']); |
|
794
|
|
|
} |
|
795
|
|
|
} |
|
796
|
|
|
|
|
797
|
|
|
/** |
|
798
|
|
|
* Remove attachments older than a given age. |
|
799
|
|
|
* Called from the maintenance screen by |
|
800
|
|
|
* ?action=admin;area=manageattachments;sa=byAge. |
|
801
|
|
|
* It optionally adds a certain text to the messages the attachments |
|
802
|
|
|
* were removed from. |
|
803
|
|
|
* @todo refactor this silly superglobals use... |
|
804
|
|
|
*/ |
|
805
|
|
|
function RemoveAttachmentByAge() |
|
806
|
|
|
{ |
|
807
|
|
|
global $smcFunc; |
|
808
|
|
|
|
|
809
|
|
|
checkSession('post', 'admin'); |
|
810
|
|
|
|
|
811
|
|
|
// @todo Ignore messages in topics that are stickied? |
|
812
|
|
|
|
|
813
|
|
|
// Deleting an attachment? |
|
814
|
|
|
if ($_REQUEST['type'] != 'avatars') |
|
815
|
|
|
{ |
|
816
|
|
|
// Get rid of all the old attachments. |
|
817
|
|
|
$messages = removeAttachments(array('attachment_type' => 0, 'poster_time' => (time() - 24 * 60 * 60 * $_POST['age'])), 'messages', true); |
|
818
|
|
|
|
|
819
|
|
|
// Update the messages to reflect the change. |
|
820
|
|
View Code Duplication |
if (!empty($messages) && !empty($_POST['notice'])) |
|
|
|
|
|
|
821
|
|
|
$smcFunc['db_query']('', ' |
|
822
|
|
|
UPDATE {db_prefix}messages |
|
823
|
|
|
SET body = CONCAT(body, {string:notice}) |
|
824
|
|
|
WHERE id_msg IN ({array_int:messages})', |
|
825
|
|
|
array( |
|
826
|
|
|
'messages' => $messages, |
|
827
|
|
|
'notice' => '<br><br>' . $_POST['notice'], |
|
828
|
|
|
) |
|
829
|
|
|
); |
|
830
|
|
|
} |
|
831
|
|
|
else |
|
832
|
|
|
{ |
|
833
|
|
|
// Remove all the old avatars. |
|
834
|
|
|
removeAttachments(array('not_id_member' => 0, 'last_login' => (time() - 24 * 60 * 60 * $_POST['age'])), 'members'); |
|
835
|
|
|
} |
|
836
|
|
|
redirectexit('action=admin;area=manageattachments' . (empty($_REQUEST['avatars']) ? ';sa=maintenance' : ';avatars')); |
|
837
|
|
|
} |
|
838
|
|
|
|
|
839
|
|
|
/** |
|
840
|
|
|
* Remove attachments larger than a given size. |
|
841
|
|
|
* Called from the maintenance screen by |
|
842
|
|
|
* ?action=admin;area=manageattachments;sa=bySize. |
|
843
|
|
|
* Optionally adds a certain text to the messages the attachments were |
|
844
|
|
|
* removed from. |
|
845
|
|
|
*/ |
|
846
|
|
|
function RemoveAttachmentBySize() |
|
847
|
|
|
{ |
|
848
|
|
|
global $smcFunc; |
|
849
|
|
|
|
|
850
|
|
|
checkSession('post', 'admin'); |
|
851
|
|
|
|
|
852
|
|
|
// Find humungous attachments. |
|
853
|
|
|
$messages = removeAttachments(array('attachment_type' => 0, 'size' => 1024 * $_POST['size']), 'messages', true); |
|
854
|
|
|
|
|
855
|
|
|
// And make a note on the post. |
|
856
|
|
View Code Duplication |
if (!empty($messages) && !empty($_POST['notice'])) |
|
|
|
|
|
|
857
|
|
|
$smcFunc['db_query']('', ' |
|
858
|
|
|
UPDATE {db_prefix}messages |
|
859
|
|
|
SET body = CONCAT(body, {string:notice}) |
|
860
|
|
|
WHERE id_msg IN ({array_int:messages})', |
|
861
|
|
|
array( |
|
862
|
|
|
'messages' => $messages, |
|
863
|
|
|
'notice' => '<br><br>' . $_POST['notice'], |
|
864
|
|
|
) |
|
865
|
|
|
); |
|
866
|
|
|
|
|
867
|
|
|
redirectexit('action=admin;area=manageattachments;sa=maintenance'); |
|
868
|
|
|
} |
|
869
|
|
|
|
|
870
|
|
|
/** |
|
871
|
|
|
* Remove a selection of attachments or avatars. |
|
872
|
|
|
* Called from the browse screen as submitted form by |
|
873
|
|
|
* ?action=admin;area=manageattachments;sa=remove |
|
874
|
|
|
*/ |
|
875
|
|
|
function RemoveAttachment() |
|
876
|
|
|
{ |
|
877
|
|
|
global $txt, $smcFunc, $language, $user_info; |
|
878
|
|
|
|
|
879
|
|
|
checkSession(); |
|
880
|
|
|
|
|
881
|
|
|
if (!empty($_POST['remove'])) |
|
882
|
|
|
{ |
|
883
|
|
|
$attachments = array(); |
|
884
|
|
|
// There must be a quicker way to pass this safety test?? |
|
885
|
|
|
foreach ($_POST['remove'] as $removeID => $dummy) |
|
886
|
|
|
$attachments[] = (int) $removeID; |
|
887
|
|
|
|
|
888
|
|
|
// If the attachments are from a 3rd party, let them remove it. Hooks should remove their ids from the array. |
|
889
|
|
|
$filesRemoved = false; |
|
890
|
|
|
call_integration_hook('integrate_attachment_remove', array(&$filesRemoved, $attachments)); |
|
891
|
|
|
|
|
892
|
|
|
if ($_REQUEST['type'] == 'avatars' && !empty($attachments)) |
|
893
|
|
|
removeAttachments(array('id_attach' => $attachments)); |
|
894
|
|
|
else if (!empty($attachments)) |
|
895
|
|
|
{ |
|
896
|
|
|
$messages = removeAttachments(array('id_attach' => $attachments), 'messages', true); |
|
897
|
|
|
|
|
898
|
|
|
// And change the message to reflect this. |
|
899
|
|
|
if (!empty($messages)) |
|
900
|
|
|
{ |
|
901
|
|
|
loadLanguage('index', $language, true); |
|
902
|
|
|
$smcFunc['db_query']('', ' |
|
903
|
|
|
UPDATE {db_prefix}messages |
|
904
|
|
|
SET body = CONCAT(body, {string:deleted_message}) |
|
905
|
|
|
WHERE id_msg IN ({array_int:messages_affected})', |
|
906
|
|
|
array( |
|
907
|
|
|
'messages_affected' => $messages, |
|
908
|
|
|
'deleted_message' => '<br><br>' . $txt['attachment_delete_admin'], |
|
909
|
|
|
) |
|
910
|
|
|
); |
|
911
|
|
|
loadLanguage('index', $user_info['language'], true); |
|
912
|
|
|
} |
|
913
|
|
|
} |
|
914
|
|
|
} |
|
915
|
|
|
|
|
916
|
|
|
$_GET['sort'] = isset($_GET['sort']) ? $_GET['sort'] : 'date'; |
|
917
|
|
|
redirectexit('action=admin;area=manageattachments;sa=browse;' . $_REQUEST['type'] . ';sort=' . $_GET['sort'] . (isset($_GET['desc']) ? ';desc' : '') . ';start=' . $_REQUEST['start']); |
|
918
|
|
|
} |
|
919
|
|
|
|
|
920
|
|
|
/** |
|
921
|
|
|
* Removes all attachments in a single click |
|
922
|
|
|
* Called from the maintenance screen by |
|
923
|
|
|
* ?action=admin;area=manageattachments;sa=removeall. |
|
924
|
|
|
*/ |
|
925
|
|
|
function RemoveAllAttachments() |
|
926
|
|
|
{ |
|
927
|
|
|
global $txt, $smcFunc; |
|
928
|
|
|
|
|
929
|
|
|
checkSession('get', 'admin'); |
|
930
|
|
|
|
|
931
|
|
|
$messages = removeAttachments(array('attachment_type' => 0), '', true); |
|
932
|
|
|
|
|
933
|
|
|
if (!isset($_POST['notice'])) |
|
934
|
|
|
$_POST['notice'] = $txt['attachment_delete_admin']; |
|
935
|
|
|
|
|
936
|
|
|
// Add the notice on the end of the changed messages. |
|
937
|
|
View Code Duplication |
if (!empty($messages)) |
|
|
|
|
|
|
938
|
|
|
$smcFunc['db_query']('', ' |
|
939
|
|
|
UPDATE {db_prefix}messages |
|
940
|
|
|
SET body = CONCAT(body, {string:deleted_message}) |
|
941
|
|
|
WHERE id_msg IN ({array_int:messages})', |
|
942
|
|
|
array( |
|
943
|
|
|
'messages' => $messages, |
|
944
|
|
|
'deleted_message' => '<br><br>' . $_POST['notice'], |
|
945
|
|
|
) |
|
946
|
|
|
); |
|
947
|
|
|
|
|
948
|
|
|
redirectexit('action=admin;area=manageattachments;sa=maintenance'); |
|
949
|
|
|
} |
|
950
|
|
|
|
|
951
|
|
|
/** |
|
952
|
|
|
* Removes attachments or avatars based on a given query condition. |
|
953
|
|
|
* Called by several remove avatar/attachment functions in this file. |
|
954
|
|
|
* It removes attachments based that match the $condition. |
|
955
|
|
|
* It allows query_types 'messages' and 'members', whichever is need by the |
|
956
|
|
|
* $condition parameter. |
|
957
|
|
|
* It does no permissions check. |
|
958
|
|
|
* @internal |
|
959
|
|
|
* |
|
960
|
|
|
* @param array $condition An array of conditions |
|
961
|
|
|
* @param string $query_type The query type. Can be 'messages' or 'members' |
|
962
|
|
|
* @param bool $return_affected_messages Whether to return an array with the IDs of affected messages |
|
963
|
|
|
* @param bool $autoThumbRemoval Whether to automatically remove any thumbnails associated with the removed files |
|
964
|
|
|
* @return void|int[] Returns an array containing IDs of affected messages if $return_affected_messages is true |
|
965
|
|
|
*/ |
|
966
|
|
|
function removeAttachments($condition, $query_type = '', $return_affected_messages = false, $autoThumbRemoval = true) |
|
967
|
|
|
{ |
|
968
|
|
|
global $modSettings, $smcFunc; |
|
969
|
|
|
|
|
970
|
|
|
// @todo This might need more work! |
|
971
|
|
|
$new_condition = array(); |
|
972
|
|
|
$query_parameter = array( |
|
973
|
|
|
'thumb_attachment_type' => 3, |
|
974
|
|
|
); |
|
975
|
|
|
$do_logging = array(); |
|
976
|
|
|
|
|
977
|
|
|
if (is_array($condition)) |
|
978
|
|
|
{ |
|
979
|
|
|
foreach ($condition as $real_type => $restriction) |
|
980
|
|
|
{ |
|
981
|
|
|
// Doing a NOT? |
|
982
|
|
|
$is_not = substr($real_type, 0, 4) == 'not_'; |
|
983
|
|
|
$type = $is_not ? substr($real_type, 4) : $real_type; |
|
984
|
|
|
|
|
985
|
|
|
if (in_array($type, array('id_member', 'id_attach', 'id_msg'))) |
|
986
|
|
|
$new_condition[] = 'a.' . $type . ($is_not ? ' NOT' : '') . ' IN (' . (is_array($restriction) ? '{array_int:' . $real_type . '}' : '{int:' . $real_type . '}') . ')'; |
|
987
|
|
|
elseif ($type == 'attachment_type') |
|
988
|
|
|
$new_condition[] = 'a.attachment_type = {int:' . $real_type . '}'; |
|
989
|
|
|
elseif ($type == 'poster_time') |
|
990
|
|
|
$new_condition[] = 'm.poster_time < {int:' . $real_type . '}'; |
|
991
|
|
|
elseif ($type == 'last_login') |
|
992
|
|
|
$new_condition[] = 'mem.last_login < {int:' . $real_type . '}'; |
|
993
|
|
|
elseif ($type == 'size') |
|
994
|
|
|
$new_condition[] = 'a.size > {int:' . $real_type . '}'; |
|
995
|
|
|
elseif ($type == 'id_topic') |
|
996
|
|
|
$new_condition[] = 'm.id_topic IN (' . (is_array($restriction) ? '{array_int:' . $real_type . '}' : '{int:' . $real_type . '}') . ')'; |
|
997
|
|
|
|
|
998
|
|
|
// Add the parameter! |
|
999
|
|
|
$query_parameter[$real_type] = $restriction; |
|
1000
|
|
|
|
|
1001
|
|
|
if ($type == 'do_logging') |
|
1002
|
|
|
$do_logging = $condition['id_attach']; |
|
1003
|
|
|
} |
|
1004
|
|
|
$condition = implode(' AND ', $new_condition); |
|
1005
|
|
|
} |
|
1006
|
|
|
|
|
1007
|
|
|
// Delete it only if it exists... |
|
1008
|
|
|
$msgs = array(); |
|
1009
|
|
|
$attach = array(); |
|
1010
|
|
|
$parents = array(); |
|
1011
|
|
|
|
|
1012
|
|
|
// Get all the attachment names and id_msg's. |
|
1013
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1014
|
|
|
SELECT |
|
1015
|
|
|
a.id_folder, a.filename, a.file_hash, a.attachment_type, a.id_attach, a.id_member' . ($query_type == 'messages' ? ', m.id_msg' : ', a.id_msg') . ', |
|
1016
|
|
|
thumb.id_folder AS thumb_folder, COALESCE(thumb.id_attach, 0) AS id_thumb, thumb.filename AS thumb_filename, thumb.file_hash AS thumb_file_hash, thumb_parent.id_attach AS id_parent |
|
1017
|
|
|
FROM {db_prefix}attachments AS a' .($query_type == 'members' ? ' |
|
1018
|
|
|
INNER JOIN {db_prefix}members AS mem ON (mem.id_member = a.id_member)' : ($query_type == 'messages' ? ' |
|
1019
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)' : '')) . ' |
|
1020
|
|
|
LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb) |
|
1021
|
|
|
LEFT JOIN {db_prefix}attachments AS thumb_parent ON (thumb.attachment_type = {int:thumb_attachment_type} AND thumb_parent.id_thumb = a.id_attach) |
|
1022
|
|
|
WHERE ' . $condition, |
|
1023
|
|
|
$query_parameter |
|
1024
|
|
|
); |
|
1025
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
1026
|
|
|
{ |
|
1027
|
|
|
// Figure out the "encrypted" filename and unlink it ;). |
|
1028
|
|
|
if ($row['attachment_type'] == 1) |
|
1029
|
|
|
{ |
|
1030
|
|
|
// if attachment_type = 1, it's... an avatar in a custom avatar directory. |
|
1031
|
|
|
// wasn't it obvious? :P |
|
1032
|
|
|
// @todo look again at this. |
|
1033
|
|
|
@unlink($modSettings['custom_avatar_dir'] . '/' . $row['filename']); |
|
|
|
|
|
|
1034
|
|
|
} |
|
1035
|
|
|
else |
|
1036
|
|
|
{ |
|
1037
|
|
|
$filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']); |
|
1038
|
|
|
@unlink($filename); |
|
|
|
|
|
|
1039
|
|
|
|
|
1040
|
|
|
// If this was a thumb, the parent attachment should know about it. |
|
1041
|
|
|
if (!empty($row['id_parent'])) |
|
1042
|
|
|
$parents[] = $row['id_parent']; |
|
1043
|
|
|
|
|
1044
|
|
|
// If this attachments has a thumb, remove it as well. |
|
1045
|
|
|
if (!empty($row['id_thumb']) && $autoThumbRemoval) |
|
1046
|
|
|
{ |
|
1047
|
|
|
$thumb_filename = getAttachmentFilename($row['thumb_filename'], $row['id_thumb'], $row['thumb_folder'], false, $row['thumb_file_hash']); |
|
1048
|
|
|
@unlink($thumb_filename); |
|
|
|
|
|
|
1049
|
|
|
$attach[] = $row['id_thumb']; |
|
1050
|
|
|
} |
|
1051
|
|
|
} |
|
1052
|
|
|
|
|
1053
|
|
|
// Make a list. |
|
1054
|
|
|
if ($return_affected_messages && empty($row['attachment_type'])) |
|
1055
|
|
|
$msgs[] = $row['id_msg']; |
|
1056
|
|
|
|
|
1057
|
|
|
$attach[] = $row['id_attach']; |
|
1058
|
|
|
} |
|
1059
|
|
|
$smcFunc['db_free_result']($request); |
|
1060
|
|
|
|
|
1061
|
|
|
// Removed attachments don't have to be updated anymore. |
|
1062
|
|
|
$parents = array_diff($parents, $attach); |
|
1063
|
|
|
if (!empty($parents)) |
|
1064
|
|
|
$smcFunc['db_query']('', ' |
|
1065
|
|
|
UPDATE {db_prefix}attachments |
|
1066
|
|
|
SET id_thumb = {int:no_thumb} |
|
1067
|
|
|
WHERE id_attach IN ({array_int:parent_attachments})', |
|
1068
|
|
|
array( |
|
1069
|
|
|
'parent_attachments' => $parents, |
|
1070
|
|
|
'no_thumb' => 0, |
|
1071
|
|
|
) |
|
1072
|
|
|
); |
|
1073
|
|
|
|
|
1074
|
|
|
if (!empty($do_logging)) |
|
1075
|
|
|
{ |
|
1076
|
|
|
// In order to log the attachments, we really need their message and filename |
|
1077
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1078
|
|
|
SELECT m.id_msg, a.filename |
|
1079
|
|
|
FROM {db_prefix}attachments AS a |
|
1080
|
|
|
INNER JOIN {db_prefix}messages AS m ON (a.id_msg = m.id_msg) |
|
1081
|
|
|
WHERE a.id_attach IN ({array_int:attachments}) |
|
1082
|
|
|
AND a.attachment_type = {int:attachment_type}', |
|
1083
|
|
|
array( |
|
1084
|
|
|
'attachments' => $do_logging, |
|
1085
|
|
|
'attachment_type' => 0, |
|
1086
|
|
|
) |
|
1087
|
|
|
); |
|
1088
|
|
|
|
|
1089
|
|
View Code Duplication |
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
|
|
|
|
|
1090
|
|
|
logAction( |
|
1091
|
|
|
'remove_attach', |
|
1092
|
|
|
array( |
|
1093
|
|
|
'message' => $row['id_msg'], |
|
1094
|
|
|
'filename' => preg_replace('~&#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', $smcFunc['htmlspecialchars']($row['filename'])), |
|
1095
|
|
|
) |
|
1096
|
|
|
); |
|
1097
|
|
|
$smcFunc['db_free_result']($request); |
|
1098
|
|
|
} |
|
1099
|
|
|
|
|
1100
|
|
|
if (!empty($attach)) |
|
1101
|
|
|
$smcFunc['db_query']('', ' |
|
1102
|
|
|
DELETE FROM {db_prefix}attachments |
|
1103
|
|
|
WHERE id_attach IN ({array_int:attachment_list})', |
|
1104
|
|
|
array( |
|
1105
|
|
|
'attachment_list' => $attach, |
|
1106
|
|
|
) |
|
1107
|
|
|
); |
|
1108
|
|
|
|
|
1109
|
|
|
call_integration_hook('integrate_remove_attachments', array($attach)); |
|
1110
|
|
|
|
|
1111
|
|
|
if ($return_affected_messages) |
|
1112
|
|
|
return array_unique($msgs); |
|
1113
|
|
|
} |
|
1114
|
|
|
|
|
1115
|
|
|
/** |
|
1116
|
|
|
* This function should find attachments in the database that no longer exist and clear them, and fix filesize issues. |
|
1117
|
|
|
*/ |
|
1118
|
|
|
function RepairAttachments() |
|
1119
|
|
|
{ |
|
1120
|
|
|
global $modSettings, $context, $txt, $smcFunc; |
|
1121
|
|
|
|
|
1122
|
|
|
checkSession('get'); |
|
1123
|
|
|
|
|
1124
|
|
|
// If we choose cancel, redirect right back. |
|
1125
|
|
|
if (isset($_POST['cancel'])) |
|
1126
|
|
|
redirectexit('action=admin;area=manageattachments;sa=maintenance'); |
|
1127
|
|
|
|
|
1128
|
|
|
// Try give us a while to sort this out... |
|
1129
|
|
|
@set_time_limit(600); |
|
|
|
|
|
|
1130
|
|
|
|
|
1131
|
|
|
$_GET['step'] = empty($_GET['step']) ? 0 : (int) $_GET['step']; |
|
1132
|
|
|
$context['starting_substep'] = $_GET['substep'] = empty($_GET['substep']) ? 0 : (int) $_GET['substep']; |
|
1133
|
|
|
|
|
1134
|
|
|
// Don't recall the session just in case. |
|
1135
|
|
|
if ($_GET['step'] == 0 && $_GET['substep'] == 0) |
|
1136
|
|
|
{ |
|
1137
|
|
|
unset($_SESSION['attachments_to_fix'], $_SESSION['attachments_to_fix2']); |
|
1138
|
|
|
|
|
1139
|
|
|
// If we're actually fixing stuff - work out what. |
|
1140
|
|
|
if (isset($_GET['fixErrors'])) |
|
1141
|
|
|
{ |
|
1142
|
|
|
// Nothing? |
|
1143
|
|
|
if (empty($_POST['to_fix'])) |
|
1144
|
|
|
redirectexit('action=admin;area=manageattachments;sa=maintenance'); |
|
1145
|
|
|
|
|
1146
|
|
|
$_SESSION['attachments_to_fix'] = array(); |
|
1147
|
|
|
// @todo No need to do this I think. |
|
1148
|
|
|
foreach ($_POST['to_fix'] as $value) |
|
1149
|
|
|
$_SESSION['attachments_to_fix'][] = $value; |
|
1150
|
|
|
} |
|
1151
|
|
|
} |
|
1152
|
|
|
|
|
1153
|
|
|
// All the valid problems are here: |
|
1154
|
|
|
$context['repair_errors'] = array( |
|
1155
|
|
|
'missing_thumbnail_parent' => 0, |
|
1156
|
|
|
'parent_missing_thumbnail' => 0, |
|
1157
|
|
|
'file_missing_on_disk' => 0, |
|
1158
|
|
|
'file_wrong_size' => 0, |
|
1159
|
|
|
'file_size_of_zero' => 0, |
|
1160
|
|
|
'attachment_no_msg' => 0, |
|
1161
|
|
|
'avatar_no_member' => 0, |
|
1162
|
|
|
'wrong_folder' => 0, |
|
1163
|
|
|
'files_without_attachment' => 0, |
|
1164
|
|
|
); |
|
1165
|
|
|
|
|
1166
|
|
|
$to_fix = !empty($_SESSION['attachments_to_fix']) ? $_SESSION['attachments_to_fix'] : array(); |
|
1167
|
|
|
$context['repair_errors'] = isset($_SESSION['attachments_to_fix2']) ? $_SESSION['attachments_to_fix2'] : $context['repair_errors']; |
|
1168
|
|
|
$fix_errors = isset($_GET['fixErrors']) ? true : false; |
|
1169
|
|
|
|
|
1170
|
|
|
// Get stranded thumbnails. |
|
1171
|
|
|
if ($_GET['step'] <= 0) |
|
1172
|
|
|
{ |
|
1173
|
|
|
$result = $smcFunc['db_query']('', ' |
|
1174
|
|
|
SELECT MAX(id_attach) |
|
1175
|
|
|
FROM {db_prefix}attachments |
|
1176
|
|
|
WHERE attachment_type = {int:thumbnail}', |
|
1177
|
|
|
array( |
|
1178
|
|
|
'thumbnail' => 3, |
|
1179
|
|
|
) |
|
1180
|
|
|
); |
|
1181
|
|
|
list ($thumbnails) = $smcFunc['db_fetch_row']($result); |
|
1182
|
|
|
$smcFunc['db_free_result']($result); |
|
1183
|
|
|
|
|
1184
|
|
|
for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) |
|
1185
|
|
|
{ |
|
1186
|
|
|
$to_remove = array(); |
|
1187
|
|
|
|
|
1188
|
|
|
$result = $smcFunc['db_query']('', ' |
|
1189
|
|
|
SELECT thumb.id_attach, thumb.id_folder, thumb.filename, thumb.file_hash |
|
1190
|
|
|
FROM {db_prefix}attachments AS thumb |
|
1191
|
|
|
LEFT JOIN {db_prefix}attachments AS tparent ON (tparent.id_thumb = thumb.id_attach) |
|
1192
|
|
|
WHERE thumb.id_attach BETWEEN {int:substep} AND {int:substep} + 499 |
|
1193
|
|
|
AND thumb.attachment_type = {int:thumbnail} |
|
1194
|
|
|
AND tparent.id_attach IS NULL', |
|
1195
|
|
|
array( |
|
1196
|
|
|
'thumbnail' => 3, |
|
1197
|
|
|
'substep' => $_GET['substep'], |
|
1198
|
|
|
) |
|
1199
|
|
|
); |
|
1200
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($result)) |
|
1201
|
|
|
{ |
|
1202
|
|
|
// Only do anything once... just in case |
|
1203
|
|
|
if (!isset($to_remove[$row['id_attach']])) |
|
1204
|
|
|
{ |
|
1205
|
|
|
$to_remove[$row['id_attach']] = $row['id_attach']; |
|
1206
|
|
|
$context['repair_errors']['missing_thumbnail_parent']++; |
|
1207
|
|
|
|
|
1208
|
|
|
// If we are repairing remove the file from disk now. |
|
1209
|
|
View Code Duplication |
if ($fix_errors && in_array('missing_thumbnail_parent', $to_fix)) |
|
|
|
|
|
|
1210
|
|
|
{ |
|
1211
|
|
|
$filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']); |
|
1212
|
|
|
@unlink($filename); |
|
|
|
|
|
|
1213
|
|
|
} |
|
1214
|
|
|
} |
|
1215
|
|
|
} |
|
1216
|
|
|
if ($smcFunc['db_num_rows']($result) != 0) |
|
1217
|
|
|
$to_fix[] = 'missing_thumbnail_parent'; |
|
1218
|
|
|
$smcFunc['db_free_result']($result); |
|
1219
|
|
|
|
|
1220
|
|
|
// Do we need to delete what we have? |
|
1221
|
|
View Code Duplication |
if ($fix_errors && !empty($to_remove) && in_array('missing_thumbnail_parent', $to_fix)) |
|
|
|
|
|
|
1222
|
|
|
$smcFunc['db_query']('', ' |
|
1223
|
|
|
DELETE FROM {db_prefix}attachments |
|
1224
|
|
|
WHERE id_attach IN ({array_int:to_remove}) |
|
1225
|
|
|
AND attachment_type = {int:attachment_type}', |
|
1226
|
|
|
array( |
|
1227
|
|
|
'to_remove' => $to_remove, |
|
1228
|
|
|
'attachment_type' => 3, |
|
1229
|
|
|
) |
|
1230
|
|
|
); |
|
1231
|
|
|
|
|
1232
|
|
|
pauseAttachmentMaintenance($to_fix, $thumbnails); |
|
1233
|
|
|
} |
|
1234
|
|
|
|
|
1235
|
|
|
$_GET['step'] = 1; |
|
1236
|
|
|
$_GET['substep'] = 0; |
|
1237
|
|
|
pauseAttachmentMaintenance($to_fix); |
|
1238
|
|
|
} |
|
1239
|
|
|
|
|
1240
|
|
|
// Find parents which think they have thumbnails, but actually, don't. |
|
1241
|
|
|
if ($_GET['step'] <= 1) |
|
1242
|
|
|
{ |
|
1243
|
|
|
$result = $smcFunc['db_query']('', ' |
|
1244
|
|
|
SELECT MAX(id_attach) |
|
1245
|
|
|
FROM {db_prefix}attachments |
|
1246
|
|
|
WHERE id_thumb != {int:no_thumb}', |
|
1247
|
|
|
array( |
|
1248
|
|
|
'no_thumb' => 0, |
|
1249
|
|
|
) |
|
1250
|
|
|
); |
|
1251
|
|
|
list ($thumbnails) = $smcFunc['db_fetch_row']($result); |
|
1252
|
|
|
$smcFunc['db_free_result']($result); |
|
1253
|
|
|
|
|
1254
|
|
|
for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) |
|
1255
|
|
|
{ |
|
1256
|
|
|
$to_update = array(); |
|
1257
|
|
|
|
|
1258
|
|
|
$result = $smcFunc['db_query']('', ' |
|
1259
|
|
|
SELECT a.id_attach |
|
1260
|
|
|
FROM {db_prefix}attachments AS a |
|
1261
|
|
|
LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb) |
|
1262
|
|
|
WHERE a.id_attach BETWEEN {int:substep} AND {int:substep} + 499 |
|
1263
|
|
|
AND a.id_thumb != {int:no_thumb} |
|
1264
|
|
|
AND thumb.id_attach IS NULL', |
|
1265
|
|
|
array( |
|
1266
|
|
|
'no_thumb' => 0, |
|
1267
|
|
|
'substep' => $_GET['substep'], |
|
1268
|
|
|
) |
|
1269
|
|
|
); |
|
1270
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($result)) |
|
1271
|
|
|
{ |
|
1272
|
|
|
$to_update[] = $row['id_attach']; |
|
1273
|
|
|
$context['repair_errors']['parent_missing_thumbnail']++; |
|
1274
|
|
|
} |
|
1275
|
|
|
if ($smcFunc['db_num_rows']($result) != 0) |
|
1276
|
|
|
$to_fix[] = 'parent_missing_thumbnail'; |
|
1277
|
|
|
$smcFunc['db_free_result']($result); |
|
1278
|
|
|
|
|
1279
|
|
|
// Do we need to delete what we have? |
|
1280
|
|
|
if ($fix_errors && !empty($to_update) && in_array('parent_missing_thumbnail', $to_fix)) |
|
1281
|
|
|
$smcFunc['db_query']('', ' |
|
1282
|
|
|
UPDATE {db_prefix}attachments |
|
1283
|
|
|
SET id_thumb = {int:no_thumb} |
|
1284
|
|
|
WHERE id_attach IN ({array_int:to_update})', |
|
1285
|
|
|
array( |
|
1286
|
|
|
'to_update' => $to_update, |
|
1287
|
|
|
'no_thumb' => 0, |
|
1288
|
|
|
) |
|
1289
|
|
|
); |
|
1290
|
|
|
|
|
1291
|
|
|
pauseAttachmentMaintenance($to_fix, $thumbnails); |
|
1292
|
|
|
} |
|
1293
|
|
|
|
|
1294
|
|
|
$_GET['step'] = 2; |
|
1295
|
|
|
$_GET['substep'] = 0; |
|
1296
|
|
|
pauseAttachmentMaintenance($to_fix); |
|
1297
|
|
|
} |
|
1298
|
|
|
|
|
1299
|
|
|
// This may take forever I'm afraid, but life sucks... recount EVERY attachments! |
|
1300
|
|
|
if ($_GET['step'] <= 2) |
|
1301
|
|
|
{ |
|
1302
|
|
|
$result = $smcFunc['db_query']('', ' |
|
1303
|
|
|
SELECT MAX(id_attach) |
|
1304
|
|
|
FROM {db_prefix}attachments', |
|
1305
|
|
|
array( |
|
1306
|
|
|
) |
|
1307
|
|
|
); |
|
1308
|
|
|
list ($thumbnails) = $smcFunc['db_fetch_row']($result); |
|
1309
|
|
|
$smcFunc['db_free_result']($result); |
|
1310
|
|
|
|
|
1311
|
|
|
for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 250) |
|
1312
|
|
|
{ |
|
1313
|
|
|
$to_remove = array(); |
|
1314
|
|
|
$errors_found = array(); |
|
1315
|
|
|
|
|
1316
|
|
|
$result = $smcFunc['db_query']('', ' |
|
1317
|
|
|
SELECT id_attach, id_folder, filename, file_hash, size, attachment_type |
|
1318
|
|
|
FROM {db_prefix}attachments |
|
1319
|
|
|
WHERE id_attach BETWEEN {int:substep} AND {int:substep} + 249', |
|
1320
|
|
|
array( |
|
1321
|
|
|
'substep' => $_GET['substep'], |
|
1322
|
|
|
) |
|
1323
|
|
|
); |
|
1324
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($result)) |
|
1325
|
|
|
{ |
|
1326
|
|
|
// Get the filename. |
|
1327
|
|
View Code Duplication |
if ($row['attachment_type'] == 1) |
|
|
|
|
|
|
1328
|
|
|
$filename = $modSettings['custom_avatar_dir'] . '/' . $row['filename']; |
|
1329
|
|
|
else |
|
1330
|
|
|
$filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']); |
|
1331
|
|
|
|
|
1332
|
|
|
// File doesn't exist? |
|
1333
|
|
|
if (!file_exists($filename)) |
|
1334
|
|
|
{ |
|
1335
|
|
|
// If we're lucky it might just be in a different folder. |
|
1336
|
|
|
if (!empty($modSettings['currentAttachmentUploadDir'])) |
|
1337
|
|
|
{ |
|
1338
|
|
|
// Get the attachment name with out the folder. |
|
1339
|
|
|
$attachment_name = $row['id_attach'] . '_' . $row['file_hash'] .'.dat'; |
|
1340
|
|
|
|
|
1341
|
|
|
// Loop through the other folders. |
|
1342
|
|
|
foreach ($modSettings['attachmentUploadDir'] as $id => $dir) |
|
1343
|
|
|
if (file_exists($dir . '/' . $attachment_name)) |
|
1344
|
|
|
{ |
|
1345
|
|
|
$context['repair_errors']['wrong_folder']++; |
|
1346
|
|
|
$errors_found[] = 'wrong_folder'; |
|
1347
|
|
|
|
|
1348
|
|
|
// Are we going to fix this now? |
|
1349
|
|
View Code Duplication |
if ($fix_errors && in_array('wrong_folder', $to_fix)) |
|
|
|
|
|
|
1350
|
|
|
$smcFunc['db_query']('', ' |
|
1351
|
|
|
UPDATE {db_prefix}attachments |
|
1352
|
|
|
SET id_folder = {int:new_folder} |
|
1353
|
|
|
WHERE id_attach = {int:id_attach}', |
|
1354
|
|
|
array( |
|
1355
|
|
|
'new_folder' => $id, |
|
1356
|
|
|
'id_attach' => $row['id_attach'], |
|
1357
|
|
|
) |
|
1358
|
|
|
); |
|
1359
|
|
|
|
|
1360
|
|
|
continue 2; |
|
1361
|
|
|
} |
|
1362
|
|
|
} |
|
1363
|
|
|
|
|
1364
|
|
|
$to_remove[] = $row['id_attach']; |
|
1365
|
|
|
$context['repair_errors']['file_missing_on_disk']++; |
|
1366
|
|
|
$errors_found[] = 'file_missing_on_disk'; |
|
1367
|
|
|
} |
|
1368
|
|
|
elseif (filesize($filename) == 0) |
|
1369
|
|
|
{ |
|
1370
|
|
|
$context['repair_errors']['file_size_of_zero']++; |
|
1371
|
|
|
$errors_found[] = 'file_size_of_zero'; |
|
1372
|
|
|
|
|
1373
|
|
|
// Fixing? |
|
1374
|
|
|
if ($fix_errors && in_array('file_size_of_zero', $to_fix)) |
|
1375
|
|
|
{ |
|
1376
|
|
|
$to_remove[] = $row['id_attach']; |
|
1377
|
|
|
@unlink($filename); |
|
|
|
|
|
|
1378
|
|
|
} |
|
1379
|
|
|
} |
|
1380
|
|
|
elseif (filesize($filename) != $row['size']) |
|
1381
|
|
|
{ |
|
1382
|
|
|
$context['repair_errors']['file_wrong_size']++; |
|
1383
|
|
|
$errors_found[] = 'file_wrong_size'; |
|
1384
|
|
|
|
|
1385
|
|
|
// Fix it here? |
|
1386
|
|
View Code Duplication |
if ($fix_errors && in_array('file_wrong_size', $to_fix)) |
|
|
|
|
|
|
1387
|
|
|
{ |
|
1388
|
|
|
$smcFunc['db_query']('', ' |
|
1389
|
|
|
UPDATE {db_prefix}attachments |
|
1390
|
|
|
SET size = {int:filesize} |
|
1391
|
|
|
WHERE id_attach = {int:id_attach}', |
|
1392
|
|
|
array( |
|
1393
|
|
|
'filesize' => filesize($filename), |
|
1394
|
|
|
'id_attach' => $row['id_attach'], |
|
1395
|
|
|
) |
|
1396
|
|
|
); |
|
1397
|
|
|
} |
|
1398
|
|
|
} |
|
1399
|
|
|
} |
|
1400
|
|
|
|
|
1401
|
|
|
if (in_array('file_missing_on_disk', $errors_found)) |
|
1402
|
|
|
$to_fix[] = 'file_missing_on_disk'; |
|
1403
|
|
|
if (in_array('file_size_of_zero', $errors_found)) |
|
1404
|
|
|
$to_fix[] = 'file_size_of_zero'; |
|
1405
|
|
|
if (in_array('file_wrong_size', $errors_found)) |
|
1406
|
|
|
$to_fix[] = 'file_wrong_size'; |
|
1407
|
|
|
if (in_array('wrong_folder', $errors_found)) |
|
1408
|
|
|
$to_fix[] = 'wrong_folder'; |
|
1409
|
|
|
$smcFunc['db_free_result']($result); |
|
1410
|
|
|
|
|
1411
|
|
|
// Do we need to delete what we have? |
|
1412
|
|
|
if ($fix_errors && !empty($to_remove)) |
|
1413
|
|
|
{ |
|
1414
|
|
|
$smcFunc['db_query']('', ' |
|
1415
|
|
|
DELETE FROM {db_prefix}attachments |
|
1416
|
|
|
WHERE id_attach IN ({array_int:to_remove})', |
|
1417
|
|
|
array( |
|
1418
|
|
|
'to_remove' => $to_remove, |
|
1419
|
|
|
) |
|
1420
|
|
|
); |
|
1421
|
|
|
$smcFunc['db_query']('', ' |
|
1422
|
|
|
UPDATE {db_prefix}attachments |
|
1423
|
|
|
SET id_thumb = {int:no_thumb} |
|
1424
|
|
|
WHERE id_thumb IN ({array_int:to_remove})', |
|
1425
|
|
|
array( |
|
1426
|
|
|
'to_remove' => $to_remove, |
|
1427
|
|
|
'no_thumb' => 0, |
|
1428
|
|
|
) |
|
1429
|
|
|
); |
|
1430
|
|
|
} |
|
1431
|
|
|
|
|
1432
|
|
|
pauseAttachmentMaintenance($to_fix, $thumbnails); |
|
1433
|
|
|
} |
|
1434
|
|
|
|
|
1435
|
|
|
$_GET['step'] = 3; |
|
1436
|
|
|
$_GET['substep'] = 0; |
|
1437
|
|
|
pauseAttachmentMaintenance($to_fix); |
|
1438
|
|
|
} |
|
1439
|
|
|
|
|
1440
|
|
|
// Get avatars with no members associated with them. |
|
1441
|
|
|
if ($_GET['step'] <= 3) |
|
1442
|
|
|
{ |
|
1443
|
|
|
$result = $smcFunc['db_query']('', ' |
|
1444
|
|
|
SELECT MAX(id_attach) |
|
1445
|
|
|
FROM {db_prefix}attachments', |
|
1446
|
|
|
array( |
|
1447
|
|
|
) |
|
1448
|
|
|
); |
|
1449
|
|
|
list ($thumbnails) = $smcFunc['db_fetch_row']($result); |
|
1450
|
|
|
$smcFunc['db_free_result']($result); |
|
1451
|
|
|
|
|
1452
|
|
|
for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) |
|
1453
|
|
|
{ |
|
1454
|
|
|
$to_remove = array(); |
|
1455
|
|
|
|
|
1456
|
|
|
$result = $smcFunc['db_query']('', ' |
|
1457
|
|
|
SELECT a.id_attach, a.id_folder, a.filename, a.file_hash, a.attachment_type |
|
1458
|
|
|
FROM {db_prefix}attachments AS a |
|
1459
|
|
|
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = a.id_member) |
|
1460
|
|
|
WHERE a.id_attach BETWEEN {int:substep} AND {int:substep} + 499 |
|
1461
|
|
|
AND a.id_member != {int:no_member} |
|
1462
|
|
|
AND a.id_msg = {int:no_msg} |
|
1463
|
|
|
AND mem.id_member IS NULL', |
|
1464
|
|
|
array( |
|
1465
|
|
|
'no_member' => 0, |
|
1466
|
|
|
'no_msg' => 0, |
|
1467
|
|
|
'substep' => $_GET['substep'], |
|
1468
|
|
|
) |
|
1469
|
|
|
); |
|
1470
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($result)) |
|
1471
|
|
|
{ |
|
1472
|
|
|
$to_remove[] = $row['id_attach']; |
|
1473
|
|
|
$context['repair_errors']['avatar_no_member']++; |
|
1474
|
|
|
|
|
1475
|
|
|
// If we are repairing remove the file from disk now. |
|
1476
|
|
|
if ($fix_errors && in_array('avatar_no_member', $to_fix)) |
|
1477
|
|
|
{ |
|
1478
|
|
View Code Duplication |
if ($row['attachment_type'] == 1) |
|
|
|
|
|
|
1479
|
|
|
$filename = $modSettings['custom_avatar_dir'] . '/' . $row['filename']; |
|
1480
|
|
|
else |
|
1481
|
|
|
$filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']); |
|
1482
|
|
|
@unlink($filename); |
|
|
|
|
|
|
1483
|
|
|
} |
|
1484
|
|
|
} |
|
1485
|
|
|
if ($smcFunc['db_num_rows']($result) != 0) |
|
1486
|
|
|
$to_fix[] = 'avatar_no_member'; |
|
1487
|
|
|
$smcFunc['db_free_result']($result); |
|
1488
|
|
|
|
|
1489
|
|
|
// Do we need to delete what we have? |
|
1490
|
|
View Code Duplication |
if ($fix_errors && !empty($to_remove) && in_array('avatar_no_member', $to_fix)) |
|
|
|
|
|
|
1491
|
|
|
$smcFunc['db_query']('', ' |
|
1492
|
|
|
DELETE FROM {db_prefix}attachments |
|
1493
|
|
|
WHERE id_attach IN ({array_int:to_remove}) |
|
1494
|
|
|
AND id_member != {int:no_member} |
|
1495
|
|
|
AND id_msg = {int:no_msg}', |
|
1496
|
|
|
array( |
|
1497
|
|
|
'to_remove' => $to_remove, |
|
1498
|
|
|
'no_member' => 0, |
|
1499
|
|
|
'no_msg' => 0, |
|
1500
|
|
|
) |
|
1501
|
|
|
); |
|
1502
|
|
|
|
|
1503
|
|
|
pauseAttachmentMaintenance($to_fix, $thumbnails); |
|
1504
|
|
|
} |
|
1505
|
|
|
|
|
1506
|
|
|
$_GET['step'] = 4; |
|
1507
|
|
|
$_GET['substep'] = 0; |
|
1508
|
|
|
pauseAttachmentMaintenance($to_fix); |
|
1509
|
|
|
} |
|
1510
|
|
|
|
|
1511
|
|
|
// What about attachments, who are missing a message :'( |
|
1512
|
|
|
if ($_GET['step'] <= 4) |
|
1513
|
|
|
{ |
|
1514
|
|
|
$result = $smcFunc['db_query']('', ' |
|
1515
|
|
|
SELECT MAX(id_attach) |
|
1516
|
|
|
FROM {db_prefix}attachments', |
|
1517
|
|
|
array( |
|
1518
|
|
|
) |
|
1519
|
|
|
); |
|
1520
|
|
|
list ($thumbnails) = $smcFunc['db_fetch_row']($result); |
|
1521
|
|
|
$smcFunc['db_free_result']($result); |
|
1522
|
|
|
|
|
1523
|
|
|
for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) |
|
1524
|
|
|
{ |
|
1525
|
|
|
$to_remove = array(); |
|
1526
|
|
|
$ignore_ids = array(0); |
|
1527
|
|
|
call_integration_hook('integrate_repair_attachments_nomsg', array(&$ignore_ids, $_GET['substep'], $_GET['substep'] += 500)); |
|
1528
|
|
|
|
|
1529
|
|
|
$result = $smcFunc['db_query']('', ' |
|
1530
|
|
|
SELECT a.id_attach, a.id_folder, a.filename, a.file_hash |
|
1531
|
|
|
FROM {db_prefix}attachments AS a |
|
1532
|
|
|
LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg) |
|
1533
|
|
|
WHERE a.id_attach BETWEEN {int:substep} AND {int:substep} + 499 |
|
1534
|
|
|
AND a.id_member = {int:no_member} |
|
1535
|
|
|
AND a.id_msg != {int:no_msg} |
|
1536
|
|
|
AND NOT FIND_IN_SET(a.id_msg, {array_int:ignore_ids}) |
|
1537
|
|
|
AND m.id_msg IS NULL', |
|
1538
|
|
|
array( |
|
1539
|
|
|
'no_member' => 0, |
|
1540
|
|
|
'no_msg' => 0, |
|
1541
|
|
|
'substep' => $_GET['substep'], |
|
1542
|
|
|
'ignore_ids' => $ignore_ids, |
|
1543
|
|
|
) |
|
1544
|
|
|
); |
|
1545
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($result)) |
|
1546
|
|
|
{ |
|
1547
|
|
|
$to_remove[] = $row['id_attach']; |
|
1548
|
|
|
$context['repair_errors']['attachment_no_msg']++; |
|
1549
|
|
|
|
|
1550
|
|
|
// If we are repairing remove the file from disk now. |
|
1551
|
|
View Code Duplication |
if ($fix_errors && in_array('attachment_no_msg', $to_fix)) |
|
|
|
|
|
|
1552
|
|
|
{ |
|
1553
|
|
|
$filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']); |
|
1554
|
|
|
@unlink($filename); |
|
|
|
|
|
|
1555
|
|
|
} |
|
1556
|
|
|
} |
|
1557
|
|
|
if ($smcFunc['db_num_rows']($result) != 0) |
|
1558
|
|
|
$to_fix[] = 'attachment_no_msg'; |
|
1559
|
|
|
$smcFunc['db_free_result']($result); |
|
1560
|
|
|
|
|
1561
|
|
|
// Do we need to delete what we have? |
|
1562
|
|
View Code Duplication |
if ($fix_errors && !empty($to_remove) && in_array('attachment_no_msg', $to_fix)) |
|
|
|
|
|
|
1563
|
|
|
$smcFunc['db_query']('', ' |
|
1564
|
|
|
DELETE FROM {db_prefix}attachments |
|
1565
|
|
|
WHERE id_attach IN ({array_int:to_remove}) |
|
1566
|
|
|
AND id_member = {int:no_member} |
|
1567
|
|
|
AND id_msg != {int:no_msg}', |
|
1568
|
|
|
array( |
|
1569
|
|
|
'to_remove' => $to_remove, |
|
1570
|
|
|
'no_member' => 0, |
|
1571
|
|
|
'no_msg' => 0, |
|
1572
|
|
|
) |
|
1573
|
|
|
); |
|
1574
|
|
|
|
|
1575
|
|
|
pauseAttachmentMaintenance($to_fix, $thumbnails); |
|
1576
|
|
|
} |
|
1577
|
|
|
|
|
1578
|
|
|
$_GET['step'] = 5; |
|
1579
|
|
|
$_GET['substep'] = 0; |
|
1580
|
|
|
pauseAttachmentMaintenance($to_fix); |
|
1581
|
|
|
} |
|
1582
|
|
|
|
|
1583
|
|
|
// What about files who are not recorded in the database? |
|
1584
|
|
|
if ($_GET['step'] <= 5) |
|
1585
|
|
|
{ |
|
1586
|
|
|
$attach_dirs = $modSettings['attachmentUploadDir']; |
|
1587
|
|
|
|
|
1588
|
|
|
$current_check = 0; |
|
1589
|
|
|
$max_checks = 500; |
|
1590
|
|
|
$files_checked = empty($_GET['substep']) ? 0 : $_GET['substep']; |
|
1591
|
|
|
foreach ($attach_dirs as $attach_dir) |
|
1592
|
|
|
{ |
|
1593
|
|
|
if ($dir = @opendir($attach_dir)) |
|
1594
|
|
|
{ |
|
1595
|
|
|
while ($file = readdir($dir)) |
|
1596
|
|
|
{ |
|
1597
|
|
|
if (in_array($file, array('.', '..', '.htaccess', 'index.php'))) |
|
1598
|
|
|
continue; |
|
1599
|
|
|
|
|
1600
|
|
|
if ($files_checked <= $current_check) |
|
1601
|
|
|
{ |
|
1602
|
|
|
// Temporary file, get rid of it! |
|
1603
|
|
|
if (strpos($file, 'post_tmp_') !== false) |
|
1604
|
|
|
{ |
|
1605
|
|
|
// Temp file is more than 5 hours old! |
|
1606
|
|
View Code Duplication |
if (filemtime($attach_dir . '/' . $file) < time() - 18000) |
|
|
|
|
|
|
1607
|
|
|
@unlink($attach_dir . '/' . $file); |
|
|
|
|
|
|
1608
|
|
|
} |
|
1609
|
|
|
// That should be an attachment, let's check if we have it in the database |
|
1610
|
|
|
elseif (strpos($file, '_') !== false) |
|
1611
|
|
|
{ |
|
1612
|
|
|
$attachID = (int) substr($file, 0, strpos($file, '_')); |
|
1613
|
|
|
if (!empty($attachID)) |
|
1614
|
|
|
{ |
|
1615
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1616
|
|
|
SELECT id_attach |
|
1617
|
|
|
FROM {db_prefix}attachments |
|
1618
|
|
|
WHERE id_attach = {int:attachment_id} |
|
1619
|
|
|
LIMIT 1', |
|
1620
|
|
|
array( |
|
1621
|
|
|
'attachment_id' => $attachID, |
|
1622
|
|
|
) |
|
1623
|
|
|
); |
|
1624
|
|
|
if ($smcFunc['db_num_rows']($request) == 0) |
|
1625
|
|
|
{ |
|
1626
|
|
View Code Duplication |
if ($fix_errors && in_array('files_without_attachment', $to_fix)) |
|
|
|
|
|
|
1627
|
|
|
{ |
|
1628
|
|
|
@unlink($attach_dir . '/' . $file); |
|
|
|
|
|
|
1629
|
|
|
} |
|
1630
|
|
|
else |
|
1631
|
|
|
{ |
|
1632
|
|
|
$context['repair_errors']['files_without_attachment']++; |
|
1633
|
|
|
$to_fix[] = 'files_without_attachment'; |
|
1634
|
|
|
} |
|
1635
|
|
|
} |
|
1636
|
|
|
$smcFunc['db_free_result']($request); |
|
1637
|
|
|
} |
|
1638
|
|
|
} |
|
1639
|
|
View Code Duplication |
else |
|
|
|
|
|
|
1640
|
|
|
{ |
|
1641
|
|
|
if ($fix_errors && in_array('files_without_attachment', $to_fix)) |
|
1642
|
|
|
{ |
|
1643
|
|
|
@unlink($attach_dir . '/' . $file); |
|
|
|
|
|
|
1644
|
|
|
} |
|
1645
|
|
|
else |
|
1646
|
|
|
{ |
|
1647
|
|
|
$context['repair_errors']['files_without_attachment']++; |
|
1648
|
|
|
$to_fix[] = 'files_without_attachment'; |
|
1649
|
|
|
} |
|
1650
|
|
|
} |
|
1651
|
|
|
} |
|
1652
|
|
|
$current_check++; |
|
1653
|
|
|
$_GET['substep'] = $current_check; |
|
1654
|
|
|
if ($current_check - $files_checked >= $max_checks) |
|
1655
|
|
|
pauseAttachmentMaintenance($to_fix); |
|
1656
|
|
|
} |
|
1657
|
|
|
closedir($dir); |
|
1658
|
|
|
} |
|
1659
|
|
|
} |
|
1660
|
|
|
|
|
1661
|
|
|
$_GET['step'] = 5; |
|
1662
|
|
|
$_GET['substep'] = 0; |
|
1663
|
|
|
pauseAttachmentMaintenance($to_fix); |
|
1664
|
|
|
} |
|
1665
|
|
|
|
|
1666
|
|
|
// Got here we must be doing well - just the template! :D |
|
1667
|
|
|
$context['page_title'] = $txt['repair_attachments']; |
|
1668
|
|
|
$context[$context['admin_menu_name']]['current_subsection'] = 'maintenance'; |
|
1669
|
|
|
$context['sub_template'] = 'attachment_repair'; |
|
1670
|
|
|
|
|
1671
|
|
|
// What stage are we at? |
|
1672
|
|
|
$context['completed'] = $fix_errors ? true : false; |
|
1673
|
|
|
$context['errors_found'] = !empty($to_fix) ? true : false; |
|
1674
|
|
|
|
|
1675
|
|
|
} |
|
1676
|
|
|
|
|
1677
|
|
|
/** |
|
1678
|
|
|
* Function called in-between each round of attachments and avatar repairs. |
|
1679
|
|
|
* Called by repairAttachments(). |
|
1680
|
|
|
* If repairAttachments() has more steps added, this function needs updated! |
|
1681
|
|
|
* |
|
1682
|
|
|
* @param array $to_fix IDs of attachments to fix |
|
1683
|
|
|
* @param int The maximum substep to reach before pausing |
|
1684
|
|
|
*/ |
|
1685
|
|
|
function pauseAttachmentMaintenance($to_fix, $max_substep = 0) |
|
1686
|
|
|
{ |
|
1687
|
|
|
global $context, $txt, $time_start; |
|
1688
|
|
|
|
|
1689
|
|
|
// Try get more time... |
|
1690
|
|
|
@set_time_limit(600); |
|
|
|
|
|
|
1691
|
|
|
if (function_exists('apache_reset_timeout')) |
|
1692
|
|
|
@apache_reset_timeout(); |
|
|
|
|
|
|
1693
|
|
|
|
|
1694
|
|
|
// Have we already used our maximum time? |
|
1695
|
|
|
if (time() - array_sum(explode(' ', $time_start)) < 3 || $context['starting_substep'] == $_GET['substep']) |
|
1696
|
|
|
return; |
|
1697
|
|
|
|
|
1698
|
|
|
$context['continue_get_data'] = '?action=admin;area=manageattachments;sa=repair' . (isset($_GET['fixErrors']) ? ';fixErrors' : '') . ';step=' . $_GET['step'] . ';substep=' . $_GET['substep'] . ';' . $context['session_var'] . '=' . $context['session_id']; |
|
1699
|
|
|
$context['page_title'] = $txt['not_done_title']; |
|
1700
|
|
|
$context['continue_post_data'] = ''; |
|
1701
|
|
|
$context['continue_countdown'] = '2'; |
|
1702
|
|
|
$context['sub_template'] = 'not_done'; |
|
1703
|
|
|
|
|
1704
|
|
|
// Specific stuff to not break this template! |
|
1705
|
|
|
$context[$context['admin_menu_name']]['current_subsection'] = 'maintenance'; |
|
1706
|
|
|
|
|
1707
|
|
|
// Change these two if more steps are added! |
|
1708
|
|
|
if (empty($max_substep)) |
|
1709
|
|
|
$context['continue_percent'] = round(($_GET['step'] * 100) / 25); |
|
1710
|
|
View Code Duplication |
else |
|
|
|
|
|
|
1711
|
|
|
$context['continue_percent'] = round(($_GET['step'] * 100 + ($_GET['substep'] * 100) / $max_substep) / 25); |
|
1712
|
|
|
|
|
1713
|
|
|
// Never more than 100%! |
|
1714
|
|
|
$context['continue_percent'] = min($context['continue_percent'], 100); |
|
1715
|
|
|
|
|
1716
|
|
|
$_SESSION['attachments_to_fix'] = $to_fix; |
|
1717
|
|
|
$_SESSION['attachments_to_fix2'] = $context['repair_errors']; |
|
1718
|
|
|
|
|
1719
|
|
|
obExit(); |
|
1720
|
|
|
} |
|
1721
|
|
|
|
|
1722
|
|
|
/** |
|
1723
|
|
|
* Called from a mouse click, works out what we want to do with attachments and actions it. |
|
1724
|
|
|
*/ |
|
1725
|
|
|
function ApproveAttach() |
|
1726
|
|
|
{ |
|
1727
|
|
|
global $smcFunc; |
|
1728
|
|
|
|
|
1729
|
|
|
// Security is our primary concern... |
|
1730
|
|
|
checkSession('get'); |
|
1731
|
|
|
|
|
1732
|
|
|
// If it approve or delete? |
|
1733
|
|
|
$is_approve = !isset($_GET['sa']) || $_GET['sa'] != 'reject' ? true : false; |
|
1734
|
|
|
|
|
1735
|
|
|
$attachments = array(); |
|
1736
|
|
|
// If we are approving all ID's in a message , get the ID's. |
|
1737
|
|
|
if ($_GET['sa'] == 'all' && !empty($_GET['mid'])) |
|
1738
|
|
|
{ |
|
1739
|
|
|
$id_msg = (int) $_GET['mid']; |
|
1740
|
|
|
|
|
1741
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1742
|
|
|
SELECT id_attach |
|
1743
|
|
|
FROM {db_prefix}attachments |
|
1744
|
|
|
WHERE id_msg = {int:id_msg} |
|
1745
|
|
|
AND approved = {int:is_approved} |
|
1746
|
|
|
AND attachment_type = {int:attachment_type}', |
|
1747
|
|
|
array( |
|
1748
|
|
|
'id_msg' => $id_msg, |
|
1749
|
|
|
'is_approved' => 0, |
|
1750
|
|
|
'attachment_type' => 0, |
|
1751
|
|
|
) |
|
1752
|
|
|
); |
|
1753
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
1754
|
|
|
$attachments[] = $row['id_attach']; |
|
1755
|
|
|
$smcFunc['db_free_result']($request); |
|
1756
|
|
|
} |
|
1757
|
|
|
elseif (!empty($_GET['aid'])) |
|
1758
|
|
|
$attachments[] = (int) $_GET['aid']; |
|
1759
|
|
|
|
|
1760
|
|
|
if (empty($attachments)) |
|
1761
|
|
|
fatal_lang_error('no_access', false); |
|
|
|
|
|
|
1762
|
|
|
|
|
1763
|
|
|
// Now we have some ID's cleaned and ready to approve, but first - let's check we have permission! |
|
1764
|
|
|
$allowed_boards = boardsAllowedTo('approve_posts'); |
|
1765
|
|
|
|
|
1766
|
|
|
// Validate the attachments exist and are the right approval state. |
|
1767
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1768
|
|
|
SELECT a.id_attach, m.id_board, m.id_msg, m.id_topic |
|
1769
|
|
|
FROM {db_prefix}attachments AS a |
|
1770
|
|
|
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg) |
|
1771
|
|
|
WHERE a.id_attach IN ({array_int:attachments}) |
|
1772
|
|
|
AND a.attachment_type = {int:attachment_type} |
|
1773
|
|
|
AND a.approved = {int:is_approved}', |
|
1774
|
|
|
array( |
|
1775
|
|
|
'attachments' => $attachments, |
|
1776
|
|
|
'attachment_type' => 0, |
|
1777
|
|
|
'is_approved' => 0, |
|
1778
|
|
|
) |
|
1779
|
|
|
); |
|
1780
|
|
|
$attachments = array(); |
|
1781
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
1782
|
|
|
{ |
|
1783
|
|
|
// We can only add it if we can approve in this board! |
|
1784
|
|
|
if ($allowed_boards = array(0) || in_array($row['id_board'], $allowed_boards)) |
|
|
|
|
|
|
1785
|
|
|
{ |
|
1786
|
|
|
$attachments[] = $row['id_attach']; |
|
1787
|
|
|
|
|
1788
|
|
|
// Also come up with the redirection URL. |
|
1789
|
|
|
$redirect = 'topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg']; |
|
1790
|
|
|
} |
|
1791
|
|
|
} |
|
1792
|
|
|
$smcFunc['db_free_result']($request); |
|
1793
|
|
|
|
|
1794
|
|
|
if (empty($attachments)) |
|
1795
|
|
|
fatal_lang_error('no_access', false); |
|
|
|
|
|
|
1796
|
|
|
|
|
1797
|
|
|
// Finally, we are there. Follow through! |
|
1798
|
|
|
if ($is_approve) |
|
1799
|
|
|
{ |
|
1800
|
|
|
// Checked and deemed worthy. |
|
1801
|
|
|
ApproveAttachments($attachments); |
|
1802
|
|
|
} |
|
1803
|
|
|
else |
|
1804
|
|
|
removeAttachments(array('id_attach' => $attachments, 'do_logging' => true)); |
|
1805
|
|
|
|
|
1806
|
|
|
// Return to the topic.... |
|
1807
|
|
|
redirectexit($redirect); |
|
|
|
|
|
|
1808
|
|
|
} |
|
1809
|
|
|
|
|
1810
|
|
|
/** |
|
1811
|
|
|
* Approve an attachment, or maybe even more - no permission check! |
|
1812
|
|
|
* |
|
1813
|
|
|
* @param array $attachments The IDs of the attachments to approve |
|
1814
|
|
|
* @return void|int Returns 0 if the operation failed, otherwise returns nothing |
|
1815
|
|
|
*/ |
|
1816
|
|
|
function ApproveAttachments($attachments) |
|
1817
|
|
|
{ |
|
1818
|
|
|
global $smcFunc; |
|
1819
|
|
|
|
|
1820
|
|
|
if (empty($attachments)) |
|
1821
|
|
|
return 0; |
|
1822
|
|
|
|
|
1823
|
|
|
// For safety, check for thumbnails... |
|
1824
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1825
|
|
|
SELECT |
|
1826
|
|
|
a.id_attach, a.id_member, COALESCE(thumb.id_attach, 0) AS id_thumb |
|
1827
|
|
|
FROM {db_prefix}attachments AS a |
|
1828
|
|
|
LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb) |
|
1829
|
|
|
WHERE a.id_attach IN ({array_int:attachments}) |
|
1830
|
|
|
AND a.attachment_type = {int:attachment_type}', |
|
1831
|
|
|
array( |
|
1832
|
|
|
'attachments' => $attachments, |
|
1833
|
|
|
'attachment_type' => 0, |
|
1834
|
|
|
) |
|
1835
|
|
|
); |
|
1836
|
|
|
$attachments = array(); |
|
1837
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
1838
|
|
|
{ |
|
1839
|
|
|
// Update the thumbnail too... |
|
1840
|
|
|
if (!empty($row['id_thumb'])) |
|
1841
|
|
|
$attachments[] = $row['id_thumb']; |
|
1842
|
|
|
|
|
1843
|
|
|
$attachments[] = $row['id_attach']; |
|
1844
|
|
|
} |
|
1845
|
|
|
$smcFunc['db_free_result']($request); |
|
1846
|
|
|
|
|
1847
|
|
|
if (empty($attachments)) |
|
1848
|
|
|
return 0; |
|
1849
|
|
|
|
|
1850
|
|
|
// Approving an attachment is not hard - it's easy. |
|
1851
|
|
|
$smcFunc['db_query']('', ' |
|
1852
|
|
|
UPDATE {db_prefix}attachments |
|
1853
|
|
|
SET approved = {int:is_approved} |
|
1854
|
|
|
WHERE id_attach IN ({array_int:attachments})', |
|
1855
|
|
|
array( |
|
1856
|
|
|
'attachments' => $attachments, |
|
1857
|
|
|
'is_approved' => 1, |
|
1858
|
|
|
) |
|
1859
|
|
|
); |
|
1860
|
|
|
|
|
1861
|
|
|
// In order to log the attachments, we really need their message and filename |
|
1862
|
|
|
$request = $smcFunc['db_query']('', ' |
|
1863
|
|
|
SELECT m.id_msg, a.filename |
|
1864
|
|
|
FROM {db_prefix}attachments AS a |
|
1865
|
|
|
INNER JOIN {db_prefix}messages AS m ON (a.id_msg = m.id_msg) |
|
1866
|
|
|
WHERE a.id_attach IN ({array_int:attachments}) |
|
1867
|
|
|
AND a.attachment_type = {int:attachment_type}', |
|
1868
|
|
|
array( |
|
1869
|
|
|
'attachments' => $attachments, |
|
1870
|
|
|
'attachment_type' => 0, |
|
1871
|
|
|
) |
|
1872
|
|
|
); |
|
1873
|
|
|
|
|
1874
|
|
View Code Duplication |
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
|
|
|
|
|
1875
|
|
|
logAction( |
|
1876
|
|
|
'approve_attach', |
|
1877
|
|
|
array( |
|
1878
|
|
|
'message' => $row['id_msg'], |
|
1879
|
|
|
'filename' => preg_replace('~&#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', $smcFunc['htmlspecialchars']($row['filename'])), |
|
1880
|
|
|
) |
|
1881
|
|
|
); |
|
1882
|
|
|
$smcFunc['db_free_result']($request); |
|
1883
|
|
|
|
|
1884
|
|
|
// Remove from the approval queue. |
|
1885
|
|
|
$smcFunc['db_query']('', ' |
|
1886
|
|
|
DELETE FROM {db_prefix}approval_queue |
|
1887
|
|
|
WHERE id_attach IN ({array_int:attachments})', |
|
1888
|
|
|
array( |
|
1889
|
|
|
'attachments' => $attachments, |
|
1890
|
|
|
) |
|
1891
|
|
|
); |
|
1892
|
|
|
|
|
1893
|
|
|
call_integration_hook('integrate_approve_attachments', array($attachments)); |
|
1894
|
|
|
} |
|
1895
|
|
|
|
|
1896
|
|
|
/** |
|
1897
|
|
|
* This function lists and allows updating of multiple attachments paths. |
|
1898
|
|
|
*/ |
|
1899
|
|
|
function ManageAttachmentPaths() |
|
1900
|
|
|
{ |
|
1901
|
|
|
global $modSettings, $scripturl, $context, $txt, $sourcedir, $boarddir, $smcFunc, $settings; |
|
1902
|
|
|
|
|
1903
|
|
|
// Since this needs to be done eventually. |
|
1904
|
|
|
if (!isset($modSettings['attachment_basedirectories'])) |
|
1905
|
|
|
$modSettings['attachment_basedirectories'] = array(); |
|
1906
|
|
|
|
|
1907
|
|
|
elseif (!is_array($modSettings['attachment_basedirectories'])) |
|
1908
|
|
|
$modSettings['attachment_basedirectories'] = smf_json_decode($modSettings['attachment_basedirectories'], true); |
|
1909
|
|
|
|
|
1910
|
|
|
$errors = array(); |
|
1911
|
|
|
|
|
1912
|
|
|
// Saving? |
|
1913
|
|
|
if (isset($_REQUEST['save'])) |
|
1914
|
|
|
{ |
|
1915
|
|
|
checkSession(); |
|
1916
|
|
|
|
|
1917
|
|
|
$_POST['current_dir'] = (int) $_POST['current_dir']; |
|
1918
|
|
|
$new_dirs = array(); |
|
1919
|
|
|
foreach ($_POST['dirs'] as $id => $path) |
|
1920
|
|
|
{ |
|
1921
|
|
|
$error = ''; |
|
1922
|
|
|
$id = (int) $id; |
|
1923
|
|
|
if ($id < 1) |
|
1924
|
|
|
continue; |
|
1925
|
|
|
|
|
1926
|
|
|
// Sorry, these dirs are NOT valid |
|
1927
|
|
|
$invalid_dirs = array($boarddir, $settings['default_theme_dir'], $sourcedir); |
|
1928
|
|
|
if (in_array($path, $invalid_dirs)) |
|
1929
|
|
|
{ |
|
1930
|
|
|
$errors[] = $path . ': ' . $txt['attach_dir_invalid']; |
|
1931
|
|
|
continue; |
|
1932
|
|
|
} |
|
1933
|
|
|
|
|
1934
|
|
|
// Hmm, a new path maybe? |
|
1935
|
|
|
// Don't allow empty paths |
|
1936
|
|
|
if (!array_key_exists($id, $modSettings['attachmentUploadDir']) && !empty($path)) |
|
1937
|
|
|
{ |
|
1938
|
|
|
// or is it? |
|
1939
|
|
|
if (in_array($path, $modSettings['attachmentUploadDir']) || in_array($boarddir . DIRECTORY_SEPARATOR . $path, $modSettings['attachmentUploadDir'])) |
|
1940
|
|
|
{ |
|
1941
|
|
|
$errors[] = $path . ': ' . $txt['attach_dir_duplicate_msg']; |
|
1942
|
|
|
continue; |
|
1943
|
|
|
} |
|
1944
|
|
|
elseif (empty($path)) |
|
1945
|
|
|
{ |
|
1946
|
|
|
// Ignore this and set $id to one less |
|
1947
|
|
|
continue; |
|
1948
|
|
|
} |
|
1949
|
|
|
|
|
1950
|
|
|
// OK, so let's try to create it then. |
|
1951
|
|
|
require_once($sourcedir . '/Subs-Attachments.php'); |
|
1952
|
|
|
if (automanage_attachments_create_directory($path)) |
|
1953
|
|
|
$_POST['current_dir'] = $modSettings['currentAttachmentUploadDir']; |
|
1954
|
|
|
else |
|
1955
|
|
|
$errors[] = $path . ': ' . $txt[$context['dir_creation_error']]; |
|
1956
|
|
|
} |
|
1957
|
|
|
|
|
1958
|
|
|
// Changing a directory name? |
|
1959
|
|
|
if (!empty($modSettings['attachmentUploadDir'][$id]) && !empty($path) && $path != $modSettings['attachmentUploadDir'][$id]) |
|
1960
|
|
|
{ |
|
1961
|
|
|
if ($path != $modSettings['attachmentUploadDir'][$id] && !is_dir($path)) |
|
1962
|
|
|
{ |
|
1963
|
|
|
if (!@rename($modSettings['attachmentUploadDir'][$id], $path)) |
|
1964
|
|
|
{ |
|
1965
|
|
|
$errors[] = $path . ': ' . $txt['attach_dir_no_rename']; |
|
1966
|
|
|
$path = $modSettings['attachmentUploadDir'][$id]; |
|
1967
|
|
|
} |
|
1968
|
|
|
} |
|
1969
|
|
|
else |
|
1970
|
|
|
{ |
|
1971
|
|
|
$errors[] = $path . ': ' . $txt['attach_dir_exists_msg']; |
|
1972
|
|
|
$path = $modSettings['attachmentUploadDir'][$id]; |
|
1973
|
|
|
} |
|
1974
|
|
|
|
|
1975
|
|
|
// Update the base directory path |
|
1976
|
|
|
if (!empty($modSettings['attachment_basedirectories']) && array_key_exists($id, $modSettings['attachment_basedirectories'])) |
|
1977
|
|
|
{ |
|
1978
|
|
|
$base = $modSettings['basedirectory_for_attachments'] == $modSettings['attachmentUploadDir'][$id] ? $path : $modSettings['basedirectory_for_attachments']; |
|
1979
|
|
|
|
|
1980
|
|
|
$modSettings['attachment_basedirectories'][$id] = $path; |
|
1981
|
|
|
updateSettings(array( |
|
1982
|
|
|
'attachment_basedirectories' => json_encode($modSettings['attachment_basedirectories']), |
|
1983
|
|
|
'basedirectory_for_attachments' => $base, |
|
1984
|
|
|
)); |
|
1985
|
|
|
$modSettings['attachment_basedirectories'] = smf_json_decode($modSettings['attachment_basedirectories'], true); |
|
|
|
|
|
|
1986
|
|
|
} |
|
1987
|
|
|
} |
|
1988
|
|
|
|
|
1989
|
|
|
if (empty($path)) |
|
1990
|
|
|
{ |
|
1991
|
|
|
$path = $modSettings['attachmentUploadDir'][$id]; |
|
1992
|
|
|
|
|
1993
|
|
|
// It's not a good idea to delete the current directory. |
|
1994
|
|
|
if ($id == (!empty($_POST['current_dir']) ? $_POST['current_dir'] : $modSettings['currentAttachmentUploadDir'])) |
|
1995
|
|
|
$errors[] = $path . ': ' . $txt['attach_dir_is_current']; |
|
1996
|
|
|
// Or the current base directory |
|
1997
|
|
|
elseif (!empty($modSettings['basedirectory_for_attachments']) && $modSettings['basedirectory_for_attachments'] == $modSettings['attachmentUploadDir'][$id]) |
|
1998
|
|
|
$errors[] = $path . ': ' . $txt['attach_dir_is_current_bd']; |
|
1999
|
|
|
else |
|
2000
|
|
|
{ |
|
2001
|
|
|
// Let's not try to delete a path with files in it. |
|
2002
|
|
|
$request = $smcFunc['db_query']('', ' |
|
2003
|
|
|
SELECT COUNT(id_attach) AS num_attach |
|
2004
|
|
|
FROM {db_prefix}attachments |
|
2005
|
|
|
WHERE id_folder = {int:id_folder}', |
|
2006
|
|
|
array( |
|
2007
|
|
|
'id_folder' => (int) $id, |
|
2008
|
|
|
) |
|
2009
|
|
|
); |
|
2010
|
|
|
|
|
2011
|
|
|
list ($num_attach) = $smcFunc['db_fetch_row']($request); |
|
2012
|
|
|
$smcFunc['db_free_result']($request); |
|
2013
|
|
|
|
|
2014
|
|
|
// A check to see if it's a used base dir. |
|
2015
|
|
|
if (!empty($modSettings['attachment_basedirectories'])) |
|
2016
|
|
|
{ |
|
2017
|
|
|
// Count any sub-folders. |
|
2018
|
|
View Code Duplication |
foreach ($modSettings['attachmentUploadDir'] as $sub) |
|
|
|
|
|
|
2019
|
|
|
if (strpos($sub, $path . DIRECTORY_SEPARATOR) !== false) |
|
2020
|
|
|
$num_attach++; |
|
2021
|
|
|
} |
|
2022
|
|
|
|
|
2023
|
|
|
// It's safe to delete. So try to delete the folder also |
|
2024
|
|
|
if ($num_attach == 0) |
|
2025
|
|
|
{ |
|
2026
|
|
|
if (is_dir($path)) |
|
2027
|
|
|
$doit = true; |
|
2028
|
|
|
elseif (is_dir($boarddir . DIRECTORY_SEPARATOR . $path)) |
|
2029
|
|
|
{ |
|
2030
|
|
|
$doit = true; |
|
2031
|
|
|
$path = $boarddir . DIRECTORY_SEPARATOR . $path; |
|
2032
|
|
|
} |
|
2033
|
|
|
|
|
2034
|
|
|
if (isset($doit) && realpath($path) != realpath($boarddir)) |
|
2035
|
|
|
{ |
|
2036
|
|
|
unlink($path . '/.htaccess'); |
|
2037
|
|
|
unlink($path . '/index.php'); |
|
2038
|
|
|
if (!@rmdir($path)) |
|
2039
|
|
|
$error = $path . ': ' . $txt['attach_dir_no_delete']; |
|
2040
|
|
|
} |
|
2041
|
|
|
|
|
2042
|
|
|
// Remove it from the base directory list. |
|
2043
|
|
|
if (empty($error) && !empty($modSettings['attachment_basedirectories'])) |
|
2044
|
|
|
{ |
|
2045
|
|
|
unset($modSettings['attachment_basedirectories'][$id]); |
|
2046
|
|
|
updateSettings(array('attachment_basedirectories' => json_encode($modSettings['attachment_basedirectories']))); |
|
2047
|
|
|
$modSettings['attachment_basedirectories'] = smf_json_decode($modSettings['attachment_basedirectories'], true); |
|
|
|
|
|
|
2048
|
|
|
} |
|
2049
|
|
|
} |
|
2050
|
|
|
else |
|
2051
|
|
|
$error = $path . ': ' . $txt['attach_dir_no_remove']; |
|
2052
|
|
|
|
|
2053
|
|
|
if (empty($error)) |
|
2054
|
|
|
continue; |
|
2055
|
|
|
else |
|
2056
|
|
|
$errors[] = $error; |
|
2057
|
|
|
} |
|
2058
|
|
|
} |
|
2059
|
|
|
|
|
2060
|
|
|
$new_dirs[$id] = $path; |
|
2061
|
|
|
} |
|
2062
|
|
|
|
|
2063
|
|
|
// We need to make sure the current directory is right. |
|
2064
|
|
|
if (empty($_POST['current_dir']) && !empty($modSettings['currentAttachmentUploadDir'])) |
|
2065
|
|
|
$_POST['current_dir'] = $modSettings['currentAttachmentUploadDir']; |
|
2066
|
|
|
|
|
2067
|
|
|
// Find the current directory if there's no value carried, |
|
2068
|
|
|
if (empty($_POST['current_dir']) || empty($new_dirs[$_POST['current_dir']])) |
|
2069
|
|
|
{ |
|
2070
|
|
|
if (array_key_exists($modSettings['currentAttachmentUploadDir'], $modSettings['attachmentUploadDir'])) |
|
2071
|
|
|
$_POST['current_dir'] = $modSettings['currentAttachmentUploadDir']; |
|
2072
|
|
|
else |
|
2073
|
|
|
$_POST['current_dir'] = max(array_keys($modSettings['attachmentUploadDir'])); |
|
2074
|
|
|
} |
|
2075
|
|
|
|
|
2076
|
|
|
// If the user wishes to go back, update the last_dir array |
|
2077
|
|
|
if ($_POST['current_dir'] != $modSettings['currentAttachmentUploadDir']&& !empty($modSettings['last_attachments_directory']) && (isset($modSettings['last_attachments_directory'][$_POST['current_dir']]) || isset($modSettings['last_attachments_directory'][0]))) |
|
2078
|
|
|
{ |
|
2079
|
|
View Code Duplication |
if (!is_array($modSettings['last_attachments_directory'])) |
|
|
|
|
|
|
2080
|
|
|
$modSettings['last_attachments_directory'] = smf_json_decode($modSettings['last_attachments_directory'], true); |
|
2081
|
|
|
$num = substr(strrchr($modSettings['attachmentUploadDir'][$_POST['current_dir']], '_'), 1); |
|
2082
|
|
|
|
|
2083
|
|
|
if (is_numeric($num)) |
|
2084
|
|
|
{ |
|
2085
|
|
|
// Need to find the base folder. |
|
2086
|
|
|
$bid = -1; |
|
2087
|
|
|
$use_subdirectories_for_attachments = 0; |
|
2088
|
|
|
if (!empty($modSettings['attachment_basedirectories'])) |
|
2089
|
|
|
foreach ($modSettings['attachment_basedirectories'] as $bid => $base) |
|
2090
|
|
View Code Duplication |
if (strpos($modSettings['attachmentUploadDir'][$_POST['current_dir']], $base . DIRECTORY_SEPARATOR) !==false) |
|
|
|
|
|
|
2091
|
|
|
{ |
|
2092
|
|
|
$use_subdirectories_for_attachments = 1; |
|
2093
|
|
|
break; |
|
2094
|
|
|
} |
|
2095
|
|
|
|
|
2096
|
|
View Code Duplication |
if ($use_subdirectories_for_attachments == 0 && strpos($modSettings['attachmentUploadDir'][$_POST['current_dir']], $boarddir . DIRECTORY_SEPARATOR) !== false) |
|
|
|
|
|
|
2097
|
|
|
$bid = 0; |
|
2098
|
|
|
|
|
2099
|
|
|
$modSettings['last_attachments_directory'][$bid] = (int) $num; |
|
2100
|
|
|
$modSettings['basedirectory_for_attachments'] = !empty($modSettings['basedirectory_for_attachments']) ? $modSettings['basedirectory_for_attachments'] : ''; |
|
2101
|
|
|
$modSettings['use_subdirectories_for_attachments'] = !empty($modSettings['use_subdirectories_for_attachments']) ? $modSettings['use_subdirectories_for_attachments'] : 0; |
|
2102
|
|
|
updateSettings(array( |
|
2103
|
|
|
'last_attachments_directory' => json_encode($modSettings['last_attachments_directory']), |
|
2104
|
|
|
'basedirectory_for_attachments' => $bid == 0 ? $modSettings['basedirectory_for_attachments'] : $modSettings['attachment_basedirectories'][$bid], |
|
2105
|
|
|
'use_subdirectories_for_attachments' => $use_subdirectories_for_attachments, |
|
2106
|
|
|
)); |
|
2107
|
|
|
} |
|
2108
|
|
|
} |
|
2109
|
|
|
|
|
2110
|
|
|
// Going back to just one path? |
|
2111
|
|
|
if (count($new_dirs) == 1) |
|
2112
|
|
|
{ |
|
2113
|
|
|
// We might need to reset the paths. This loop will just loop through once. |
|
2114
|
|
|
foreach ($new_dirs as $id => $dir) |
|
2115
|
|
|
{ |
|
2116
|
|
|
if ($id != 1) |
|
2117
|
|
|
$smcFunc['db_query']('', ' |
|
2118
|
|
|
UPDATE {db_prefix}attachments |
|
2119
|
|
|
SET id_folder = {int:default_folder} |
|
2120
|
|
|
WHERE id_folder = {int:current_folder}', |
|
2121
|
|
|
array( |
|
2122
|
|
|
'default_folder' => 1, |
|
2123
|
|
|
'current_folder' => $id, |
|
2124
|
|
|
) |
|
2125
|
|
|
); |
|
2126
|
|
|
|
|
2127
|
|
|
$update = array( |
|
2128
|
|
|
'currentAttachmentUploadDir' => 1, |
|
2129
|
|
|
'attachmentUploadDir' => json_encode(array(1 => $dir)), |
|
2130
|
|
|
); |
|
2131
|
|
|
} |
|
2132
|
|
|
} |
|
2133
|
|
|
else |
|
2134
|
|
|
{ |
|
2135
|
|
|
// Save it to the database. |
|
2136
|
|
|
$update = array( |
|
2137
|
|
|
'currentAttachmentUploadDir' => $_POST['current_dir'], |
|
2138
|
|
|
'attachmentUploadDir' => json_encode($new_dirs), |
|
2139
|
|
|
); |
|
2140
|
|
|
} |
|
2141
|
|
|
|
|
2142
|
|
|
if (!empty($update)) |
|
2143
|
|
|
updateSettings($update); |
|
2144
|
|
|
|
|
2145
|
|
|
if (!empty($errors)) |
|
2146
|
|
|
$_SESSION['errors']['dir'] = $errors; |
|
2147
|
|
|
|
|
2148
|
|
|
redirectexit('action=admin;area=manageattachments;sa=attachpaths;' . $context['session_var'] . '=' . $context['session_id']); |
|
2149
|
|
|
} |
|
2150
|
|
|
|
|
2151
|
|
|
// Saving a base directory? |
|
2152
|
|
|
if (isset($_REQUEST['save2'])) |
|
2153
|
|
|
{ |
|
2154
|
|
|
checkSession(); |
|
2155
|
|
|
|
|
2156
|
|
|
// Changing the current base directory? |
|
2157
|
|
|
$_POST['current_base_dir'] = isset($_POST['current_base_dir']) ? (int) $_POST['current_base_dir'] : 1; |
|
2158
|
|
|
if (empty($_POST['new_base_dir']) && !empty($_POST['current_base_dir'])) |
|
2159
|
|
|
{ |
|
2160
|
|
View Code Duplication |
if ($modSettings['basedirectory_for_attachments'] != $modSettings['attachmentUploadDir'][$_POST['current_base_dir']]) |
|
|
|
|
|
|
2161
|
|
|
$update = (array( |
|
2162
|
|
|
'basedirectory_for_attachments' => $modSettings['attachmentUploadDir'][$_POST['current_base_dir']], |
|
2163
|
|
|
)); |
|
2164
|
|
|
} |
|
2165
|
|
|
|
|
2166
|
|
|
if (isset($_POST['base_dir'])) |
|
2167
|
|
|
{ |
|
2168
|
|
|
foreach ($_POST['base_dir'] as $id => $dir) |
|
2169
|
|
|
{ |
|
2170
|
|
|
if (!empty($dir) && $dir != $modSettings['attachmentUploadDir'][$id]) |
|
2171
|
|
|
{ |
|
2172
|
|
|
if (@rename($modSettings['attachmentUploadDir'][$id], $dir)) |
|
2173
|
|
|
{ |
|
2174
|
|
|
$modSettings['attachmentUploadDir'][$id] = $dir; |
|
2175
|
|
|
$modSettings['attachment_basedirectories'][$id] = $dir; |
|
2176
|
|
|
$update = (array( |
|
2177
|
|
|
'attachmentUploadDir' => json_encode($modSettings['attachmentUploadDir']), |
|
2178
|
|
|
'attachment_basedirectories' => json_encode($modSettings['attachment_basedirectories']), |
|
2179
|
|
|
'basedirectory_for_attachments' => $modSettings['attachmentUploadDir'][$_POST['current_base_dir']], |
|
2180
|
|
|
)); |
|
2181
|
|
|
} |
|
2182
|
|
|
} |
|
2183
|
|
|
|
|
2184
|
|
|
if (empty($dir)) |
|
2185
|
|
|
{ |
|
2186
|
|
|
if ($id == $_POST['current_base_dir']) |
|
2187
|
|
|
{ |
|
2188
|
|
|
$errors[] = $modSettings['attachmentUploadDir'][$id] . ': ' . $txt['attach_dir_is_current']; |
|
2189
|
|
|
continue; |
|
2190
|
|
|
} |
|
2191
|
|
|
|
|
2192
|
|
|
unset($modSettings['attachment_basedirectories'][$id]); |
|
2193
|
|
|
$update = (array( |
|
2194
|
|
|
'attachment_basedirectories' => json_encode($modSettings['attachment_basedirectories']), |
|
2195
|
|
|
'basedirectory_for_attachments' => $modSettings['attachmentUploadDir'][$_POST['current_base_dir']], |
|
2196
|
|
|
)); |
|
2197
|
|
|
} |
|
2198
|
|
|
} |
|
2199
|
|
|
} |
|
2200
|
|
|
|
|
2201
|
|
|
// Or adding a new one? |
|
2202
|
|
|
if (!empty($_POST['new_base_dir'])) |
|
2203
|
|
|
{ |
|
2204
|
|
|
require_once($sourcedir . '/Subs-Attachments.php'); |
|
2205
|
|
|
$_POST['new_base_dir'] = $smcFunc['htmlspecialchars']($_POST['new_base_dir'], ENT_QUOTES); |
|
2206
|
|
|
|
|
2207
|
|
|
$current_dir = $modSettings['currentAttachmentUploadDir']; |
|
2208
|
|
|
|
|
2209
|
|
|
if (!in_array($_POST['new_base_dir'], $modSettings['attachmentUploadDir'])) |
|
2210
|
|
|
{ |
|
2211
|
|
|
if (!automanage_attachments_create_directory($_POST['new_base_dir'])) |
|
2212
|
|
|
$errors[] = $_POST['new_base_dir'] . ': ' . $txt['attach_dir_base_no_create']; |
|
2213
|
|
|
} |
|
2214
|
|
|
|
|
2215
|
|
|
$modSettings['currentAttachmentUploadDir'] = array_search($_POST['new_base_dir'], $modSettings['attachmentUploadDir']); |
|
2216
|
|
|
if (!in_array($_POST['new_base_dir'], $modSettings['attachment_basedirectories'])) |
|
2217
|
|
|
$modSettings['attachment_basedirectories'][$modSettings['currentAttachmentUploadDir']] = $_POST['new_base_dir']; |
|
2218
|
|
|
ksort($modSettings['attachment_basedirectories']); |
|
2219
|
|
|
|
|
2220
|
|
|
$update = (array( |
|
2221
|
|
|
'attachment_basedirectories' => json_encode($modSettings['attachment_basedirectories']), |
|
2222
|
|
|
'basedirectory_for_attachments' => $_POST['new_base_dir'], |
|
2223
|
|
|
'currentAttachmentUploadDir' => $current_dir, |
|
2224
|
|
|
)); |
|
2225
|
|
|
} |
|
2226
|
|
|
|
|
2227
|
|
|
if (!empty($errors)) |
|
2228
|
|
|
$_SESSION['errors']['base'] = $errors; |
|
2229
|
|
|
|
|
2230
|
|
|
if (!empty($update)) |
|
2231
|
|
|
updateSettings($update); |
|
2232
|
|
|
|
|
2233
|
|
|
redirectexit('action=admin;area=manageattachments;sa=attachpaths;' . $context['session_var'] . '=' . $context['session_id']); |
|
2234
|
|
|
} |
|
2235
|
|
|
|
|
2236
|
|
|
if (isset($_SESSION['errors'])) |
|
2237
|
|
|
{ |
|
2238
|
|
|
if (is_array($_SESSION['errors'])) |
|
2239
|
|
|
{ |
|
2240
|
|
|
$errors = array(); |
|
2241
|
|
View Code Duplication |
if (!empty($_SESSION['errors']['dir'])) |
|
|
|
|
|
|
2242
|
|
|
foreach ($_SESSION['errors']['dir'] as $error) |
|
2243
|
|
|
$errors['dir'][] = $smcFunc['htmlspecialchars']($error, ENT_QUOTES); |
|
2244
|
|
|
|
|
2245
|
|
View Code Duplication |
if (!empty($_SESSION['errors']['base'])) |
|
|
|
|
|
|
2246
|
|
|
foreach ($_SESSION['errors']['base'] as $error) |
|
2247
|
|
|
$errors['base'][] = $smcFunc['htmlspecialchars']($error, ENT_QUOTES); |
|
2248
|
|
|
} |
|
2249
|
|
|
unset($_SESSION['errors']); |
|
2250
|
|
|
} |
|
2251
|
|
|
|
|
2252
|
|
|
$listOptions = array( |
|
2253
|
|
|
'id' => 'attach_paths', |
|
2254
|
|
|
'base_href' => $scripturl . '?action=admin;area=manageattachments;sa=attachpaths;' . $context['session_var'] . '=' . $context['session_id'], |
|
2255
|
|
|
'title' => $txt['attach_paths'], |
|
2256
|
|
|
'get_items' => array( |
|
2257
|
|
|
'function' => 'list_getAttachDirs', |
|
2258
|
|
|
), |
|
2259
|
|
|
'columns' => array( |
|
2260
|
|
|
'current_dir' => array( |
|
2261
|
|
|
'header' => array( |
|
2262
|
|
|
'value' => $txt['attach_current'], |
|
2263
|
|
|
'class' => 'centercol', |
|
2264
|
|
|
), |
|
2265
|
|
|
'data' => array( |
|
2266
|
|
|
'function' => function ($rowData) |
|
2267
|
|
|
{ |
|
2268
|
|
|
return '<input type="radio" name="current_dir" value="' . $rowData['id'] . '"' . ($rowData['current'] ? ' checked' : '') . (!empty($rowData['disable_current']) ? ' disabled' : '') . ' class="input_radio">'; |
|
2269
|
|
|
}, |
|
2270
|
|
|
'style' => 'width: 10%;', |
|
2271
|
|
|
'class' => 'centercol', |
|
2272
|
|
|
), |
|
2273
|
|
|
), |
|
2274
|
|
|
'path' => array( |
|
2275
|
|
|
'header' => array( |
|
2276
|
|
|
'value' => $txt['attach_path'], |
|
2277
|
|
|
), |
|
2278
|
|
|
'data' => array( |
|
2279
|
|
|
'function' => function ($rowData) |
|
2280
|
|
|
{ |
|
2281
|
|
|
return '<input type="hidden" name="dirs[' . $rowData['id'] . ']" value="' . $rowData['path'] . '"><input type="text" size="40" name="dirs[' . $rowData['id'] . ']" value="' . $rowData['path'] . '"' . (!empty($rowData['disable_base_dir']) ? ' disabled' : '') . ' class="input_text" style="width: 100%">'; |
|
2282
|
|
|
}, |
|
2283
|
|
|
'style' => 'width: 40%;', |
|
2284
|
|
|
), |
|
2285
|
|
|
), |
|
2286
|
|
|
'current_size' => array( |
|
2287
|
|
|
'header' => array( |
|
2288
|
|
|
'value' => $txt['attach_current_size'], |
|
2289
|
|
|
), |
|
2290
|
|
|
'data' => array( |
|
2291
|
|
|
'db' => 'current_size', |
|
2292
|
|
|
'style' => 'width: 15%;', |
|
2293
|
|
|
), |
|
2294
|
|
|
), |
|
2295
|
|
|
'num_files' => array( |
|
2296
|
|
|
'header' => array( |
|
2297
|
|
|
'value' => $txt['attach_num_files'], |
|
2298
|
|
|
), |
|
2299
|
|
|
'data' => array( |
|
2300
|
|
|
'db' => 'num_files', |
|
2301
|
|
|
'style' => 'width: 15%;', |
|
2302
|
|
|
), |
|
2303
|
|
|
), |
|
2304
|
|
|
'status' => array( |
|
2305
|
|
|
'header' => array( |
|
2306
|
|
|
'value' => $txt['attach_dir_status'], |
|
2307
|
|
|
'class' => 'centercol', |
|
2308
|
|
|
), |
|
2309
|
|
|
'data' => array( |
|
2310
|
|
|
'db' => 'status', |
|
2311
|
|
|
'style' => 'width: 25%;', |
|
2312
|
|
|
'class' => 'centercol', |
|
2313
|
|
|
), |
|
2314
|
|
|
), |
|
2315
|
|
|
), |
|
2316
|
|
|
'form' => array( |
|
2317
|
|
|
'href' => $scripturl . '?action=admin;area=manageattachments;sa=attachpaths;' . $context['session_var'] . '=' . $context['session_id'], |
|
2318
|
|
|
), |
|
2319
|
|
|
'additional_rows' => array( |
|
2320
|
|
|
array( |
|
2321
|
|
|
'position' => 'below_table_data', |
|
2322
|
|
|
'value' => ' |
|
2323
|
|
|
<input type="hidden" name="' . $context['session_var'] . '" value="' . $context['session_id'] . '"> |
|
2324
|
|
|
<input type="submit" name="save" value="' . $txt['save'] . '" class="button_submit"> |
|
2325
|
|
|
<input type="submit" name="new_path" value="' . $txt['attach_add_path'] . '" class="button_submit">', |
|
2326
|
|
|
), |
|
2327
|
|
|
empty($errors['dir']) ? array( |
|
2328
|
|
|
'position' => 'top_of_list', |
|
2329
|
|
|
'value' => $txt['attach_dir_desc'], |
|
2330
|
|
|
'style' => 'padding: 5px 10px;', |
|
2331
|
|
|
'class' => 'windowbg2 smalltext' |
|
2332
|
|
|
) : array( |
|
2333
|
|
|
'position' => 'top_of_list', |
|
2334
|
|
|
'value' => $txt['attach_dir_save_problem'] . '<br>' . implode('<br>', $errors['dir']), |
|
2335
|
|
|
'style' => 'padding-left: 35px;', |
|
2336
|
|
|
'class' => 'noticebox', |
|
2337
|
|
|
), |
|
2338
|
|
|
), |
|
2339
|
|
|
); |
|
2340
|
|
|
require_once($sourcedir . '/Subs-List.php'); |
|
2341
|
|
|
createList($listOptions); |
|
2342
|
|
|
|
|
2343
|
|
|
if (!empty($modSettings['attachment_basedirectories'])) |
|
2344
|
|
|
{ |
|
2345
|
|
|
$listOptions2 = array( |
|
2346
|
|
|
'id' => 'base_paths', |
|
2347
|
|
|
'base_href' => $scripturl . '?action=admin;area=manageattachments;sa=attachpaths;' . $context['session_var'] . '=' . $context['session_id'], |
|
2348
|
|
|
'title' => $txt['attach_base_paths'], |
|
2349
|
|
|
'get_items' => array( |
|
2350
|
|
|
'function' => 'list_getBaseDirs', |
|
2351
|
|
|
), |
|
2352
|
|
|
'columns' => array( |
|
2353
|
|
|
'current_dir' => array( |
|
2354
|
|
|
'header' => array( |
|
2355
|
|
|
'value' => $txt['attach_current'], |
|
2356
|
|
|
'class' => 'centercol', |
|
2357
|
|
|
), |
|
2358
|
|
|
'data' => array( |
|
2359
|
|
|
'function' => function ($rowData) |
|
2360
|
|
|
{ |
|
2361
|
|
|
return '<input type="radio" name="current_base_dir" value="' . $rowData['id'] . '"' . ($rowData['current'] ? ' checked' : '') . ' class="input_radio">'; |
|
2362
|
|
|
}, |
|
2363
|
|
|
'style' => 'width: 10%;', |
|
2364
|
|
|
'class' => 'centercol', |
|
2365
|
|
|
), |
|
2366
|
|
|
), |
|
2367
|
|
|
'path' => array( |
|
2368
|
|
|
'header' => array( |
|
2369
|
|
|
'value' => $txt['attach_path'], |
|
2370
|
|
|
), |
|
2371
|
|
|
'data' => array( |
|
2372
|
|
|
'db' => 'path', |
|
2373
|
|
|
'style' => 'width: 45%;', |
|
2374
|
|
|
), |
|
2375
|
|
|
), |
|
2376
|
|
|
'num_dirs' => array( |
|
2377
|
|
|
'header' => array( |
|
2378
|
|
|
'value' => $txt['attach_num_dirs'], |
|
2379
|
|
|
), |
|
2380
|
|
|
'data' => array( |
|
2381
|
|
|
'db' => 'num_dirs', |
|
2382
|
|
|
'style' => 'width: 15%;', |
|
2383
|
|
|
), |
|
2384
|
|
|
), |
|
2385
|
|
|
'status' => array( |
|
2386
|
|
|
'header' => array( |
|
2387
|
|
|
'value' => $txt['attach_dir_status'], |
|
2388
|
|
|
), |
|
2389
|
|
|
'data' => array( |
|
2390
|
|
|
'db' => 'status', |
|
2391
|
|
|
'style' => 'width: 15%;', |
|
2392
|
|
|
'class' => 'centercol', |
|
2393
|
|
|
), |
|
2394
|
|
|
), |
|
2395
|
|
|
), |
|
2396
|
|
|
'form' => array( |
|
2397
|
|
|
'href' => $scripturl . '?action=admin;area=manageattachments;sa=attachpaths;' . $context['session_var'] . '=' . $context['session_id'], |
|
2398
|
|
|
), |
|
2399
|
|
|
'additional_rows' => array( |
|
2400
|
|
|
array( |
|
2401
|
|
|
'position' => 'below_table_data', |
|
2402
|
|
|
'value' => '<input type="hidden" name="' . $context['session_var'] . '" value="' . $context['session_id'] . '"><input type="submit" name="save2" value="' . $txt['save'] . '" class="button_submit"> |
|
2403
|
|
|
<input type="submit" name="new_base_path" value="' . $txt['attach_add_path'] . '" class="button_submit">', |
|
2404
|
|
|
), |
|
2405
|
|
|
empty($errors['base']) ? array( |
|
2406
|
|
|
'position' => 'top_of_list', |
|
2407
|
|
|
'value' => $txt['attach_dir_base_desc'], |
|
2408
|
|
|
'style' => 'padding: 5px 10px;', |
|
2409
|
|
|
'class' => 'windowbg2 smalltext' |
|
2410
|
|
|
) : array( |
|
2411
|
|
|
'position' => 'top_of_list', |
|
2412
|
|
|
'value' => $txt['attach_dir_save_problem'] . '<br>' . implode('<br>', $errors['base']), |
|
2413
|
|
|
'style' => 'padding-left: 35px', |
|
2414
|
|
|
'class' => 'noticebox', |
|
2415
|
|
|
), |
|
2416
|
|
|
), |
|
2417
|
|
|
); |
|
2418
|
|
|
createList($listOptions2); |
|
2419
|
|
|
} |
|
2420
|
|
|
|
|
2421
|
|
|
// Fix up our template. |
|
2422
|
|
|
$context[$context['admin_menu_name']]['current_subsection'] = 'attachpaths'; |
|
2423
|
|
|
$context['page_title'] = $txt['attach_path_manage']; |
|
2424
|
|
|
$context['sub_template'] = 'attachment_paths'; |
|
2425
|
|
|
} |
|
2426
|
|
|
|
|
2427
|
|
|
/** |
|
2428
|
|
|
* Prepare the actual attachment directories to be displayed in the list. |
|
2429
|
|
|
* @return array An array of information about the attachment directories |
|
2430
|
|
|
*/ |
|
2431
|
|
|
function list_getAttachDirs() |
|
2432
|
|
|
{ |
|
2433
|
|
|
global $smcFunc, $modSettings, $context, $txt; |
|
2434
|
|
|
|
|
2435
|
|
|
$request = $smcFunc['db_query']('', ' |
|
2436
|
|
|
SELECT id_folder, COUNT(id_attach) AS num_attach, SUM(size) AS size_attach |
|
2437
|
|
|
FROM {db_prefix}attachments |
|
2438
|
|
|
WHERE attachment_type != {int:type} |
|
2439
|
|
|
GROUP BY id_folder', |
|
2440
|
|
|
array( |
|
2441
|
|
|
'type' => 1, |
|
2442
|
|
|
) |
|
2443
|
|
|
); |
|
2444
|
|
|
|
|
2445
|
|
|
$expected_files = array(); |
|
2446
|
|
|
$expected_size = array(); |
|
2447
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
2448
|
|
|
{ |
|
2449
|
|
|
$expected_files[$row['id_folder']] = $row['num_attach']; |
|
2450
|
|
|
$expected_size[$row['id_folder']] = $row['size_attach']; |
|
2451
|
|
|
} |
|
2452
|
|
|
$smcFunc['db_free_result']($request); |
|
2453
|
|
|
|
|
2454
|
|
|
$attachdirs = array(); |
|
2455
|
|
|
foreach ($modSettings['attachmentUploadDir'] as $id => $dir) |
|
2456
|
|
|
{ |
|
2457
|
|
|
// If there aren't any attachments in this directory this won't exist. |
|
2458
|
|
|
if (!isset($expected_files[$id])) |
|
2459
|
|
|
$expected_files[$id] = 0; |
|
2460
|
|
|
|
|
2461
|
|
|
// Check if the directory is doing okay. |
|
2462
|
|
|
list ($status, $error, $files) = attachDirStatus($dir, $expected_files[$id]); |
|
2463
|
|
|
|
|
2464
|
|
|
// If it is one, let's show that it's a base directory. |
|
2465
|
|
|
$sub_dirs = 0; |
|
2466
|
|
|
$is_base_dir = false; |
|
2467
|
|
|
if (!empty($modSettings['attachment_basedirectories'])) |
|
2468
|
|
|
{ |
|
2469
|
|
|
$is_base_dir = in_array($dir, $modSettings['attachment_basedirectories']); |
|
2470
|
|
|
|
|
2471
|
|
|
// Count any sub-folders. |
|
2472
|
|
|
foreach ($modSettings['attachmentUploadDir'] as $sid => $sub) |
|
2473
|
|
|
if (strpos($sub, $dir . DIRECTORY_SEPARATOR) !== false) |
|
2474
|
|
|
{ |
|
2475
|
|
|
$expected_files[$id]++; |
|
2476
|
|
|
$sub_dirs++; |
|
2477
|
|
|
} |
|
2478
|
|
|
} |
|
2479
|
|
|
|
|
2480
|
|
|
$attachdirs[] = array( |
|
2481
|
|
|
'id' => $id, |
|
2482
|
|
|
'current' => $id == $modSettings['currentAttachmentUploadDir'], |
|
2483
|
|
|
'disable_current' => isset($modSettings['automanage_attachments']) && $modSettings['automanage_attachments'] > 1, |
|
2484
|
|
|
'disable_base_dir' => $is_base_dir && $sub_dirs > 0 && !empty($files) && empty($error) && empty($save_errors), |
|
2485
|
|
|
'path' => $dir, |
|
2486
|
|
|
'current_size' => !empty($expected_size[$id]) ? comma_format($expected_size[$id] / 1024, 0) : 0, |
|
2487
|
|
|
'num_files' => comma_format($expected_files[$id] - $sub_dirs, 0) . ($sub_dirs > 0 ? ' (' . $sub_dirs . ')' : ''), |
|
2488
|
|
|
'status' => ($is_base_dir ? $txt['attach_dir_basedir'] . '<br>' : '') . ($error ? '<div class="error">' : '') . sprintf($txt['attach_dir_' . $status], $context['session_id'], $context['session_var']) . ($error ? '</div>' : ''), |
|
2489
|
|
|
); |
|
2490
|
|
|
} |
|
2491
|
|
|
|
|
2492
|
|
|
// Just stick a new directory on at the bottom. |
|
2493
|
|
|
if (isset($_REQUEST['new_path'])) |
|
2494
|
|
|
$attachdirs[] = array( |
|
2495
|
|
|
'id' => max(array_merge(array_keys($expected_files), array_keys($modSettings['attachmentUploadDir']))) + 1, |
|
2496
|
|
|
'current' => false, |
|
2497
|
|
|
'path' => '', |
|
2498
|
|
|
'current_size' => '', |
|
2499
|
|
|
'num_files' => '', |
|
2500
|
|
|
'status' => '', |
|
2501
|
|
|
); |
|
2502
|
|
|
|
|
2503
|
|
|
return $attachdirs; |
|
2504
|
|
|
} |
|
2505
|
|
|
|
|
2506
|
|
|
/** |
|
2507
|
|
|
* Prepare the base directories to be displayed in a list. |
|
2508
|
|
|
* @return void|array Returns nothing if there are no base directories, otherwise returns an array of info about the directories |
|
2509
|
|
|
*/ |
|
2510
|
|
|
function list_getBaseDirs() |
|
2511
|
|
|
{ |
|
2512
|
|
|
global $modSettings, $txt; |
|
2513
|
|
|
|
|
2514
|
|
|
if (empty($modSettings['attachment_basedirectories'])) |
|
2515
|
|
|
return; |
|
2516
|
|
|
|
|
2517
|
|
|
$basedirs = array(); |
|
2518
|
|
|
// Get a list of the base directories. |
|
2519
|
|
|
foreach ($modSettings['attachment_basedirectories'] as $id => $dir) |
|
2520
|
|
|
{ |
|
2521
|
|
|
// Loop through the attach directory array to count any sub-directories |
|
2522
|
|
|
$expected_dirs = 0; |
|
2523
|
|
View Code Duplication |
foreach ($modSettings['attachmentUploadDir'] as $sid => $sub) |
|
|
|
|
|
|
2524
|
|
|
if (strpos($sub, $dir . DIRECTORY_SEPARATOR) !== false) |
|
2525
|
|
|
$expected_dirs++; |
|
2526
|
|
|
|
|
2527
|
|
|
if (!is_dir($dir)) |
|
2528
|
|
|
$status = 'does_not_exist'; |
|
2529
|
|
|
elseif (!is_writeable($dir)) |
|
2530
|
|
|
$status = 'not_writable'; |
|
2531
|
|
|
else |
|
2532
|
|
|
$status = 'ok'; |
|
2533
|
|
|
|
|
2534
|
|
|
$basedirs[] = array( |
|
2535
|
|
|
'id' => $id, |
|
2536
|
|
|
'current' => $dir == $modSettings['basedirectory_for_attachments'], |
|
2537
|
|
|
'path' => $expected_dirs > 0 ? $dir : ('<input type="text" name="base_dir[' . $id . ']" value="' . $dir . '" size="40">'), |
|
2538
|
|
|
'num_dirs' => $expected_dirs, |
|
2539
|
|
|
'status' => $status == 'ok' ? $txt['attach_dir_ok'] : ('<span class="error">' . $txt['attach_dir_' . $status] . '</span>'), |
|
2540
|
|
|
); |
|
2541
|
|
|
} |
|
2542
|
|
|
|
|
2543
|
|
|
if (isset($_REQUEST['new_base_path'])) |
|
2544
|
|
|
$basedirs[] = array( |
|
2545
|
|
|
'id' => '', |
|
2546
|
|
|
'current' => false, |
|
2547
|
|
|
'path' => '<input type="text" name="new_base_dir" value="" size="40">', |
|
2548
|
|
|
'num_dirs' => '', |
|
2549
|
|
|
'status' => '', |
|
2550
|
|
|
); |
|
2551
|
|
|
|
|
2552
|
|
|
return $basedirs; |
|
2553
|
|
|
} |
|
2554
|
|
|
|
|
2555
|
|
|
/** |
|
2556
|
|
|
* Checks the status of an attachment directory and returns an array |
|
2557
|
|
|
* of the status key, if that status key signifies an error, and |
|
2558
|
|
|
* the file count. |
|
2559
|
|
|
* |
|
2560
|
|
|
* @param string $dir The directory to check |
|
2561
|
|
|
* @param int $expected_files How many files should be in that directory |
|
2562
|
|
|
* @return array An array containing the status of the directory, whether the number of files was what we expected and how many were in the directory |
|
2563
|
|
|
*/ |
|
2564
|
|
|
function attachDirStatus($dir, $expected_files) |
|
2565
|
|
|
{ |
|
2566
|
|
|
if (!is_dir($dir)) |
|
2567
|
|
|
return array('does_not_exist', true, ''); |
|
2568
|
|
|
elseif (!is_writable($dir)) |
|
2569
|
|
|
return array('not_writable', true, ''); |
|
2570
|
|
|
|
|
2571
|
|
|
// Everything is okay so far, start to scan through the directory. |
|
2572
|
|
|
$num_files = 0; |
|
2573
|
|
|
$dir_handle = dir($dir); |
|
2574
|
|
|
while ($file = $dir_handle->read()) |
|
2575
|
|
|
{ |
|
2576
|
|
|
// Now do we have a real file here? |
|
2577
|
|
|
if (in_array($file, array('.', '..', '.htaccess', 'index.php'))) |
|
2578
|
|
|
continue; |
|
2579
|
|
|
|
|
2580
|
|
|
$num_files++; |
|
2581
|
|
|
} |
|
2582
|
|
|
$dir_handle->close(); |
|
2583
|
|
|
|
|
2584
|
|
|
if ($num_files < $expected_files) |
|
2585
|
|
|
return array('files_missing', true, $num_files); |
|
2586
|
|
|
// Empty? |
|
2587
|
|
|
elseif ($expected_files == 0) |
|
2588
|
|
|
return array('unused', false, $num_files); |
|
2589
|
|
|
// All good! |
|
2590
|
|
|
else |
|
2591
|
|
|
return array('ok', false, $num_files); |
|
2592
|
|
|
} |
|
2593
|
|
|
|
|
2594
|
|
|
/** |
|
2595
|
|
|
* Maintance function to move attachments from one directory to another |
|
2596
|
|
|
*/ |
|
2597
|
|
|
function TransferAttachments() |
|
2598
|
|
|
{ |
|
2599
|
|
|
global $modSettings, $smcFunc, $sourcedir, $txt, $boarddir; |
|
2600
|
|
|
|
|
2601
|
|
|
checkSession(); |
|
2602
|
|
|
|
|
2603
|
|
|
$modSettings['attachmentUploadDir'] = smf_json_decode($modSettings['attachmentUploadDir'], true); |
|
2604
|
|
|
if (!empty($modSettings['attachment_basedirectories'])) |
|
2605
|
|
|
$modSettings['attachment_basedirectories'] = smf_json_decode($modSettings['attachment_basedirectories'], true); |
|
|
|
|
|
|
2606
|
|
|
else |
|
2607
|
|
|
$modSettings['basedirectory_for_attachments'] = array(); |
|
2608
|
|
|
|
|
2609
|
|
|
$_POST['from'] = (int) $_POST['from']; |
|
2610
|
|
|
$_POST['auto'] = !empty($_POST['auto']) ? (int) $_POST['auto'] : 0; |
|
2611
|
|
|
$_POST['to'] = (int) $_POST['to']; |
|
2612
|
|
|
$start = !empty($_POST['empty_it']) ? 0 : $modSettings['attachmentDirFileLimit']; |
|
2613
|
|
|
$_SESSION['checked'] = !empty($_POST['empty_it']) ? true : false; |
|
2614
|
|
|
$limit = 501; |
|
2615
|
|
|
$results = array(); |
|
2616
|
|
|
$dir_files = 0; |
|
2617
|
|
|
$current_progress = 0; |
|
2618
|
|
|
$total_moved = 0; |
|
2619
|
|
|
$total_not_moved = 0; |
|
2620
|
|
|
|
|
2621
|
|
|
if (empty($_POST['from']) || (empty($_POST['auto']) && empty($_POST['to']))) |
|
2622
|
|
|
$results[] = $txt['attachment_transfer_no_dir']; |
|
2623
|
|
|
|
|
2624
|
|
|
if ($_POST['from'] == $_POST['to']) |
|
2625
|
|
|
$results[] = $txt['attachment_transfer_same_dir']; |
|
2626
|
|
|
|
|
2627
|
|
|
if (empty($results)) |
|
2628
|
|
|
{ |
|
2629
|
|
|
// Get the total file count for the progess bar. |
|
2630
|
|
|
$request = $smcFunc['db_query']('', ' |
|
2631
|
|
|
SELECT COUNT(*) |
|
2632
|
|
|
FROM {db_prefix}attachments |
|
2633
|
|
|
WHERE id_folder = {int:folder_id} |
|
2634
|
|
|
AND attachment_type != {int:attachment_type}', |
|
2635
|
|
|
array( |
|
2636
|
|
|
'folder_id' => $_POST['from'], |
|
2637
|
|
|
'attachment_type' => 1, |
|
2638
|
|
|
) |
|
2639
|
|
|
); |
|
2640
|
|
|
list ($total_progress) = $smcFunc['db_fetch_row']($request); |
|
2641
|
|
|
$smcFunc['db_free_result']($request); |
|
2642
|
|
|
$total_progress -= $start; |
|
2643
|
|
|
|
|
2644
|
|
|
if ($total_progress < 1) |
|
2645
|
|
|
$results[] = $txt['attachment_transfer_no_find']; |
|
2646
|
|
|
} |
|
2647
|
|
|
|
|
2648
|
|
|
if (empty($results)) |
|
2649
|
|
|
{ |
|
2650
|
|
|
// Where are they going? |
|
2651
|
|
|
if (!empty($_POST['auto'])) |
|
2652
|
|
|
{ |
|
2653
|
|
|
require_once($sourcedir . '/Subs-Attachments.php'); |
|
2654
|
|
|
|
|
2655
|
|
|
$modSettings['automanage_attachments'] = 1; |
|
2656
|
|
|
$modSettings['use_subdirectories_for_attachments'] = $_POST['auto'] == -1 ? 0 : 1; |
|
2657
|
|
|
$modSettings['basedirectory_for_attachments'] = $_POST['auto'] > 0 ? $modSettings['attachmentUploadDir'][$_POST['auto']] : $modSettings['basedirectory_for_attachments']; |
|
2658
|
|
|
|
|
2659
|
|
|
automanage_attachments_check_directory(); |
|
2660
|
|
|
$new_dir = $modSettings['currentAttachmentUploadDir']; |
|
2661
|
|
|
} |
|
2662
|
|
|
else |
|
2663
|
|
|
$new_dir = $_POST['to']; |
|
2664
|
|
|
|
|
2665
|
|
|
$modSettings['currentAttachmentUploadDir'] = $new_dir; |
|
2666
|
|
|
|
|
2667
|
|
|
$break = false; |
|
2668
|
|
|
while ($break == false) |
|
|
|
|
|
|
2669
|
|
|
{ |
|
2670
|
|
|
@set_time_limit(300); |
|
|
|
|
|
|
2671
|
|
|
if (function_exists('apache_reset_timeout')) |
|
2672
|
|
|
@apache_reset_timeout(); |
|
|
|
|
|
|
2673
|
|
|
|
|
2674
|
|
|
// If limits are set, get the file count and size for the destination folder |
|
2675
|
|
|
if ($dir_files <= 0 && (!empty($modSettings['attachmentDirSizeLimit']) || !empty($modSettings['attachmentDirFileLimit']))) |
|
2676
|
|
|
{ |
|
2677
|
|
|
$request = $smcFunc['db_query']('', ' |
|
2678
|
|
|
SELECT COUNT(*), SUM(size) |
|
2679
|
|
|
FROM {db_prefix}attachments |
|
2680
|
|
|
WHERE id_folder = {int:folder_id} |
|
2681
|
|
|
AND attachment_type != {int:attachment_type}', |
|
2682
|
|
|
array( |
|
2683
|
|
|
'folder_id' => $new_dir, |
|
2684
|
|
|
'attachment_type' => 1, |
|
2685
|
|
|
) |
|
2686
|
|
|
); |
|
2687
|
|
|
list ($dir_files, $dir_size) = $smcFunc['db_fetch_row']($request); |
|
2688
|
|
|
$smcFunc['db_free_result']($request); |
|
2689
|
|
|
} |
|
2690
|
|
|
|
|
2691
|
|
|
// Find some attachments to move |
|
2692
|
|
|
$request = $smcFunc['db_query']('', ' |
|
2693
|
|
|
SELECT id_attach, filename, id_folder, file_hash, size |
|
2694
|
|
|
FROM {db_prefix}attachments |
|
2695
|
|
|
WHERE id_folder = {int:folder} |
|
2696
|
|
|
AND attachment_type != {int:attachment_type} |
|
2697
|
|
|
LIMIT {int:start}, {int:limit}', |
|
2698
|
|
|
array( |
|
2699
|
|
|
'folder' => $_POST['from'], |
|
2700
|
|
|
'attachment_type' => 1, |
|
2701
|
|
|
'start' => $start, |
|
2702
|
|
|
'limit' => $limit, |
|
2703
|
|
|
) |
|
2704
|
|
|
); |
|
2705
|
|
|
|
|
2706
|
|
|
if ($smcFunc['db_num_rows']($request) === 0) |
|
2707
|
|
|
{ |
|
2708
|
|
|
if (empty($current_progress)) |
|
2709
|
|
|
$results[] = $txt['attachment_transfer_no_find']; |
|
2710
|
|
|
break; |
|
2711
|
|
|
} |
|
2712
|
|
|
|
|
2713
|
|
|
if ($smcFunc['db_num_rows']($request) < $limit) |
|
2714
|
|
|
$break = true; |
|
2715
|
|
|
|
|
2716
|
|
|
// Move them |
|
2717
|
|
|
$moved = array(); |
|
2718
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
2719
|
|
|
{ |
|
2720
|
|
|
$source = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']); |
|
2721
|
|
|
$dest = $modSettings['attachmentUploadDir'][$new_dir] . '/' . basename($source); |
|
2722
|
|
|
|
|
2723
|
|
|
// Size and file count check |
|
2724
|
|
|
if (!empty($modSettings['attachmentDirSizeLimit']) || !empty($modSettings['attachmentDirFileLimit'])) |
|
2725
|
|
|
{ |
|
2726
|
|
|
$dir_files++; |
|
2727
|
|
|
$dir_size += !empty($row['size']) ? $row['size'] : filesize($source); |
|
|
|
|
|
|
2728
|
|
|
|
|
2729
|
|
|
// If we've reached a limit. Do something. |
|
2730
|
|
|
if (!empty($modSettings['attachmentDirSizeLimit']) && $dir_size > $modSettings['attachmentDirSizeLimit'] * 1024 || (!empty($modSettings['attachmentDirFileLimit']) && $dir_files > $modSettings['attachmentDirFileLimit'])) |
|
2731
|
|
|
{ |
|
2732
|
|
|
if (!empty($_POST['auto'])) |
|
2733
|
|
|
{ |
|
2734
|
|
|
// Since we're in auto mode. Create a new folder and reset the counters. |
|
2735
|
|
|
automanage_attachments_by_space(); |
|
2736
|
|
|
|
|
2737
|
|
|
$results[] = sprintf($txt['attachments_transferred'], $total_moved, $modSettings['attachmentUploadDir'][$new_dir]); |
|
2738
|
|
|
if (!empty($total_not_moved)) |
|
2739
|
|
|
$results[] = sprintf($txt['attachments_not_transferred'], $total_not_moved); |
|
2740
|
|
|
|
|
2741
|
|
|
$dir_files = 0; |
|
2742
|
|
|
$total_moved = 0; |
|
2743
|
|
|
$total_not_moved = 0; |
|
2744
|
|
|
|
|
2745
|
|
|
$break = false; |
|
2746
|
|
|
break; |
|
2747
|
|
|
} |
|
2748
|
|
|
else |
|
2749
|
|
|
{ |
|
2750
|
|
|
// Hmm, not in auto. Time to bail out then... |
|
2751
|
|
|
$results[] = $txt['attachment_transfer_no_room']; |
|
2752
|
|
|
$break = true; |
|
2753
|
|
|
break; |
|
2754
|
|
|
} |
|
2755
|
|
|
} |
|
2756
|
|
|
} |
|
2757
|
|
|
|
|
2758
|
|
|
if (@rename($source, $dest)) |
|
2759
|
|
|
{ |
|
2760
|
|
|
$total_moved++; |
|
2761
|
|
|
$current_progress++; |
|
2762
|
|
|
$moved[] = $row['id_attach']; |
|
2763
|
|
|
} |
|
2764
|
|
|
else |
|
2765
|
|
|
$total_not_moved++; |
|
2766
|
|
|
} |
|
2767
|
|
|
$smcFunc['db_free_result']($request); |
|
2768
|
|
|
|
|
2769
|
|
|
if (!empty($moved)) |
|
2770
|
|
|
{ |
|
2771
|
|
|
// Update the database |
|
2772
|
|
|
$smcFunc['db_query']('', ' |
|
2773
|
|
|
UPDATE {db_prefix}attachments |
|
2774
|
|
|
SET id_folder = {int:new} |
|
2775
|
|
|
WHERE id_attach IN ({array_int:attachments})', |
|
2776
|
|
|
array( |
|
2777
|
|
|
'attachments' => $moved, |
|
2778
|
|
|
'new' => $new_dir, |
|
2779
|
|
|
) |
|
2780
|
|
|
); |
|
2781
|
|
|
} |
|
2782
|
|
|
|
|
2783
|
|
|
$moved = array(); |
|
|
|
|
|
|
2784
|
|
|
$new_dir = $modSettings['currentAttachmentUploadDir']; |
|
2785
|
|
|
|
|
2786
|
|
|
// Create the progress bar. |
|
2787
|
|
|
if (!$break) |
|
2788
|
|
|
{ |
|
2789
|
|
|
$percent_done = min(round($current_progress / $total_progress * 100, 0), 100); |
|
|
|
|
|
|
2790
|
|
|
$prog_bar = ' |
|
2791
|
|
|
<div class="progress_bar"> |
|
2792
|
|
|
<div class="full_bar">' . $percent_done . '%</div> |
|
2793
|
|
|
<div class="green_percent" style="width: ' . $percent_done . '%;"> </div> |
|
2794
|
|
|
</div>'; |
|
2795
|
|
|
// Write it to a file so it can be displayed |
|
2796
|
|
|
$fp = fopen($boarddir . '/progress.php', "w"); |
|
2797
|
|
|
fwrite($fp, $prog_bar); |
|
2798
|
|
|
fclose($fp); |
|
2799
|
|
|
usleep(500000); |
|
2800
|
|
|
} |
|
2801
|
|
|
} |
|
2802
|
|
|
|
|
2803
|
|
|
$results[] = sprintf($txt['attachments_transferred'], $total_moved, $modSettings['attachmentUploadDir'][$new_dir]); |
|
2804
|
|
|
if (!empty($total_not_moved)) |
|
2805
|
|
|
$results[] = sprintf($txt['attachments_not_transferred'], $total_not_moved); |
|
2806
|
|
|
} |
|
2807
|
|
|
|
|
2808
|
|
|
$_SESSION['results'] = $results; |
|
2809
|
|
|
if (file_exists($boarddir . '/progress.php')) |
|
2810
|
|
|
unlink($boarddir . '/progress.php'); |
|
2811
|
|
|
|
|
2812
|
|
|
redirectexit('action=admin;area=manageattachments;sa=maintenance#transfer'); |
|
2813
|
|
|
} |
|
2814
|
|
|
|
|
2815
|
|
|
?> |
|
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.