Files
forum/Sources/ManageAttachments.php

361 lines
13 KiB
PHP

<?php
/******************************************************************************
* ManageAttachments.php *
*******************************************************************************
* SMF: Simple Machines Forum *
* Open-Source Project Inspired by Zef Hemel (zef@zefhemel.com) *
* =========================================================================== *
* Software Version: SMF 1.0.1 *
* Software by: Simple Machines (http://www.simplemachines.org) *
* Copyright 2001-2005 by: Lewis Media (http://www.lewismedia.com) *
* Support, News, Updates at: http://www.simplemachines.org *
*******************************************************************************
* This program is free software; you may redistribute it and/or modify it *
* under the terms of the provided license as published by Lewis Media. *
* *
* This program is distributed in the hope that it is and will be useful, *
* but WITHOUT ANY WARRANTIES; without even any implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
* See the "license.txt" file for details of the Simple Machines license. *
* The latest version can always be found at http://www.simplemachines.org. *
******************************************************************************/
if (!defined('SMF'))
die('Hacking attempt...');
// The main attachment management function.
function ManageAttachments()
{
global $txt, $db_prefix, $modSettings, $scripturl, $context, $options;
// You have to be able to moderate the forum to do this.
isAllowedTo('manage_attachments');
// Show the administration bar, etc.
adminIndex('manage_attachments');
// If they want to delete attachment(s), delete them. (otherwise fall through..)
$subActions = array(
'byAge' => 'RemoveAttachmentByAge',
'bySize' => 'RemoveAttachmentBySize',
'maintain' => 'MaintainAttachments',
'remove' => 'RemoveAttachment',
'removeall' => 'RemoveAllAttachments'
);
if (isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]))
$subActions[$_REQUEST['sa']]();
loadTemplate('ManageAttachments');
// Attachments or avatars?
$context['browse_avatars'] = isset($_REQUEST['avatars']);
// Get the number of attachments....
$request = db_query("
SELECT COUNT(ID_ATTACH)
FROM {$db_prefix}attachments
WHERE ID_MSG != 0", __FILE__, __LINE__);
list ($context['num_attachments']) = mysql_fetch_row($request);
mysql_free_result($request);
// Also get the avatar amount....
$request = db_query("
SELECT COUNT(ID_ATTACH)
FROM {$db_prefix}attachments
WHERE ID_MEMBER != 0", __FILE__, __LINE__);
list ($context['num_avatars']) = mysql_fetch_row($request);
mysql_free_result($request);
// Allow for sorting of each column...
$sort_methods = array(
'name' => 'a.filename',
'date' => $context['browse_avatars'] ? 'mem.lastLogin' : 'm.ID_MSG',
'size' => 'filesize',
'member' => 'mem.realName'
);
// Set up the importantant sorting variables... if they picked one...
if (!isset($_GET['sort']) || !isset($sort_methods[$_GET['sort']]))
{
$_GET['sort'] = 'date';
$descending = !empty($options['view_newest_first']);
}
// ... and if they didn't...
else
$descending = isset($_GET['desc']);
$context['sort_by'] = $_GET['sort'];
$_GET['sort'] = $sort_methods[$_GET['sort']];
$context['sort_direction'] = $descending ? 'down' : 'up';
// Get the page index ready......
if (!isset($_REQUEST['start']) || $_REQUEST['start'] < 0)
$_REQUEST['start'] = 0;
$context['start'] = $_REQUEST['start'];
$context['page_index'] = constructPageIndex($scripturl . '?action=manageattachments;' . ($context['browse_avatars'] ? 'avatars;' : '') . 'sort=' . $context['sort_by'] . ($context['sort_direction'] == 'down' ? ';desc' : ''), $context['start'], $context['browse_avatars'] ? $context['num_avatars'] : $context['num_attachments'], $modSettings['defaultMaxMessages']);
// Choose a query depending on what we are viewing.
if (!$context['browse_avatars'])
$request = db_query("
SELECT
m.ID_MSG, IFNULL(mem.realName, m.posterName) AS posterName, m.posterTime, m.ID_TOPIC, m.ID_MEMBER,
a.filename, IFNULL(a.size, 0) AS filesize, a.ID_ATTACH, a.downloads, mf.subject, t.ID_BOARD
FROM ({$db_prefix}attachments AS a, {$db_prefix}messages AS m, {$db_prefix}topics AS t, {$db_prefix}messages AS mf)
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)
WHERE a.ID_MSG = m.ID_MSG
AND t.ID_TOPIC = m.ID_TOPIC
AND mf.ID_MSG = t.ID_FIRST_MSG
ORDER BY $_GET[sort] " . ($descending ? 'DESC' : 'ASC') . "
LIMIT $context[start], $modSettings[defaultMaxMessages]", __FILE__, __LINE__);
else
$request = db_query("
SELECT
'' AS ID_MSG, IFNULL(mem.realName, '$txt[470]') AS posterName, mem.lastLogin AS posterTime, 0 AS ID_TOPIC, a.ID_MEMBER,
a.filename, IFNULL(a.size, 0) AS filesize, a.ID_ATTACH, a.downloads, '' AS subject, 0 AS ID_BOARD
FROM {$db_prefix}attachments AS a
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = a.ID_MEMBER)
WHERE a.ID_MEMBER != 0
ORDER BY $_GET[sort] " . ($descending ? 'DESC' : 'ASC') . "
LIMIT $context[start], $modSettings[defaultMaxMessages]", __FILE__, __LINE__);
$context['posts'] = array();
while ($row = mysql_fetch_assoc($request))
$context['posts'][] = array(
'id' => $row['ID_MSG'],
'poster' => array(
'id' => $row['ID_MEMBER'],
'name' => $row['posterName'],
'href' => empty($row['ID_MEMBER']) ? '' : $scripturl . '?action=profile;u=' . $row['ID_MEMBER'],
'link' => empty($row['ID_MEMBER']) ? $row['posterName'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '">' . $row['posterName'] . '</a>'
),
'time' => empty($row['posterTime']) ? $txt['never'] : timeformat($row['posterTime']),
'timestamp' => $row['posterTime'],
'attachment' => array(
'id' => $row['ID_ATTACH'],
'size' => round($row['filesize'] / 1024, 2),
'name' => $row['filename'],
'downloads' => $row['downloads'],
'href' => $scripturl . '?action=dlattach;' . ($context['browse_avatars'] ? 'type=avatar;' : 'topic=' . $row['ID_TOPIC'] . '.0;') . 'id=' . $row['ID_ATTACH'],
'link' => '<a href="' . $scripturl . '?action=dlattach;' . ($context['browse_avatars'] ? 'type=avatar;' : 'topic=' . $row['ID_TOPIC'] . '.0;') . 'id=' . $row['ID_ATTACH'] . '">' . $row['filename'] . '</a>'
),
'topic' => $row['ID_TOPIC'],
'subject' => $row['subject'],
'link' => '<a href="' . $scripturl . '?topic=' . $row['ID_TOPIC'] . '.0">' . $row['subject'] . '</a>'
);
mysql_free_result($request);
// Find out how big the directory is.
$attachmentDirSize = 0;
$dir = @opendir($modSettings['attachmentUploadDir']) or fatal_lang_error('smf115b');
while ($file = readdir($dir))
{
if (substr($file, 0, -1) == '.')
continue;
$attachmentDirSize += filesize($modSettings['attachmentUploadDir'] . '/' . $file);
}
closedir($dir);
// Divide it into kilobytes.
$attachmentDirSize /= 1024;
// If they specified a limit only....
if (!empty($modSettings['attachmentDirSizeLimit']))
$context['attachment_space'] = round($modSettings['attachmentDirSizeLimit'] - $attachmentDirSize, 2);
$context['attachment_total_size'] = round($attachmentDirSize, 2);
$context['page_title'] = $txt['smf201'];
}
function RemoveAttachmentByAge()
{
global $db_prefix, $modSettings;
checkSession('post', 'manageattachments');
// Deleting an attachment?
if ($_REQUEST['type'] != 'avatars')
{
// Get all the old attachments.
$messages = removeAttachments('a.ID_MSG > 0 AND m.posterTime < ' . (time() - 24 * 60 * 60 * $_POST['age']), 'messages', true);
// Update the messages to reflect the change.
if (!empty($messages))
db_query("
UPDATE {$db_prefix}messages
SET body = " . (!empty($_POST['notice']) ? "CONCAT(body, '\n\n$_POST[notice]')" : '') . "
WHERE ID_MSG IN (" . implode(', ', $messages) . ")
LIMIT " . count($messages), __FILE__, __LINE__);
}
else
{
// Remove all the old avatars.
removeAttachments('a.ID_MEMBER != 0 AND mem.lastLogin < ' . (time() - 24 * 60 * 60 * $_POST['age']), 'members');
}
redirectexit('action=manageattachments' . (empty($_REQUEST['avatars']) ? '' : ';avatars'));
}
function RemoveAttachmentBySize()
{
global $db_prefix, $modSettings;
checkSession('post', 'manageattachments');
// Find humungous attachments.
$messages = removeAttachments('a.ID_MSG > 0 AND a.size > ' . (1024 * $_POST['size']), 'messages', true);
// And make a note on the post.
if (!empty($messages))
db_query("
UPDATE {$db_prefix}messages
SET body = " . (!empty($_POST['notice']) ? "CONCAT(body, '\n\n$_POST[notice]')" : '') . "
WHERE ID_MSG IN (" . implode(',', $messages) . ")
LIMIT " . count($messages), __FILE__, __LINE__);
redirectexit('action=manageattachments');
}
function RemoveAttachment()
{
global $db_prefix, $modSettings, $txt;
checkSession('post', 'manageattachments');
if (!empty($_POST['remove']))
{
$attachments = array();
// There must be a quicker way to pass this safety test??
foreach ($_POST['remove'] as $removeID => $dummy)
$attachments[] = (int) $removeID;
if ($_REQUEST['type'] == 'avatars')
removeAttachments('a.ID_ATTACH IN (' . implode(', ', $attachments) . ')');
else
{
$messages = array_unique(removeAttachments('a.ID_ATTACH IN (' . implode(', ', $attachments) . ')', 'messages', true));
// And change the message to reflect this.
if (!empty($messages))
db_query("
UPDATE {$db_prefix}messages
SET body = CONCAT(body, '\n\n" . addslashes($txt['smf216']) . "')
WHERE ID_MSG IN (" . implode(', ', $messages) . ")
LIMIT " . count($messages), __FILE__, __LINE__);
}
}
redirectexit('action=manageattachments;' . ($_REQUEST['type'] == 'avatars' ? 'avatars;' : '') . 'start=' . $_REQUEST['start']);
}
function RemoveAllAttachments()
{
global $db_prefix, $txt;
checkSession('get', 'manageattachments');
$messages = removeAttachments('a.ID_MSG > 0', '', true);
if (!isset($_POST['notice']))
$_POST['notice'] = $txt['smf216'];
// Add the notice on the end of the changed messages.
if (!empty($messages))
db_query("
UPDATE {$db_prefix}messages
SET body = CONCAT(body, '\n\n$_POST[notice]')
WHERE ID_MSG IN (" . implode(',', $messages) . ")
LIMIT " . count($messages), __FILE__, __LINE__);
redirectexit('action=manageattachments');
}
// Removes attachments - allowed query_types: '', 'messages', 'members'
function removeAttachments($condition, $query_type = '', $return_affected_messages = false)
{
global $db_prefix, $modSettings;
// Delete it only if it exists...
$msgs = array();
$attach = array();
// Get all the attachment names and ID_MSGs.
$request = db_query("
SELECT a.filename, a.ID_ATTACH" . ($query_type == 'messages' ? ', m.ID_MSG' : ', a.ID_MSG') . "
FROM {$db_prefix}attachments AS a" .
($query_type == 'messages' ? ", {$db_prefix}messages AS m" : '') .
($query_type == 'members' ? ", {$db_prefix}members AS mem" : '') . "
WHERE $condition" . ($query_type == 'messages' ? '
AND m.ID_MSG = a.ID_MSG' : '') . ($query_type == 'members' ? '
AND mem.ID_MEMBER = a.ID_MEMBER' : ''), __FILE__, __LINE__);
while ($row = mysql_fetch_assoc($request))
{
// Figure out the "encrypted" filename and unlink it ;).
@unlink(getAttachmentFilename($row['filename'], $row['ID_ATTACH']));
// Make a list.
if ($return_affected_messages)
$msgs[] = $row['ID_MSG'];
$attach[] = $row['ID_ATTACH'];
}
mysql_free_result($request);
if (!empty($attach))
db_query("
DELETE FROM {$db_prefix}attachments
WHERE ID_ATTACH IN (" . implode(', ', $attach) . ")
LIMIT " . count($attach), __FILE__, __LINE__);
if ($return_affected_messages)
return $msgs;
}
// This function should find attachments in the database that no longer exist and clear them, and fix filesize issues.
function MaintainAttachments()
{
global $db_prefix, $modSettings;
$request = db_query("
SELECT ID_ATTACH, ID_MSG, ID_MEMBER, filename, IFNULL(size, 0) AS size, downloads
FROM {$db_prefix}attachments", __FILE__, __LINE__);
$removals = array();
$filesizes = array();
while ($row = mysql_fetch_assoc($request))
{
$filename = getAttachmentFilename($row['filename'], $row['ID_ATTACH']);
// Test if the file exists...
if (!file_exists($filename))
{
$removals[] = $row['ID_ATTACH'];
continue;
}
// Fetch the actual filesize.
$realFileSize = filesize($filename);
// If it's different that the previous one... we need to update the database.
if ($realFileSize != $row['size'] && $realFileSize !== false && $realFileSize !== null)
$filesizes[$row['ID_ATTACH']] = (int) $realFileSize;
}
mysql_free_result($request);
// Remove the missing ones...
if (!empty($removals))
{
removeAttachments('a.ID_ATTACH IN (' . implode(', ', $removals) . ')', 'messages');
$context['attachments_removed'] = count($removals);
}
// Update the database with the filesize fixes.
if (!empty($filesizes))
{
foreach ($filesizes as $attach => $filesize)
db_query("
UPDATE {$db_prefix}attachments
SET size = $filesize
WHERE ID_ATTACH = $attach
LIMIT 1", __FILE__, __LINE__);
$context['attachments_fixed'] = count($filesizes);
}
}
?>