Chris@76: 'ManageAttachmentSettings', Chris@76: 'attachpaths' => 'ManageAttachmentPaths', Chris@76: 'avatars' => 'ManageAvatarSettings', Chris@76: 'browse' => 'BrowseFiles', Chris@76: 'byAge' => 'RemoveAttachmentByAge', Chris@76: 'bySize' => 'RemoveAttachmentBySize', Chris@76: 'maintenance' => 'MaintainFiles', Chris@76: 'moveAvatars' => 'MoveAvatars', Chris@76: 'repair' => 'RepairAttachments', Chris@76: 'remove' => 'RemoveAttachment', Chris@76: 'removeall' => 'RemoveAllAttachments' Chris@76: ); Chris@76: Chris@76: // Pick the correct sub-action. Chris@76: if (isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']])) Chris@76: $context['sub_action'] = $_REQUEST['sa']; Chris@76: else Chris@76: $context['sub_action'] = 'browse'; Chris@76: Chris@76: // Default page title is good. Chris@76: $context['page_title'] = $txt['attachments_avatars']; Chris@76: Chris@76: // This uses admin tabs - as it should! Chris@76: $context[$context['admin_menu_name']]['tab_data'] = array( Chris@76: 'title' => $txt['attachments_avatars'], Chris@76: 'help' => 'manage_files', Chris@76: 'description' => $txt['attachments_desc'], Chris@76: ); Chris@76: Chris@76: // Finally fall through to what we are doing. Chris@76: $subActions[$context['sub_action']](); Chris@76: } Chris@76: Chris@76: function ManageAttachmentSettings($return_config = false) Chris@76: { Chris@76: global $txt, $modSettings, $scripturl, $context, $options, $sourcedir; Chris@76: Chris@76: $context['valid_upload_dir'] = is_dir($modSettings['attachmentUploadDir']) && is_writable($modSettings['attachmentUploadDir']); Chris@76: Chris@76: // Perform a test to see if the GD module is installed. Chris@76: $testGD = get_extension_funcs('gd'); Chris@76: Chris@76: $config_vars = array( Chris@76: array('title', 'attachment_manager_settings'), Chris@76: // Are attachments enabled? Chris@76: array('select', 'attachmentEnable', array($txt['attachmentEnable_deactivate'], $txt['attachmentEnable_enable_all'], $txt['attachmentEnable_disable_new'])), Chris@76: '', Chris@76: // Extension checks etc. Chris@76: array('check', 'attachmentCheckExtensions'), Chris@76: array('text', 'attachmentExtensions', 40), Chris@76: array('check', 'attachmentRecodeLineEndings'), Chris@76: '', Chris@76: // Directory and size limits. Chris@76: empty($modSettings['currentAttachmentUploadDir']) ? array('text', 'attachmentUploadDir', 40, 'invalid' => !$context['valid_upload_dir']) : array('var_message', 'attachmentUploadDir_multiple', 'message' => 'attachmentUploadDir_multiple_configure'), Chris@76: array('text', 'attachmentDirSizeLimit', 6, 'postinput' => $txt['kilobyte']), Chris@76: array('text', 'attachmentPostLimit', 6, 'postinput' => $txt['kilobyte']), Chris@76: array('text', 'attachmentSizeLimit', 6, 'postinput' => $txt['kilobyte']), Chris@76: array('text', 'attachmentNumPerPostLimit', 6), Chris@76: '', Chris@76: // Image settings. Chris@76: array('warning', empty($testGD) ? 'attachment_gd_warning' : ''), Chris@76: array('check', 'attachment_image_reencode'), Chris@76: '', Chris@76: array('warning', 'attachment_image_paranoid_warning'), Chris@76: array('check', 'attachment_image_paranoid'), Chris@76: '', Chris@76: // Thumbnail settings. Chris@76: array('check', 'attachmentShowImages'), Chris@76: array('check', 'attachmentThumbnails'), Chris@76: array('check', 'attachment_thumb_png'), Chris@76: array('text', 'attachmentThumbWidth', 6), Chris@76: array('text', 'attachmentThumbHeight', 6), Chris@76: ); Chris@76: Chris@76: if ($return_config) Chris@76: return $config_vars; Chris@76: Chris@76: // These are very likely to come in handy! (i.e. without them we're doomed!) Chris@76: require_once($sourcedir . '/ManagePermissions.php'); Chris@76: require_once($sourcedir . '/ManageServer.php'); Chris@76: Chris@76: // Saving settings? Chris@76: if (isset($_GET['save'])) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: saveDBSettings($config_vars); Chris@76: redirectexit('action=admin;area=manageattachments;sa=attachments'); Chris@76: } Chris@76: Chris@76: $context['post_url'] = $scripturl . '?action=admin;area=manageattachments;save;sa=attachments'; Chris@76: prepareDBSettingContext($config_vars); Chris@76: Chris@76: $context['sub_template'] = 'show_settings'; Chris@76: } Chris@76: Chris@76: function ManageAvatarSettings($return_config = false) Chris@76: { Chris@76: global $txt, $context, $modSettings, $sourcedir, $scripturl; Chris@76: Chris@76: // Perform a test to see if the GD module is installed. Chris@76: $testGD = get_extension_funcs('gd'); Chris@76: Chris@76: $context['valid_avatar_dir'] = is_dir($modSettings['avatar_directory']); Chris@76: $context['valid_custom_avatar_dir'] = empty($modSettings['custom_avatar_enabled']) || (!empty($modSettings['custom_avatar_dir']) && is_dir($modSettings['custom_avatar_dir']) && is_writable($modSettings['custom_avatar_dir'])); Chris@76: Chris@76: $config_vars = array( Chris@76: // Server stored avatars! Chris@76: array('title', 'avatar_server_stored'), Chris@76: array('warning', empty($testGD) ? 'avatar_gd_warning' : ''), Chris@76: array('permissions', 'profile_server_avatar', 0, $txt['avatar_server_stored_groups']), Chris@76: array('text', 'avatar_directory', 40, 'invalid' => !$context['valid_avatar_dir']), Chris@76: array('text', 'avatar_url', 40), Chris@76: // External avatars? Chris@76: array('title', 'avatar_external'), Chris@76: array('permissions', 'profile_remote_avatar', 0, $txt['avatar_external_url_groups']), Chris@76: array('check', 'avatar_download_external', 0, 'onchange' => 'fUpdateStatus();'), Chris@76: array('text', 'avatar_max_width_external', 6), Chris@76: array('text', 'avatar_max_height_external', 6), Chris@76: array('select', 'avatar_action_too_large', Chris@76: array( Chris@76: 'option_refuse' => $txt['option_refuse'], Chris@76: 'option_html_resize' => $txt['option_html_resize'], Chris@76: 'option_js_resize' => $txt['option_js_resize'], Chris@76: 'option_download_and_resize' => $txt['option_download_and_resize'], Chris@76: ), Chris@76: ), Chris@76: // Uploadable avatars? Chris@76: array('title', 'avatar_upload'), Chris@76: array('permissions', 'profile_upload_avatar', 0, $txt['avatar_upload_groups']), Chris@76: array('text', 'avatar_max_width_upload', 6), Chris@76: array('text', 'avatar_max_height_upload', 6), Chris@76: array('check', 'avatar_resize_upload', 'subtext' => $txt['avatar_resize_upload_note']), Chris@76: array('check', 'avatar_reencode'), Chris@76: '', Chris@76: array('warning', 'avatar_paranoid_warning'), Chris@76: array('check', 'avatar_paranoid'), Chris@76: '', Chris@76: array('check', 'avatar_download_png'), Chris@76: array('select', 'custom_avatar_enabled', array($txt['option_attachment_dir'], $txt['option_specified_dir']), 'onchange' => 'fUpdateStatus();'), Chris@76: array('text', 'custom_avatar_dir', 40, 'subtext' => $txt['custom_avatar_dir_desc'], 'invalid' => !$context['valid_custom_avatar_dir']), Chris@76: array('text', 'custom_avatar_url', 40), Chris@76: ); Chris@76: Chris@76: if ($return_config) Chris@76: return $config_vars; Chris@76: Chris@76: // We need these files for the inline permission settings, and the settings template. Chris@76: require_once($sourcedir . '/ManagePermissions.php'); Chris@76: require_once($sourcedir . '/ManageServer.php'); Chris@76: Chris@76: // Saving avatar settings? Chris@76: if (isset($_GET['save'])) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: // Just incase the admin forgot to set both custom avatar values, we disable it to prevent errors. Chris@76: if (isset($_POST['custom_avatar_enabled']) && $_POST['custom_avatar_enabled'] == 1 && (empty($_POST['custom_avatar_dir']) || empty($_POST['custom_avatar_url']))) Chris@76: $_POST['custom_avatar_enabled'] = 0; Chris@76: Chris@76: saveDBSettings($config_vars); Chris@76: redirectexit('action=admin;area=manageattachments;sa=avatars'); Chris@76: } Chris@76: Chris@76: // Attempt to figure out if the admin is trying to break things. Chris@76: $context['settings_save_onclick'] = 'return document.getElementById(\'custom_avatar_enabled\').value == 1 && (document.getElementById(\'custom_avatar_dir\').value == \'\' || document.getElementById(\'custom_avatar_url\').value == \'\') ? confirm(\'' . $txt['custom_avatar_check_empty'] . '\') : true;'; Chris@76: Chris@76: // Prepare the context. Chris@76: $context['post_url'] = $scripturl . '?action=admin;area=manageattachments;save;sa=avatars'; Chris@76: prepareDBSettingContext($config_vars); Chris@76: Chris@76: // Add a layer for the javascript. Chris@76: $context['template_layers'][] = 'avatar_settings'; Chris@76: $context['sub_template'] = 'show_settings'; Chris@76: } Chris@76: Chris@76: function BrowseFiles() Chris@76: { Chris@76: global $context, $txt, $scripturl, $options, $modSettings; Chris@76: global $smcFunc, $sourcedir; Chris@76: Chris@76: $context['sub_template'] = 'browse'; Chris@76: Chris@76: // Attachments or avatars? Chris@76: $context['browse_type'] = isset($_REQUEST['avatars']) ? 'avatars' : (isset($_REQUEST['thumbs']) ? 'thumbs' : 'attachments'); Chris@76: Chris@76: // Set the options for the list component. Chris@76: $listOptions = array( Chris@76: 'id' => 'file_list', Chris@76: 'title' => $txt['attachment_manager_' . ($context['browse_type'] === 'avatars' ? 'avatars' : ( $context['browse_type'] === 'thumbs' ? 'thumbs' : 'attachments'))], Chris@76: 'items_per_page' => $modSettings['defaultMaxMessages'], Chris@76: 'base_href' => $scripturl . '?action=admin;area=manageattachments;sa=browse' . ($context['browse_type'] === 'avatars' ? ';avatars' : ($context['browse_type'] === 'thumbs' ? ';thumbs' : '')), Chris@76: 'default_sort_col' => 'name', Chris@76: 'no_items_label' => $txt['attachment_manager_' . ($context['browse_type'] === 'avatars' ? 'avatars' : ( $context['browse_type'] === 'thumbs' ? 'thumbs' : 'attachments')) . '_no_entries'], Chris@76: 'get_items' => array( Chris@76: 'function' => 'list_getFiles', Chris@76: 'params' => array( Chris@76: $context['browse_type'], Chris@76: ), Chris@76: ), Chris@76: 'get_count' => array( Chris@76: 'function' => 'list_getNumFiles', Chris@76: 'params' => array( Chris@76: $context['browse_type'], Chris@76: ), Chris@76: ), Chris@76: 'columns' => array( Chris@76: 'name' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['attachment_name'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: global $modSettings, $context, $scripturl; Chris@76: Chris@76: $link = \'%1$s\', preg_replace(\'~&#(\\\\d{1,7}|x[0-9a-fA-F]{1,6});~\', \'&#\\\\1;\', htmlspecialchars($rowData[\'filename\']))); Chris@76: Chris@76: // Show the dimensions. Chris@76: if (!empty($rowData[\'width\']) && !empty($rowData[\'height\'])) Chris@76: $link .= sprintf(\' %1$dx%2$d\', $rowData[\'width\'], $rowData[\'height\']); Chris@76: Chris@76: return $link; Chris@76: '), Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'a.filename', Chris@76: 'reverse' => 'a.filename DESC', Chris@76: ), Chris@76: ), Chris@76: 'filesize' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['attachment_file_size'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData',' Chris@76: global $txt; Chris@76: Chris@76: return sprintf(\'%1$s%2$s\', round($rowData[\'size\'] / 1024, 2), $txt[\'kilobyte\']); Chris@76: '), Chris@76: 'class' => 'windowbg', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'a.size', Chris@76: 'reverse' => 'a.size DESC', Chris@76: ), Chris@76: ), Chris@76: 'member' => array( Chris@76: 'header' => array( Chris@76: 'value' => $context['browse_type'] == 'avatars' ? $txt['attachment_manager_member'] : $txt['posted_by'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: global $scripturl; Chris@76: Chris@76: // In case of an attachment, return the poster of the attachment. Chris@76: if (empty($rowData[\'id_member\'])) Chris@76: return htmlspecialchars($rowData[\'poster_name\']); Chris@76: Chris@76: // Otherwise it must be an avatar, return the link to the owner of it. Chris@76: else Chris@76: return sprintf(\'%3$s\', $scripturl, $rowData[\'id_member\'], $rowData[\'poster_name\']); Chris@76: '), Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'mem.real_name', Chris@76: 'reverse' => 'mem.real_name DESC', Chris@76: ), Chris@76: ), Chris@76: 'date' => array( Chris@76: 'header' => array( Chris@76: 'value' => $context['browse_type'] == 'avatars' ? $txt['attachment_manager_last_active'] : $txt['date'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: global $txt, $context, $scripturl; Chris@76: Chris@76: // The date the message containing the attachment was posted or the owner of the avatar was active. Chris@76: $date = empty($rowData[\'poster_time\']) ? $txt[\'never\'] : timeformat($rowData[\'poster_time\']); Chris@76: Chris@76: // Add a link to the topic in case of an attachment. Chris@76: if ($context[\'browse_type\'] !== \'avatars\') Chris@76: $date .= sprintf(\'
%1$s %5$s\', $txt[\'in\'], $scripturl, $rowData[\'id_topic\'], $rowData[\'id_msg\'], $rowData[\'subject\']); Chris@76: Chris@76: return $date; Chris@76: '), Chris@76: 'class' => 'windowbg', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => $context['browse_type'] === 'avatars' ? 'mem.last_login' : 'm.id_msg', Chris@76: 'reverse' => $context['browse_type'] === 'avatars' ? 'mem.last_login DESC' : 'm.id_msg DESC', Chris@76: ), Chris@76: ), Chris@76: 'downloads' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['downloads'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData',' Chris@76: global $txt; Chris@76: Chris@76: return comma_format($rowData[\'downloads\']); Chris@76: '), Chris@76: 'class' => 'windowbg', Chris@76: ), Chris@76: 'sort' => array( Chris@76: 'default' => 'a.downloads', Chris@76: 'reverse' => 'a.downloads DESC', Chris@76: ), Chris@76: ), Chris@76: 'check' => array( Chris@76: 'header' => array( Chris@76: 'value' => '', Chris@76: ), Chris@76: 'data' => array( Chris@76: 'sprintf' => array( Chris@76: 'format' => '', Chris@76: 'params' => array( Chris@76: 'id_attach' => false, Chris@76: ), Chris@76: ), Chris@76: 'style' => 'text-align: center', Chris@76: ), Chris@76: ), Chris@76: ), Chris@76: 'form' => array( Chris@76: 'href' => $scripturl . '?action=admin;area=manageattachments;sa=remove' . ($context['browse_type'] === 'avatars' ? ';avatars' : ($context['browse_type'] === 'thumbs' ? ';thumbs' : '')), Chris@76: 'include_sort' => true, Chris@76: 'include_start' => true, Chris@76: 'hidden_fields' => array( Chris@76: 'type' => $context['browse_type'], Chris@76: ), Chris@76: ), Chris@76: 'additional_rows' => array( Chris@76: array( Chris@76: 'position' => 'below_table_data', Chris@76: 'value' => '', Chris@76: 'style' => 'text-align: right;', Chris@76: ), Chris@76: ), Chris@76: ); Chris@76: Chris@76: // Create the list. Chris@76: require_once($sourcedir . '/Subs-List.php'); Chris@76: createList($listOptions); Chris@76: } Chris@76: Chris@76: function list_getFiles($start, $items_per_page, $sort, $browse_type) Chris@76: { Chris@76: global $smcFunc, $txt; Chris@76: Chris@76: // Choose a query depending on what we are viewing. Chris@76: if ($browse_type === 'avatars') Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT Chris@76: {string:blank_text} AS id_msg, IFNULL(mem.real_name, {string:not_applicable_text}) AS poster_name, Chris@76: mem.last_login AS poster_time, 0 AS id_topic, a.id_member, a.id_attach, a.filename, a.file_hash, a.attachment_type, Chris@76: a.size, a.width, a.height, a.downloads, {string:blank_text} AS subject, 0 AS id_board Chris@76: FROM {db_prefix}attachments AS a Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = a.id_member) Chris@76: WHERE a.id_member != {int:guest_id} Chris@76: ORDER BY {raw:sort} Chris@76: LIMIT {int:start}, {int:per_page}', Chris@76: array( Chris@76: 'guest_id' => 0, Chris@76: 'blank_text' => '', Chris@76: 'not_applicable_text' => $txt['not_applicable'], Chris@76: 'sort' => $sort, Chris@76: 'start' => $start, Chris@76: 'per_page' => $items_per_page, Chris@76: ) Chris@76: ); Chris@76: else Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT Chris@76: m.id_msg, IFNULL(mem.real_name, m.poster_name) AS poster_name, m.poster_time, m.id_topic, m.id_member, Chris@76: a.id_attach, a.filename, a.file_hash, a.attachment_type, a.size, a.width, a.height, a.downloads, mf.subject, t.id_board Chris@76: FROM {db_prefix}attachments AS a Chris@76: INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg) Chris@76: INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) Chris@76: INNER JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg) Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member) Chris@76: WHERE a.attachment_type = {int:attachment_type} Chris@76: ORDER BY {raw:sort} Chris@76: LIMIT {int:start}, {int:per_page}', Chris@76: array( Chris@76: 'attachment_type' => $browse_type == 'thumbs' ? '3' : '0', Chris@76: 'sort' => $sort, Chris@76: 'start' => $start, Chris@76: 'per_page' => $items_per_page, Chris@76: ) Chris@76: ); Chris@76: $files = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $files[] = $row; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $files; Chris@76: } Chris@76: Chris@76: function list_getNumFiles($browse_type) Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: // Depending on the type of file, different queries are used. Chris@76: if ($browse_type === 'avatars') Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT COUNT(*) Chris@76: FROM {db_prefix}attachments Chris@76: WHERE id_member != {int:guest_id_member}', Chris@76: array( Chris@76: 'guest_id_member' => 0, Chris@76: ) Chris@76: ); Chris@76: else Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT COUNT(*) AS num_attach Chris@76: FROM {db_prefix}attachments AS a Chris@76: INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg) Chris@76: INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) Chris@76: INNER JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg) Chris@76: WHERE a.attachment_type = {int:attachment_type} Chris@76: AND a.id_member = {int:guest_id_member}', Chris@76: array( Chris@76: 'attachment_type' => $browse_type === 'thumbs' ? '3' : '0', Chris@76: 'guest_id_member' => 0, Chris@76: ) Chris@76: ); Chris@76: Chris@76: list ($num_files) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: return $num_files; Chris@76: } Chris@76: Chris@76: function MaintainFiles() Chris@76: { Chris@76: global $context, $modSettings, $txt, $smcFunc; Chris@76: Chris@76: $context['sub_template'] = 'maintenance'; Chris@76: Chris@76: if (!empty($modSettings['currentAttachmentUploadDir'])) Chris@76: $attach_dirs = unserialize($modSettings['attachmentUploadDir']); Chris@76: else Chris@76: $attach_dirs = array($modSettings['attachmentUploadDir']); Chris@76: Chris@76: // Get the number of attachments.... Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT COUNT(*) Chris@76: FROM {db_prefix}attachments Chris@76: WHERE attachment_type = {int:attachment_type} Chris@76: AND id_member = {int:guest_id_member}', Chris@76: array( Chris@76: 'attachment_type' => 0, Chris@76: 'guest_id_member' => 0, Chris@76: ) Chris@76: ); Chris@76: list ($context['num_attachments']) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Also get the avatar amount.... Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT COUNT(*) Chris@76: FROM {db_prefix}attachments Chris@76: WHERE id_member != {int:guest_id_member}', Chris@76: array( Chris@76: 'guest_id_member' => 0, Chris@76: ) Chris@76: ); Chris@76: list ($context['num_avatars']) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Find out how big the directory is. We have to loop through all our attachment paths in case there's an old temp file in one of them. Chris@76: $attachmentDirSize = 0; Chris@76: foreach ($attach_dirs as $id => $attach_dir) Chris@76: { Chris@76: $dir = @opendir($attach_dir) or fatal_lang_error('cant_access_upload_path', 'critical'); Chris@76: while ($file = readdir($dir)) Chris@76: { Chris@76: if ($file == '.' || $file == '..') Chris@76: continue; Chris@76: Chris@76: if (preg_match('~^post_tmp_\d+_\d+$~', $file) != 0) Chris@76: { Chris@76: // Temp file is more than 5 hours old! Chris@76: if (filemtime($attach_dir . '/' . $file) < time() - 18000) Chris@76: @unlink($attach_dir . '/' . $file); Chris@76: continue; Chris@76: } Chris@76: Chris@76: // We're only counting the size of the current attachment directory. Chris@76: if (empty($modSettings['currentAttachmentUploadDir']) || $modSettings['currentAttachmentUploadDir'] == $id) Chris@76: $attachmentDirSize += filesize($attach_dir . '/' . $file); Chris@76: } Chris@76: closedir($dir); Chris@76: } Chris@76: // Divide it into kilobytes. Chris@76: $attachmentDirSize /= 1024; Chris@76: Chris@76: // If they specified a limit only.... Chris@76: if (!empty($modSettings['attachmentDirSizeLimit'])) Chris@76: $context['attachment_space'] = max(round($modSettings['attachmentDirSizeLimit'] - $attachmentDirSize, 2), 0); Chris@76: $context['attachment_total_size'] = round($attachmentDirSize, 2); Chris@76: Chris@76: $context['attach_multiple_dirs'] = !empty($modSettings['currentAttachmentUploadDir']); Chris@76: } Chris@76: Chris@76: // !!! Not implemented yet. Chris@76: function MoveAvatars() Chris@76: { Chris@76: global $modSettings, $smcFunc; Chris@76: Chris@76: // First make sure the custom avatar dir is writable. Chris@76: if (!is_writable($modSettings['custom_avatar_dir'])) Chris@76: { Chris@76: // Try to fix it. Chris@76: @chmod($modSettings['custom_avatar_dir'], 0777); Chris@76: Chris@76: // Guess that didn't work? Chris@76: if (!is_writable($modSettings['custom_avatar_dir'])) Chris@76: fatal_lang_error('attachments_no_write', 'critical'); Chris@76: } Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_attach, id_folder, id_member, filename, file_hash Chris@76: FROM {db_prefix}attachments Chris@76: WHERE attachment_type = {int:attachment_type} Chris@76: AND id_member > {int:guest_id_member}', Chris@76: array( Chris@76: 'attachment_type' => 0, Chris@76: 'guest_id_member' => 0, Chris@76: ) Chris@76: ); Chris@76: $updatedAvatars = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: $filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']); Chris@76: Chris@76: if (rename($filename, $modSettings['custom_avatar_dir'] . '/' . $row['filename'])) Chris@76: $updatedAvatars[] = $row['id_attach']; Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: if (!empty($updatedAvatars)) Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}attachments Chris@76: SET attachment_type = {int:attachment_type} Chris@76: WHERE id_attach IN ({array_int:updated_avatars})', Chris@76: array( Chris@76: 'updated_avatars' => $updatedAvatars, Chris@76: 'attachment_type' => 1, Chris@76: ) Chris@76: ); Chris@76: Chris@76: redirectexit('action=admin;area=manageattachments;sa=maintenance'); Chris@76: } Chris@76: Chris@76: function RemoveAttachmentByAge() Chris@76: { Chris@76: global $modSettings, $smcFunc; Chris@76: Chris@76: checkSession('post', 'admin'); Chris@76: Chris@76: // !!! Ignore messages in topics that are stickied? Chris@76: Chris@76: // Deleting an attachment? Chris@76: if ($_REQUEST['type'] != 'avatars') Chris@76: { Chris@76: // Get all the old attachments. Chris@76: $messages = removeAttachments(array('attachment_type' => 0, 'poster_time' => (time() - 24 * 60 * 60 * $_POST['age'])), 'messages', true); Chris@76: Chris@76: // Update the messages to reflect the change. Chris@76: if (!empty($messages)) Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}messages Chris@76: SET body = CONCAT(body, ' . (!empty($_POST['notice']) ? '{string:notice}' : '') . ') Chris@76: WHERE id_msg IN ({array_int:messages})', Chris@76: array( Chris@76: 'messages' => $messages, Chris@76: 'notice' => empty($_POST['notice']) ? '' : '

' . $_POST['notice'], Chris@76: ) Chris@76: ); Chris@76: } Chris@76: else Chris@76: { Chris@76: // Remove all the old avatars. Chris@76: removeAttachments(array('not_id_member' => 0, 'last_login' => (time() - 24 * 60 * 60 * $_POST['age'])), 'members'); Chris@76: } Chris@76: redirectexit('action=admin;area=manageattachments' . (empty($_REQUEST['avatars']) ? ';sa=maintenance' : ';avatars')); Chris@76: } Chris@76: Chris@76: function RemoveAttachmentBySize() Chris@76: { Chris@76: global $modSettings, $smcFunc; Chris@76: Chris@76: checkSession('post', 'admin'); Chris@76: Chris@76: // Find humungous attachments. Chris@76: $messages = removeAttachments(array('attachment_type' => 0, 'size' => 1024 * $_POST['size']), 'messages', true); Chris@76: Chris@76: // And make a note on the post. Chris@76: if (!empty($messages)) Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}messages Chris@76: SET body = CONCAT(body, ' . (!empty($_POST['notice']) ? '{string:notice}' : '') . ') Chris@76: WHERE id_msg IN ({array_int:messages})', Chris@76: array( Chris@76: 'messages' => $messages, Chris@76: 'notice' => empty($_POST['notice']) ? '' : '

' . $_POST['notice'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: redirectexit('action=admin;area=manageattachments;sa=maintenance'); Chris@76: } Chris@76: Chris@76: function RemoveAttachment() Chris@76: { Chris@76: global $modSettings, $txt, $smcFunc; Chris@76: Chris@76: checkSession('post'); Chris@76: Chris@76: if (!empty($_POST['remove'])) Chris@76: { Chris@76: $attachments = array(); Chris@76: // There must be a quicker way to pass this safety test?? Chris@76: foreach ($_POST['remove'] as $removeID => $dummy) Chris@76: $attachments[] = (int) $removeID; Chris@76: Chris@76: if ($_REQUEST['type'] == 'avatars' && !empty($attachments)) Chris@76: removeAttachments(array('id_attach' => $attachments)); Chris@76: else if (!empty($attachments)) Chris@76: { Chris@76: $messages = removeAttachments(array('id_attach' => $attachments), 'messages', true); Chris@76: Chris@76: // And change the message to reflect this. Chris@76: if (!empty($messages)) Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}messages Chris@76: SET body = CONCAT(body, {string:deleted_message}) Chris@76: WHERE id_msg IN ({array_int:messages_affected})', Chris@76: array( Chris@76: 'messages_affected' => $messages, Chris@76: 'deleted_message' => '

' . $txt['attachment_delete_admin'], Chris@76: ) Chris@76: ); Chris@76: } Chris@76: } Chris@76: Chris@76: $_GET['sort'] = isset($_GET['sort']) ? $_GET['sort'] : 'date'; Chris@76: redirectexit('action=admin;area=manageattachments;sa=browse;' . $_REQUEST['type'] . ';sort=' . $_GET['sort'] . (isset($_GET['desc']) ? ';desc' : '') . ';start=' . $_REQUEST['start']); Chris@76: } Chris@76: Chris@76: // !!! Not implemented (yet?) Chris@76: function RemoveAllAttachments() Chris@76: { Chris@76: global $txt, $smcFunc; Chris@76: Chris@76: checkSession('get', 'admin'); Chris@76: Chris@76: $messages = removeAttachments(array('attachment_type' => 0), '', true); Chris@76: Chris@76: if (!isset($_POST['notice'])) Chris@76: $_POST['notice'] = $txt['attachment_delete_admin']; Chris@76: Chris@76: // Add the notice on the end of the changed messages. Chris@76: if (!empty($messages)) Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}messages Chris@76: SET body = CONCAT(body, {string:deleted_message}) Chris@76: WHERE id_msg IN ({array_int:messages})', Chris@76: array( Chris@76: 'messages' => $messages, Chris@76: 'deleted_message' => '

' . $_POST['notice'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: redirectexit('action=admin;area=manageattachments;sa=maintenance'); Chris@76: } Chris@76: Chris@76: // Removes attachments - allowed query_types: '', 'messages', 'members' Chris@76: function removeAttachments($condition, $query_type = '', $return_affected_messages = false, $autoThumbRemoval = true) Chris@76: { Chris@76: global $modSettings, $smcFunc; Chris@76: Chris@76: //!!! This might need more work! Chris@76: $new_condition = array(); Chris@76: $query_parameter = array( Chris@76: 'thumb_attachment_type' => 3, Chris@76: ); Chris@76: Chris@76: if (is_array($condition)) Chris@76: { Chris@76: foreach ($condition as $real_type => $restriction) Chris@76: { Chris@76: // Doing a NOT? Chris@76: $is_not = substr($real_type, 0, 4) == 'not_'; Chris@76: $type = $is_not ? substr($real_type, 4) : $real_type; Chris@76: Chris@76: if (in_array($type, array('id_member', 'id_attach', 'id_msg'))) Chris@76: $new_condition[] = 'a.' . $type . ($is_not ? ' NOT' : '') . ' IN (' . (is_array($restriction) ? '{array_int:' . $real_type . '}' : '{int:' . $real_type . '}') . ')'; Chris@76: elseif ($type == 'attachment_type') Chris@76: $new_condition[] = 'a.attachment_type = {int:' . $real_type . '}'; Chris@76: elseif ($type == 'poster_time') Chris@76: $new_condition[] = 'm.poster_time < {int:' . $real_type . '}'; Chris@76: elseif ($type == 'last_login') Chris@76: $new_condition[] = 'mem.last_login < {int:' . $real_type . '}'; Chris@76: elseif ($type == 'size') Chris@76: $new_condition[] = 'a.size > {int:' . $real_type . '}'; Chris@76: elseif ($type == 'id_topic') Chris@76: $new_condition[] = 'm.id_topic IN (' . (is_array($restriction) ? '{array_int:' . $real_type . '}' : '{int:' . $real_type . '}') . ')'; Chris@76: Chris@76: // Add the parameter! Chris@76: $query_parameter[$real_type] = $restriction; Chris@76: } Chris@76: $condition = implode(' AND ', $new_condition); Chris@76: } Chris@76: Chris@76: // Delete it only if it exists... Chris@76: $msgs = array(); Chris@76: $attach = array(); Chris@76: $parents = array(); Chris@76: Chris@76: // Get all the attachment names and id_msg's. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT Chris@76: 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') . ', Chris@76: thumb.id_folder AS thumb_folder, IFNULL(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 Chris@76: FROM {db_prefix}attachments AS a' .($query_type == 'members' ? ' Chris@76: INNER JOIN {db_prefix}members AS mem ON (mem.id_member = a.id_member)' : ($query_type == 'messages' ? ' Chris@76: INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)' : '')) . ' Chris@76: LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb) Chris@76: LEFT JOIN {db_prefix}attachments AS thumb_parent ON (thumb.attachment_type = {int:thumb_attachment_type} AND thumb_parent.id_thumb = a.id_attach) Chris@76: WHERE ' . $condition, Chris@76: $query_parameter Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: // Figure out the "encrypted" filename and unlink it ;). Chris@76: if ($row['attachment_type'] == 1) Chris@76: @unlink($modSettings['custom_avatar_dir'] . '/' . $row['filename']); Chris@76: else Chris@76: { Chris@76: $filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']); Chris@76: @unlink($filename); Chris@76: Chris@76: // If this was a thumb, the parent attachment should know about it. Chris@76: if (!empty($row['id_parent'])) Chris@76: $parents[] = $row['id_parent']; Chris@76: Chris@76: // If this attachments has a thumb, remove it as well. Chris@76: if (!empty($row['id_thumb']) && $autoThumbRemoval) Chris@76: { Chris@76: $thumb_filename = getAttachmentFilename($row['thumb_filename'], $row['id_thumb'], $row['thumb_folder'], false, $row['thumb_file_hash']); Chris@76: @unlink($thumb_filename); Chris@76: $attach[] = $row['id_thumb']; Chris@76: } Chris@76: } Chris@76: Chris@76: // Make a list. Chris@76: if ($return_affected_messages && empty($row['attachment_type'])) Chris@76: $msgs[] = $row['id_msg']; Chris@76: $attach[] = $row['id_attach']; Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Removed attachments don't have to be updated anymore. Chris@76: $parents = array_diff($parents, $attach); Chris@76: if (!empty($parents)) Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}attachments Chris@76: SET id_thumb = {int:no_thumb} Chris@76: WHERE id_attach IN ({array_int:parent_attachments})', Chris@76: array( Chris@76: 'parent_attachments' => $parents, Chris@76: 'no_thumb' => 0, Chris@76: ) Chris@76: ); Chris@76: Chris@76: if (!empty($attach)) Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}attachments Chris@76: WHERE id_attach IN ({array_int:attachment_list})', Chris@76: array( Chris@76: 'attachment_list' => $attach, Chris@76: ) Chris@76: ); Chris@76: Chris@76: if ($return_affected_messages) Chris@76: return array_unique($msgs); Chris@76: } Chris@76: Chris@76: // This function should find attachments in the database that no longer exist and clear them, and fix filesize issues. Chris@76: function RepairAttachments() Chris@76: { Chris@76: global $modSettings, $context, $txt, $smcFunc; Chris@76: Chris@76: checkSession('get'); Chris@76: Chris@76: // If we choose cancel, redirect right back. Chris@76: if (isset($_POST['cancel'])) Chris@76: redirectexit('action=admin;area=manageattachments;sa=maintenance'); Chris@76: Chris@76: // Try give us a while to sort this out... Chris@76: @set_time_limit(600); Chris@76: Chris@76: $_GET['step'] = empty($_GET['step']) ? 0 : (int) $_GET['step']; Chris@76: $_GET['substep'] = empty($_GET['substep']) ? 0 : (int) $_GET['substep']; Chris@76: Chris@76: // Don't recall the session just in case. Chris@76: if ($_GET['step'] == 0 && $_GET['substep'] == 0) Chris@76: { Chris@76: unset($_SESSION['attachments_to_fix'], $_SESSION['attachments_to_fix2']); Chris@76: Chris@76: // If we're actually fixing stuff - work out what. Chris@76: if (isset($_GET['fixErrors'])) Chris@76: { Chris@76: // Nothing? Chris@76: if (empty($_POST['to_fix'])) Chris@76: redirectexit('action=admin;area=manageattachments;sa=maintenance'); Chris@76: Chris@76: $_SESSION['attachments_to_fix'] = array(); Chris@76: //!!! No need to do this I think. Chris@76: foreach ($_POST['to_fix'] as $key => $value) Chris@76: $_SESSION['attachments_to_fix'][] = $value; Chris@76: } Chris@76: } Chris@76: Chris@76: // All the valid problems are here: Chris@76: $context['repair_errors'] = array( Chris@76: 'missing_thumbnail_parent' => 0, Chris@76: 'parent_missing_thumbnail' => 0, Chris@76: 'file_missing_on_disk' => 0, Chris@76: 'file_wrong_size' => 0, Chris@76: 'file_size_of_zero' => 0, Chris@76: 'attachment_no_msg' => 0, Chris@76: 'avatar_no_member' => 0, Chris@76: 'wrong_folder' => 0, Chris@76: ); Chris@76: Chris@76: $to_fix = !empty($_SESSION['attachments_to_fix']) ? $_SESSION['attachments_to_fix'] : array(); Chris@76: $context['repair_errors'] = isset($_SESSION['attachments_to_fix2']) ? $_SESSION['attachments_to_fix2'] : $context['repair_errors']; Chris@76: $fix_errors = isset($_GET['fixErrors']) ? true : false; Chris@76: Chris@76: // Get stranded thumbnails. Chris@76: if ($_GET['step'] <= 0) Chris@76: { Chris@76: $result = $smcFunc['db_query']('', ' Chris@76: SELECT MAX(id_attach) Chris@76: FROM {db_prefix}attachments Chris@76: WHERE attachment_type = {int:thumbnail}', Chris@76: array( Chris@76: 'thumbnail' => 3, Chris@76: ) Chris@76: ); Chris@76: list ($thumbnails) = $smcFunc['db_fetch_row']($result); Chris@76: $smcFunc['db_free_result']($result); Chris@76: Chris@76: for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) Chris@76: { Chris@76: $to_remove = array(); Chris@76: Chris@76: $result = $smcFunc['db_query']('', ' Chris@76: SELECT thumb.id_attach, thumb.id_folder, thumb.filename, thumb.file_hash Chris@76: FROM {db_prefix}attachments AS thumb Chris@76: LEFT JOIN {db_prefix}attachments AS tparent ON (tparent.id_thumb = thumb.id_attach) Chris@76: WHERE thumb.id_attach BETWEEN {int:substep} AND {int:substep} + 499 Chris@76: AND thumb.attachment_type = {int:thumbnail} Chris@76: AND tparent.id_attach IS NULL', Chris@76: array( Chris@76: 'thumbnail' => 3, Chris@76: 'substep' => $_GET['substep'], Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($result)) Chris@76: { Chris@76: // Only do anything once... just in case Chris@76: if (!isset($to_remove[$row['id_attach']])) Chris@76: { Chris@76: $to_remove[$row['id_attach']] = $row['id_attach']; Chris@76: $context['repair_errors']['missing_thumbnail_parent']++; Chris@76: Chris@76: // If we are repairing remove the file from disk now. Chris@76: if ($fix_errors && in_array('missing_thumbnail_parent', $to_fix)) Chris@76: { Chris@76: $filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']); Chris@76: @unlink($filename); Chris@76: } Chris@76: } Chris@76: } Chris@76: if ($smcFunc['db_num_rows']($result) != 0) Chris@76: $to_fix[] = 'missing_thumbnail_parent'; Chris@76: $smcFunc['db_free_result']($result); Chris@76: Chris@76: // Do we need to delete what we have? Chris@76: if ($fix_errors && !empty($to_remove) && in_array('missing_thumbnail_parent', $to_fix)) Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}attachments Chris@76: WHERE id_attach IN ({array_int:to_remove}) Chris@76: AND attachment_type = {int:attachment_type}', Chris@76: array( Chris@76: 'to_remove' => $to_remove, Chris@76: 'attachment_type' => 3, Chris@76: ) Chris@76: ); Chris@76: Chris@76: pauseAttachmentMaintenance($to_fix, $thumbnails); Chris@76: } Chris@76: Chris@76: $_GET['step'] = 1; Chris@76: $_GET['substep'] = 0; Chris@76: pauseAttachmentMaintenance($to_fix); Chris@76: } Chris@76: Chris@76: // Find parents which think they have thumbnails, but actually, don't. Chris@76: if ($_GET['step'] <= 1) Chris@76: { Chris@76: $result = $smcFunc['db_query']('', ' Chris@76: SELECT MAX(id_attach) Chris@76: FROM {db_prefix}attachments Chris@76: WHERE id_thumb != {int:no_thumb}', Chris@76: array( Chris@76: 'no_thumb' => 0, Chris@76: ) Chris@76: ); Chris@76: list ($thumbnails) = $smcFunc['db_fetch_row']($result); Chris@76: $smcFunc['db_free_result']($result); Chris@76: Chris@76: for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) Chris@76: { Chris@76: $to_update = array(); Chris@76: Chris@76: $result = $smcFunc['db_query']('', ' Chris@76: SELECT a.id_attach Chris@76: FROM {db_prefix}attachments AS a Chris@76: LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb) Chris@76: WHERE a.id_attach BETWEEN {int:substep} AND {int:substep} + 499 Chris@76: AND a.id_thumb != {int:no_thumb} Chris@76: AND thumb.id_attach IS NULL', Chris@76: array( Chris@76: 'no_thumb' => 0, Chris@76: 'substep' => $_GET['substep'], Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($result)) Chris@76: { Chris@76: $to_update[] = $row['id_attach']; Chris@76: $context['repair_errors']['parent_missing_thumbnail']++; Chris@76: } Chris@76: if ($smcFunc['db_num_rows']($result) != 0) Chris@76: $to_fix[] = 'parent_missing_thumbnail'; Chris@76: $smcFunc['db_free_result']($result); Chris@76: Chris@76: // Do we need to delete what we have? Chris@76: if ($fix_errors && !empty($to_update) && in_array('parent_missing_thumbnail', $to_fix)) Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}attachments Chris@76: SET id_thumb = {int:no_thumb} Chris@76: WHERE id_attach IN ({array_int:to_update})', Chris@76: array( Chris@76: 'to_update' => $to_update, Chris@76: 'no_thumb' => 0, Chris@76: ) Chris@76: ); Chris@76: Chris@76: pauseAttachmentMaintenance($to_fix, $thumbnails); Chris@76: } Chris@76: Chris@76: $_GET['step'] = 2; Chris@76: $_GET['substep'] = 0; Chris@76: pauseAttachmentMaintenance($to_fix); Chris@76: } Chris@76: Chris@76: // This may take forever I'm afraid, but life sucks... recount EVERY attachments! Chris@76: if ($_GET['step'] <= 2) Chris@76: { Chris@76: $result = $smcFunc['db_query']('', ' Chris@76: SELECT MAX(id_attach) Chris@76: FROM {db_prefix}attachments', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: list ($thumbnails) = $smcFunc['db_fetch_row']($result); Chris@76: $smcFunc['db_free_result']($result); Chris@76: Chris@76: for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 250) Chris@76: { Chris@76: $to_remove = array(); Chris@76: $errors_found = array(); Chris@76: Chris@76: $result = $smcFunc['db_query']('', ' Chris@76: SELECT id_attach, id_folder, filename, file_hash, size, attachment_type Chris@76: FROM {db_prefix}attachments Chris@76: WHERE id_attach BETWEEN {int:substep} AND {int:substep} + 249', Chris@76: array( Chris@76: 'substep' => $_GET['substep'], Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($result)) Chris@76: { Chris@76: // Get the filename. Chris@76: if ($row['attachment_type'] == 1) Chris@76: $filename = $modSettings['custom_avatar_dir'] . '/' . $row['filename']; Chris@76: else Chris@76: $filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']); Chris@76: Chris@76: // File doesn't exist? Chris@76: if (!file_exists($filename)) Chris@76: { Chris@76: // If we're lucky it might just be in a different folder. Chris@76: if (!empty($modSettings['currentAttachmentUploadDir'])) Chris@76: { Chris@76: // Get the attachment name with out the folder. Chris@76: $attachment_name = !empty($row['file_hash']) ? $row['id_attach'] . '_' . $row['file_hash'] : getLegacyAttachmentFilename($row['filename'], $row['id_attach'], null, true); Chris@76: Chris@76: if (!is_array($modSettings['attachmentUploadDir'])) Chris@76: $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']); Chris@76: Chris@76: // Loop through the other folders. Chris@76: foreach ($modSettings['attachmentUploadDir'] as $id => $dir) Chris@76: if (file_exists($dir . '/' . $attachment_name)) Chris@76: { Chris@76: $context['repair_errors']['wrong_folder']++; Chris@76: $errors_found[] = 'wrong_folder'; Chris@76: Chris@76: // Are we going to fix this now? Chris@76: if ($fix_errors && in_array('wrong_folder', $to_fix)) Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}attachments Chris@76: SET id_folder = {int:new_folder} Chris@76: WHERE id_attach = {int:id_attach}', Chris@76: array( Chris@76: 'new_folder' => $id, Chris@76: 'id_attach' => $row['id_attach'], Chris@76: ) Chris@76: ); Chris@76: Chris@76: continue 2; Chris@76: } Chris@76: } Chris@76: Chris@76: $to_remove[] = $row['id_attach']; Chris@76: $context['repair_errors']['file_missing_on_disk']++; Chris@76: $errors_found[] = 'file_missing_on_disk'; Chris@76: } Chris@76: elseif (filesize($filename) == 0) Chris@76: { Chris@76: $context['repair_errors']['file_size_of_zero']++; Chris@76: $errors_found[] = 'file_size_of_zero'; Chris@76: Chris@76: // Fixing? Chris@76: if ($fix_errors && in_array('file_size_of_zero', $to_fix)) Chris@76: { Chris@76: $to_remove[] = $row['id_attach']; Chris@76: @unlink($filename); Chris@76: } Chris@76: } Chris@76: elseif (filesize($filename) != $row['size']) Chris@76: { Chris@76: $context['repair_errors']['file_wrong_size']++; Chris@76: $errors_found[] = 'file_wrong_size'; Chris@76: Chris@76: // Fix it here? Chris@76: if ($fix_errors && in_array('file_wrong_size', $to_fix)) Chris@76: { Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}attachments Chris@76: SET size = {int:filesize} Chris@76: WHERE id_attach = {int:id_attach}', Chris@76: array( Chris@76: 'filesize' => filesize($filename), Chris@76: 'id_attach' => $row['id_attach'], Chris@76: ) Chris@76: ); Chris@76: } Chris@76: } Chris@76: } Chris@76: Chris@76: if (in_array('file_missing_on_disk', $errors_found)) Chris@76: $to_fix[] = 'file_missing_on_disk'; Chris@76: if (in_array('file_size_of_zero', $errors_found)) Chris@76: $to_fix[] = 'file_size_of_zero'; Chris@76: if (in_array('file_wrong_size', $errors_found)) Chris@76: $to_fix[] = 'file_wrong_size'; Chris@76: if (in_array('wrong_folder', $errors_found)) Chris@76: $to_fix[] = 'wrong_folder'; Chris@76: $smcFunc['db_free_result']($result); Chris@76: Chris@76: // Do we need to delete what we have? Chris@76: if ($fix_errors && !empty($to_remove)) Chris@76: { Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}attachments Chris@76: WHERE id_attach IN ({array_int:to_remove})', Chris@76: array( Chris@76: 'to_remove' => $to_remove, Chris@76: ) Chris@76: ); Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}attachments Chris@76: SET id_thumb = {int:no_thumb} Chris@76: WHERE id_thumb IN ({array_int:to_remove})', Chris@76: array( Chris@76: 'to_remove' => $to_remove, Chris@76: 'no_thumb' => 0, Chris@76: ) Chris@76: ); Chris@76: } Chris@76: Chris@76: pauseAttachmentMaintenance($to_fix, $thumbnails); Chris@76: } Chris@76: Chris@76: $_GET['step'] = 3; Chris@76: $_GET['substep'] = 0; Chris@76: pauseAttachmentMaintenance($to_fix); Chris@76: } Chris@76: Chris@76: // Get avatars with no members associated with them. Chris@76: if ($_GET['step'] <= 3) Chris@76: { Chris@76: $result = $smcFunc['db_query']('', ' Chris@76: SELECT MAX(id_attach) Chris@76: FROM {db_prefix}attachments', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: list ($thumbnails) = $smcFunc['db_fetch_row']($result); Chris@76: $smcFunc['db_free_result']($result); Chris@76: Chris@76: for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) Chris@76: { Chris@76: $to_remove = array(); Chris@76: Chris@76: $result = $smcFunc['db_query']('', ' Chris@76: SELECT a.id_attach, a.id_folder, a.filename, a.file_hash, a.attachment_type Chris@76: FROM {db_prefix}attachments AS a Chris@76: LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = a.id_member) Chris@76: WHERE a.id_attach BETWEEN {int:substep} AND {int:substep} + 499 Chris@76: AND a.id_member != {int:no_member} Chris@76: AND a.id_msg = {int:no_msg} Chris@76: AND mem.id_member IS NULL', Chris@76: array( Chris@76: 'no_member' => 0, Chris@76: 'no_msg' => 0, Chris@76: 'substep' => $_GET['substep'], Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($result)) Chris@76: { Chris@76: $to_remove[] = $row['id_attach']; Chris@76: $context['repair_errors']['avatar_no_member']++; Chris@76: Chris@76: // If we are repairing remove the file from disk now. Chris@76: if ($fix_errors && in_array('avatar_no_member', $to_fix)) Chris@76: { Chris@76: if ($row['attachment_type'] == 1) Chris@76: $filename = $modSettings['custom_avatar_dir'] . '/' . $row['filename']; Chris@76: else Chris@76: $filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']); Chris@76: @unlink($filename); Chris@76: } Chris@76: } Chris@76: if ($smcFunc['db_num_rows']($result) != 0) Chris@76: $to_fix[] = 'avatar_no_member'; Chris@76: $smcFunc['db_free_result']($result); Chris@76: Chris@76: // Do we need to delete what we have? Chris@76: if ($fix_errors && !empty($to_remove) && in_array('avatar_no_member', $to_fix)) Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}attachments Chris@76: WHERE id_attach IN ({array_int:to_remove}) Chris@76: AND id_member != {int:no_member} Chris@76: AND id_msg = {int:no_msg}', Chris@76: array( Chris@76: 'to_remove' => $to_remove, Chris@76: 'no_member' => 0, Chris@76: 'no_msg' => 0, Chris@76: ) Chris@76: ); Chris@76: Chris@76: pauseAttachmentMaintenance($to_fix, $thumbnails); Chris@76: } Chris@76: Chris@76: $_GET['step'] = 4; Chris@76: $_GET['substep'] = 0; Chris@76: pauseAttachmentMaintenance($to_fix); Chris@76: } Chris@76: Chris@76: // What about attachments, who are missing a message :'( Chris@76: if ($_GET['step'] <= 4) Chris@76: { Chris@76: $result = $smcFunc['db_query']('', ' Chris@76: SELECT MAX(id_attach) Chris@76: FROM {db_prefix}attachments', Chris@76: array( Chris@76: ) Chris@76: ); Chris@76: list ($thumbnails) = $smcFunc['db_fetch_row']($result); Chris@76: $smcFunc['db_free_result']($result); Chris@76: Chris@76: for (; $_GET['substep'] < $thumbnails; $_GET['substep'] += 500) Chris@76: { Chris@76: $to_remove = array(); Chris@76: Chris@76: $result = $smcFunc['db_query']('', ' Chris@76: SELECT a.id_attach, a.id_folder, a.filename, a.file_hash Chris@76: FROM {db_prefix}attachments AS a Chris@76: LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg) Chris@76: WHERE a.id_attach BETWEEN {int:substep} AND {int:substep} + 499 Chris@76: AND a.id_member = {int:no_member} Chris@76: AND a.id_msg != {int:no_msg} Chris@76: AND m.id_msg IS NULL', Chris@76: array( Chris@76: 'no_member' => 0, Chris@76: 'no_msg' => 0, Chris@76: 'substep' => $_GET['substep'], Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($result)) Chris@76: { Chris@76: $to_remove[] = $row['id_attach']; Chris@76: $context['repair_errors']['attachment_no_msg']++; Chris@76: Chris@76: // If we are repairing remove the file from disk now. Chris@76: if ($fix_errors && in_array('attachment_no_msg', $to_fix)) Chris@76: { Chris@76: $filename = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']); Chris@76: @unlink($filename); Chris@76: } Chris@76: } Chris@76: if ($smcFunc['db_num_rows']($result) != 0) Chris@76: $to_fix[] = 'attachment_no_msg'; Chris@76: $smcFunc['db_free_result']($result); Chris@76: Chris@76: // Do we need to delete what we have? Chris@76: if ($fix_errors && !empty($to_remove) && in_array('attachment_no_msg', $to_fix)) Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}attachments Chris@76: WHERE id_attach IN ({array_int:to_remove}) Chris@76: AND id_member = {int:no_member} Chris@76: AND id_msg != {int:no_msg}', Chris@76: array( Chris@76: 'to_remove' => $to_remove, Chris@76: 'no_member' => 0, Chris@76: 'no_msg' => 0, Chris@76: ) Chris@76: ); Chris@76: Chris@76: pauseAttachmentMaintenance($to_fix, $thumbnails); Chris@76: } Chris@76: Chris@76: $_GET['step'] = 5; Chris@76: $_GET['substep'] = 0; Chris@76: pauseAttachmentMaintenance($to_fix); Chris@76: } Chris@76: Chris@76: // Got here we must be doing well - just the template! :D Chris@76: $context['page_title'] = $txt['repair_attachments']; Chris@76: $context[$context['admin_menu_name']]['current_subsection'] = 'maintenance'; Chris@76: $context['sub_template'] = 'attachment_repair'; Chris@76: Chris@76: // What stage are we at? Chris@76: $context['completed'] = $fix_errors ? true : false; Chris@76: $context['errors_found'] = !empty($to_fix) ? true : false; Chris@76: Chris@76: } Chris@76: Chris@76: function pauseAttachmentMaintenance($to_fix, $max_substep = 0) Chris@76: { Chris@76: global $context, $txt, $time_start; Chris@76: Chris@76: // Try get more time... Chris@76: @set_time_limit(600); Chris@76: if (function_exists('apache_reset_timeout')) Chris@76: @apache_reset_timeout(); Chris@76: Chris@76: // Have we already used our maximum time? Chris@76: if (time() - array_sum(explode(' ', $time_start)) < 3) Chris@76: return; Chris@76: Chris@76: $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']; Chris@76: $context['page_title'] = $txt['not_done_title']; Chris@76: $context['continue_post_data'] = ''; Chris@76: $context['continue_countdown'] = '2'; Chris@76: $context['sub_template'] = 'not_done'; Chris@76: Chris@76: // Specific stuff to not break this template! Chris@76: $context[$context['admin_menu_name']]['current_subsection'] = 'maintenance'; Chris@76: Chris@76: // Change these two if more steps are added! Chris@76: if (empty($max_substep)) Chris@76: $context['continue_percent'] = round(($_GET['step'] * 100) / 25); Chris@76: else Chris@76: $context['continue_percent'] = round(($_GET['step'] * 100 + ($_GET['substep'] * 100) / $max_substep) / 25); Chris@76: Chris@76: // Never more than 100%! Chris@76: $context['continue_percent'] = min($context['continue_percent'], 100); Chris@76: Chris@76: $_SESSION['attachments_to_fix'] = $to_fix; Chris@76: $_SESSION['attachments_to_fix2'] = $context['repair_errors']; Chris@76: Chris@76: obExit(); Chris@76: } Chris@76: Chris@76: // Called from a mouse click, works out what we want to do with attachments and actions it. Chris@76: function ApproveAttach() Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: // Security is our primary concern... Chris@76: checkSession('get'); Chris@76: Chris@76: // If it approve or delete? Chris@76: $is_approve = !isset($_GET['sa']) || $_GET['sa'] != 'reject' ? true : false; Chris@76: Chris@76: $attachments = array(); Chris@76: // If we are approving all ID's in a message , get the ID's. Chris@76: if ($_GET['sa'] == 'all' && !empty($_GET['mid'])) Chris@76: { Chris@76: $id_msg = (int) $_GET['mid']; Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_attach Chris@76: FROM {db_prefix}attachments Chris@76: WHERE id_msg = {int:id_msg} Chris@76: AND approved = {int:is_approved} Chris@76: AND attachment_type = {int:attachment_type}', Chris@76: array( Chris@76: 'id_msg' => $id_msg, Chris@76: 'is_approved' => 0, Chris@76: 'attachment_type' => 0, Chris@76: ) Chris@76: ); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $attachments[] = $row['id_attach']; Chris@76: $smcFunc['db_free_result']($request); Chris@76: } Chris@76: elseif (!empty($_GET['aid'])) Chris@76: $attachments[] = (int) $_GET['aid']; Chris@76: Chris@76: if (empty($attachments)) Chris@76: fatal_lang_error('no_access', false); Chris@76: Chris@76: // Now we have some ID's cleaned and ready to approve, but first - let's check we have permission! Chris@76: $allowed_boards = boardsAllowedTo('approve_posts'); Chris@76: Chris@76: // Validate the attachments exist and are the right approval state. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT a.id_attach, m.id_board, m.id_msg, m.id_topic Chris@76: FROM {db_prefix}attachments AS a Chris@76: INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg) Chris@76: WHERE a.id_attach IN ({array_int:attachments}) Chris@76: AND a.attachment_type = {int:attachment_type} Chris@76: AND a.approved = {int:is_approved}', Chris@76: array( Chris@76: 'attachments' => $attachments, Chris@76: 'attachment_type' => 0, Chris@76: 'is_approved' => 0, Chris@76: ) Chris@76: ); Chris@76: $attachments = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: // We can only add it if we can approve in this board! Chris@76: if ($allowed_boards = array(0) || in_array($row['id_board'], $allowed_boards)) Chris@76: { Chris@76: $attachments[] = $row['id_attach']; Chris@76: Chris@76: // Also come up witht he redirection URL. Chris@76: $redirect = 'topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg']; Chris@76: } Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: if (empty($attachments)) Chris@76: fatal_lang_error('no_access', false); Chris@76: Chris@76: // Finally, we are there. Follow through! Chris@76: if ($is_approve) Chris@76: ApproveAttachments($attachments); Chris@76: else Chris@76: removeAttachments(array('id_attach' => $attachments)); Chris@76: Chris@76: // Return to the topic.... Chris@76: redirectexit($redirect); Chris@76: } Chris@76: Chris@76: // Approve an attachment, or maybe even more - no permission check! Chris@76: function ApproveAttachments($attachments) Chris@76: { Chris@76: global $smcFunc; Chris@76: Chris@76: if (empty($attachments)) Chris@76: return 0; Chris@76: Chris@76: // For safety, check for thumbnails... Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT Chris@76: a.id_attach, a.id_member, IFNULL(thumb.id_attach, 0) AS id_thumb Chris@76: FROM {db_prefix}attachments AS a Chris@76: LEFT JOIN {db_prefix}attachments AS thumb ON (thumb.id_attach = a.id_thumb) Chris@76: WHERE a.id_attach IN ({array_int:attachments}) Chris@76: AND a.attachment_type = {int:attachment_type}', Chris@76: array( Chris@76: 'attachments' => $attachments, Chris@76: 'attachment_type' => 0, Chris@76: ) Chris@76: ); Chris@76: $attachments = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: { Chris@76: // Update the thumbnail too... Chris@76: if (!empty($row['id_thumb'])) Chris@76: $attachments[] = $row['id_thumb']; Chris@76: Chris@76: $attachments[] = $row['id_attach']; Chris@76: } Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // Approving an attachment is not hard - it's easy. Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}attachments Chris@76: SET approved = {int:is_approved} Chris@76: WHERE id_attach IN ({array_int:attachments})', Chris@76: array( Chris@76: 'attachments' => $attachments, Chris@76: 'is_approved' => 1, Chris@76: ) Chris@76: ); Chris@76: Chris@76: // Remove from the approval queue. Chris@76: $smcFunc['db_query']('', ' Chris@76: DELETE FROM {db_prefix}approval_queue Chris@76: WHERE id_attach IN ({array_int:attachments})', Chris@76: array( Chris@76: 'attachments' => $attachments, Chris@76: ) Chris@76: ); Chris@76: } Chris@76: Chris@76: function ManageAttachmentPaths() Chris@76: { Chris@76: global $modSettings, $scripturl, $context, $txt, $sourcedir, $smcFunc; Chris@76: Chris@76: // Saving? Chris@76: if (isset($_REQUEST['save'])) Chris@76: { Chris@76: checkSession(); Chris@76: Chris@76: $new_dirs = array(); Chris@76: foreach ($_POST['dirs'] as $id => $path) Chris@76: { Chris@76: $id = (int) $id; Chris@76: if ($id < 1) Chris@76: continue; Chris@76: Chris@76: if (empty($path)) Chris@76: { Chris@76: // Let's not try to delete a path with files in it. Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT COUNT(id_attach) AS num_attach Chris@76: FROM {db_prefix}attachments Chris@76: WHERE id_folder = {int:id_folder}', Chris@76: array( Chris@76: 'id_folder' => (int) $id, Chris@76: ) Chris@76: ); Chris@76: Chris@76: list ($num_attach) = $smcFunc['db_fetch_row']($request); Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: // It's safe to delete. Chris@76: if ($num_attach == 0) Chris@76: continue; Chris@76: } Chris@76: Chris@76: $new_dirs[$id] = $path; Chris@76: } Chris@76: Chris@76: // We need to make sure the current directory is right. Chris@76: $_POST['current_dir'] = (int) $_POST['current_dir']; Chris@76: if (empty($_POST['current_dir']) || empty($new_dirs[$_POST['current_dir']])) Chris@76: fatal_lang_error('attach_path_current_bad', false); Chris@76: Chris@76: // Going back to just one path? Chris@76: if (count($new_dirs) == 1) Chris@76: { Chris@76: // We might need to reset the paths. This loop will just loop through once. Chris@76: foreach ($new_dirs as $id => $dir) Chris@76: { Chris@76: if ($id != 1) Chris@76: $smcFunc['db_query']('', ' Chris@76: UPDATE {db_prefix}attachments Chris@76: SET id_folder = {int:default_folder} Chris@76: WHERE id_folder = {int:current_folder}', Chris@76: array( Chris@76: 'default_folder' => 1, Chris@76: 'current_folder' => $id, Chris@76: ) Chris@76: ); Chris@76: Chris@76: updateSettings(array( Chris@76: 'currentAttachmentUploadDir' => 0, Chris@76: 'attachmentUploadDir' => $dir, Chris@76: )); Chris@76: } Chris@76: } Chris@76: else Chris@76: // Save it to the database. Chris@76: updateSettings(array( Chris@76: 'currentAttachmentUploadDir' => $_POST['current_dir'], Chris@76: 'attachmentUploadDir' => serialize($new_dirs), Chris@76: )); Chris@76: } Chris@76: Chris@76: // Are they here for the first time? Chris@76: if (empty($modSettings['currentAttachmentUploadDir'])) Chris@76: { Chris@76: $modSettings['attachmentUploadDir'] = array( Chris@76: 1 => $modSettings['attachmentUploadDir'] Chris@76: ); Chris@76: $modSettings['currentAttachmentUploadDir'] = 1; Chris@76: } Chris@76: // Otherwise just load up their attachment paths. Chris@76: else Chris@76: $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']); Chris@76: Chris@76: $listOptions = array( Chris@76: 'id' => 'attach_paths', Chris@76: 'base_href' => $scripturl . '?action=admin;area=manageattachments;sa=attachpaths;' . $context['session_var'] . '=' . $context['session_id'], Chris@76: 'title' => $txt['attach_paths'], Chris@76: 'get_items' => array( Chris@76: 'function' => 'list_getAttachDirs', Chris@76: ), Chris@76: 'columns' => array( Chris@76: 'current_dir' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['attach_current_dir'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: return \'\'; Chris@76: '), Chris@76: 'style' => 'text-align: center; width: 15%;', Chris@76: ), Chris@76: ), Chris@76: 'path' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['attach_path'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'function' => create_function('$rowData', ' Chris@76: return \'\'; Chris@76: '), Chris@76: 'style' => 'text-align: center; width: 30%;', Chris@76: ), Chris@76: ), Chris@76: 'current_size' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['attach_current_size'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'current_size', Chris@76: 'style' => 'text-align: center; width: 15%;', Chris@76: ), Chris@76: ), Chris@76: 'num_files' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['attach_num_files'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'num_files', Chris@76: 'style' => 'text-align: center; width: 15%;', Chris@76: ), Chris@76: ), Chris@76: 'status' => array( Chris@76: 'header' => array( Chris@76: 'value' => $txt['attach_dir_status'], Chris@76: ), Chris@76: 'data' => array( Chris@76: 'db' => 'status', Chris@76: 'style' => 'text-align: center; width: 25%;', Chris@76: ), Chris@76: ), Chris@76: ), Chris@76: 'form' => array( Chris@76: 'href' => $scripturl . '?action=admin;area=manageattachments;sa=attachpaths;' . $context['session_var'] . '=' . $context['session_id'], Chris@76: ), Chris@76: 'additional_rows' => array( Chris@76: array( Chris@76: 'position' => 'below_table_data', Chris@76: 'value' => ' ', Chris@76: 'style' => 'text-align: right;', Chris@76: ), Chris@76: ), Chris@76: ); Chris@76: Chris@76: require_once($sourcedir . '/Subs-List.php'); Chris@76: createList($listOptions); Chris@76: Chris@76: // Fix up our template. Chris@76: $context[$context['admin_menu_name']]['current_subsection'] = 'attachments'; Chris@76: $context['page_title'] = $txt['attach_path_manage']; Chris@76: $context['sub_template'] = 'attachment_paths'; Chris@76: } Chris@76: Chris@76: // Prepare the actual attachment directories to be displayed in the list. Chris@76: function list_getAttachDirs() Chris@76: { Chris@76: global $smcFunc, $modSettings, $context, $txt; Chris@76: Chris@76: // The dirs should already have been unserialized but just in case... Chris@76: if (!is_array($modSettings['attachmentUploadDir'])) Chris@76: $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']); Chris@76: Chris@76: $request = $smcFunc['db_query']('', ' Chris@76: SELECT id_folder, COUNT(id_attach) AS num_attach Chris@76: FROM {db_prefix}attachments' . (empty($modSettings['custom_avatar_enabled']) ? '' : ' Chris@76: WHERE attachment_type != {int:type_avatar}') . ' Chris@76: GROUP BY id_folder', Chris@76: array( Chris@76: 'type_avatar' => 1, Chris@76: ) Chris@76: ); Chris@76: Chris@76: $expected_files = array(); Chris@76: while ($row = $smcFunc['db_fetch_assoc']($request)) Chris@76: $expected_files[$row['id_folder']] = $row['num_attach']; Chris@76: $smcFunc['db_free_result']($request); Chris@76: Chris@76: $attachdirs = array(); Chris@76: foreach ($modSettings['attachmentUploadDir'] as $id => $dir) Chris@76: { Chris@76: // If there aren't any attachments in this directory this won't exist. Chris@76: if (!isset($expected_files[$id])) Chris@76: $expected_files[$id] = 0; Chris@76: Chris@76: // Check if the directory is doing okay. Chris@76: list ($status, $error, $size) = attachDirStatus($dir, $expected_files[$id]); Chris@76: Chris@76: $attachdirs[] = array( Chris@76: 'id' => $id, Chris@76: 'current' => $id == $modSettings['currentAttachmentUploadDir'], Chris@76: 'path' => $dir, Chris@76: 'current_size' => $size, Chris@76: 'num_files' => $expected_files[$id], Chris@76: 'status' => ($error ? '' : '') . sprintf($txt['attach_dir_' . $status], $context['session_id'], $context['session_var']) . ($error ? '' : ''), Chris@76: ); Chris@76: } Chris@76: Chris@76: // Just stick a new directory on at the bottom. Chris@76: if (isset($_REQUEST['new_path'])) Chris@76: $attachdirs[] = array( Chris@76: 'id' => max(array_merge(array_keys($expected_files), array_keys($modSettings['attachmentUploadDir']))) + 1, Chris@76: 'current' => false, Chris@76: 'path' => '', Chris@76: 'current_size' => '', Chris@76: 'num_files' => '', Chris@76: 'status' => '', Chris@76: ); Chris@76: Chris@76: return $attachdirs; Chris@76: } Chris@76: Chris@76: // Checks the status of an attachment directory and returns an array of the status key, if that status key signifies an error, and the folder size. Chris@76: function attachDirStatus($dir, $expected_files) Chris@76: { Chris@76: if (!is_dir($dir)) Chris@76: return array('does_not_exist', true, ''); Chris@76: elseif (!is_writable($dir)) Chris@76: return array('not_writable', true, ''); Chris@76: Chris@76: // Everything is okay so far, start to scan through the directory. Chris@76: $dir_size = 0; Chris@76: $num_files = 0; Chris@76: $dir_handle = dir($dir); Chris@76: while ($file = $dir_handle->read()) Chris@76: { Chris@76: // Now do we have a real file here? Chris@76: if (in_array($file, array('.', '..', '.htaccess', 'index.php'))) Chris@76: continue; Chris@76: Chris@76: $dir_size += filesize($dir . '/' . $file); Chris@76: $num_files++; Chris@76: } Chris@76: $dir_handle->close(); Chris@76: Chris@76: $dir_size = round($dir_size / 1024, 2); Chris@76: Chris@76: if ($num_files < $expected_files) Chris@76: return array('files_missing', true, $dir_size); Chris@76: // Empty? Chris@76: elseif ($expected_files == 0) Chris@76: return array('unused', false, $dir_size); Chris@76: // All good! Chris@76: else Chris@76: return array('ok', false, $dir_size); Chris@76: } Chris@76: Chris@76: ?>