/**
     * Maintenance function to move attachments from one directory to another
     */
    public function action_transfer()
    {
        global $modSettings, $txt;
        checkSession();
        // We will need the functions from here
        require_once SUBSDIR . '/Attachments.subs.php';
        require_once SUBSDIR . '/ManageAttachments.subs.php';
        // The list(s) of directory's that are available.
        $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
        if (!empty($modSettings['attachment_basedirectories'])) {
            $modSettings['attachment_basedirectories'] = unserialize($modSettings['attachment_basedirectories']);
        } else {
            $modSettings['basedirectory_for_attachments'] = array();
        }
        // Clean the inputs
        $_POST['from'] = (int) $_POST['from'];
        $_POST['auto'] = !empty($_POST['auto']) ? (int) $_POST['auto'] : 0;
        $_POST['to'] = (int) $_POST['to'];
        $start = !empty($_POST['empty_it']) ? 0 : $modSettings['attachmentDirFileLimit'];
        $_SESSION['checked'] = !empty($_POST['empty_it']) ? true : false;
        // Prepare for the moving
        $limit = 501;
        $results = array();
        $dir_files = 0;
        $current_progress = 0;
        $total_moved = 0;
        $total_not_moved = 0;
        // Need to know where we are moving things from
        if (empty($_POST['from']) || empty($_POST['auto']) && empty($_POST['to'])) {
            $results[] = $txt['attachment_transfer_no_dir'];
        }
        // Same location, that's easy
        if ($_POST['from'] == $_POST['to']) {
            $results[] = $txt['attachment_transfer_same_dir'];
        }
        // No errors so determine how many we may have to move
        if (empty($results)) {
            // Get the total file count for the progress bar.
            $total_progress = getFolderAttachmentCount($_POST['from']);
            $total_progress -= $start;
            if ($total_progress < 1) {
                $results[] = $txt['attachment_transfer_no_find'];
            }
        }
        // Nothing to move (no files in source or below the max limit)
        if (empty($results)) {
            // Moving them automaticaly?
            if (!empty($_POST['auto'])) {
                $modSettings['automanage_attachments'] = 1;
                // Create sub directroys off the root or from an attachment directory?
                $modSettings['use_subdirectories_for_attachments'] = $_POST['auto'] == -1 ? 0 : 1;
                $modSettings['basedirectory_for_attachments'] = $_POST['auto'] > 0 ? $modSettings['attachmentUploadDir'][$_POST['auto']] : $modSettings['basedirectory_for_attachments'];
                // Finaly, where do they need to go
                automanage_attachments_check_directory();
                $new_dir = $modSettings['currentAttachmentUploadDir'];
            } else {
                $new_dir = $_POST['to'];
            }
            $modSettings['currentAttachmentUploadDir'] = $new_dir;
            $break = false;
            while ($break === false) {
                @set_time_limit(300);
                if (function_exists('apache_reset_timeout')) {
                    @apache_reset_timeout();
                }
                // If limits are set, get the file count and size for the destination folder
                if ($dir_files <= 0 && (!empty($modSettings['attachmentDirSizeLimit']) || !empty($modSettings['attachmentDirFileLimit']))) {
                    $current_dir = attachDirProperties($new_dir);
                    $dir_files = $current_dir['files'];
                    $dir_size = $current_dir['size'];
                }
                // Find some attachments to move
                list($tomove_count, $tomove) = findAttachmentsToMove($_POST['from'], $start, $limit);
                // Nothing found to move
                if ($tomove_count === 0) {
                    if (empty($current_progress)) {
                        $results[] = $txt['attachment_transfer_no_find'];
                    }
                    break;
                }
                // No more to move after this batch then set the finished flag.
                if ($tomove_count < $limit) {
                    $break = true;
                }
                // Move them
                $moved = array();
                foreach ($tomove as $row) {
                    $source = getAttachmentFilename($row['filename'], $row['id_attach'], $row['id_folder'], false, $row['file_hash']);
                    $dest = $modSettings['attachmentUploadDir'][$new_dir] . '/' . basename($source);
                    // Size and file count check
                    if (!empty($modSettings['attachmentDirSizeLimit']) || !empty($modSettings['attachmentDirFileLimit'])) {
                        $dir_files++;
                        $dir_size += !empty($row['size']) ? $row['size'] : filesize($source);
                        // If we've reached a directory limit. Do something if we are in auto mode, otherwise set an error.
                        if (!empty($modSettings['attachmentDirSizeLimit']) && $dir_size > $modSettings['attachmentDirSizeLimit'] * 1024 || !empty($modSettings['attachmentDirFileLimit']) && $dir_files > $modSettings['attachmentDirFileLimit']) {
                            // Since we're in auto mode. Create a new folder and reset the counters.
                            if (!empty($_POST['auto'])) {
                                automanage_attachments_by_space();
                                $results[] = sprintf($txt['attachments_transfered'], $total_moved, $modSettings['attachmentUploadDir'][$new_dir]);
                                if (!empty($total_not_moved)) {
                                    $results[] = sprintf($txt['attachments_not_transfered'], $total_not_moved);
                                }
                                $dir_files = 0;
                                $total_moved = 0;
                                $total_not_moved = 0;
                                $break = false;
                                break;
                            } else {
                                $results[] = $txt['attachment_transfer_no_room'];
                                $break = true;
                                break;
                            }
                        }
                    }
                    // Actually move the file
                    if (@rename($source, $dest)) {
                        $total_moved++;
                        $current_progress++;
                        $moved[] = $row['id_attach'];
                    } else {
                        $total_not_moved++;
                    }
                }
                // Update the database to reflect the new file location
                if (!empty($moved)) {
                    moveAttachments($moved, $new_dir);
                }
                $new_dir = $modSettings['currentAttachmentUploadDir'];
                // Create / update the progress bar.
                // @todo why was this done this way?
                if (!$break) {
                    $percent_done = min(round($current_progress / $total_progress * 100, 0), 100);
                    $prog_bar = '
						<div class="progress_bar">
							<div class="full_bar">' . $percent_done . '%</div>
							<div class="green_percent" style="width: ' . $percent_done . '%;">&nbsp;</div>
						</div>';
                    // Write it to a file so it can be displayed
                    $fp = fopen(BOARDDIR . '/progress.php', 'w');
                    fwrite($fp, $prog_bar);
                    fclose($fp);
                    usleep(500000);
                }
            }
            $results[] = sprintf($txt['attachments_transfered'], $total_moved, $modSettings['attachmentUploadDir'][$new_dir]);
            if (!empty($total_not_moved)) {
                $results[] = sprintf($txt['attachments_not_transfered'], $total_not_moved);
            }
        }
        // All done, time to clean up
        $_SESSION['results'] = $results;
        if (file_exists(BOARDDIR . '/progress.php')) {
            unlink(BOARDDIR . '/progress.php');
        }
        redirectexit('action=admin;area=manageattachments;sa=maintenance#transfer');
    }
Exemplo n.º 2
0
/**
 * Create an attachment, with the given array of parameters.
 *
 * What it does:
 * - Adds any addtional or missing parameters to $attachmentOptions.
 * - Renames the temporary file.
 * - Creates a thumbnail if the file is an image and the option enabled.
 *
 * @package Attachments
 * @param mixed[] $attachmentOptions associative array of options
 */
function createAttachment(&$attachmentOptions)
{
    global $modSettings, $context;
    $db = database();
    require_once SUBSDIR . '/Graphics.subs.php';
    // These are the only valid image types.
    $validImageTypes = array(1 => 'gif', 2 => 'jpeg', 3 => 'png', 5 => 'psd', 6 => 'bmp', 7 => 'tiff', 8 => 'tiff', 9 => 'jpeg', 14 => 'iff');
    // If this is an image we need to set a few additional parameters.
    $size = @getimagesize($attachmentOptions['tmp_name']);
    list($attachmentOptions['width'], $attachmentOptions['height']) = $size;
    // If it's an image get the mime type right.
    if (empty($attachmentOptions['mime_type']) && $attachmentOptions['width']) {
        // Got a proper mime type?
        if (!empty($size['mime'])) {
            $attachmentOptions['mime_type'] = $size['mime'];
        } elseif (isset($validImageTypes[$size[2]])) {
            $attachmentOptions['mime_type'] = 'image/' . $validImageTypes[$size[2]];
        }
    }
    // It is possible we might have a MIME type that isn't actually an image but still have a size.
    // For example, Shockwave files will be able to return size but be 'application/shockwave' or similar.
    if (!empty($attachmentOptions['mime_type']) && strpos($attachmentOptions['mime_type'], 'image/') !== 0) {
        $attachmentOptions['width'] = 0;
        $attachmentOptions['height'] = 0;
    }
    // Get the hash if no hash has been given yet.
    if (empty($attachmentOptions['file_hash'])) {
        $attachmentOptions['file_hash'] = getAttachmentFilename($attachmentOptions['name'], 0, null, true);
    }
    // Assuming no-one set the extension let's take a look at it.
    if (empty($attachmentOptions['fileext'])) {
        $attachmentOptions['fileext'] = strtolower(strrpos($attachmentOptions['name'], '.') !== false ? substr($attachmentOptions['name'], strrpos($attachmentOptions['name'], '.') + 1) : '');
        if (strlen($attachmentOptions['fileext']) > 8 || '.' . $attachmentOptions['fileext'] == $attachmentOptions['name']) {
            $attachmentOptions['fileext'] = '';
        }
    }
    $db->insert('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'filename' => 'string-255', 'file_hash' => 'string-40', 'fileext' => 'string-8', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'mime_type' => 'string-20', 'approved' => 'int'), array((int) $attachmentOptions['id_folder'], (int) $attachmentOptions['post'], $attachmentOptions['name'], $attachmentOptions['file_hash'], $attachmentOptions['fileext'], (int) $attachmentOptions['size'], empty($attachmentOptions['width']) ? 0 : (int) $attachmentOptions['width'], empty($attachmentOptions['height']) ? '0' : (int) $attachmentOptions['height'], !empty($attachmentOptions['mime_type']) ? $attachmentOptions['mime_type'] : '', (int) $attachmentOptions['approved']), array('id_attach'));
    $attachmentOptions['id'] = $db->insert_id('{db_prefix}attachments', 'id_attach');
    // @todo Add an error here maybe?
    if (empty($attachmentOptions['id'])) {
        return false;
    }
    // Now that we have the attach id, let's rename this and finish up.
    $attachmentOptions['destination'] = getAttachmentFilename(basename($attachmentOptions['name']), $attachmentOptions['id'], $attachmentOptions['id_folder'], false, $attachmentOptions['file_hash']);
    rename($attachmentOptions['tmp_name'], $attachmentOptions['destination']);
    // If it's not approved then add to the approval queue.
    if (!$attachmentOptions['approved']) {
        $db->insert('', '{db_prefix}approval_queue', array('id_attach' => 'int', 'id_msg' => 'int'), array($attachmentOptions['id'], (int) $attachmentOptions['post']), array());
    }
    if (empty($modSettings['attachmentThumbnails']) || empty($attachmentOptions['width']) && empty($attachmentOptions['height'])) {
        return true;
    }
    // Like thumbnails, do we?
    if (!empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attachmentOptions['width'] > $modSettings['attachmentThumbWidth'] || $attachmentOptions['height'] > $modSettings['attachmentThumbHeight'])) {
        if (createThumbnail($attachmentOptions['destination'], $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) {
            // Figure out how big we actually made it.
            $size = @getimagesize($attachmentOptions['destination'] . '_thumb');
            list($thumb_width, $thumb_height) = $size;
            if (!empty($size['mime'])) {
                $thumb_mime = $size['mime'];
            } elseif (isset($validImageTypes[$size[2]])) {
                $thumb_mime = 'image/' . $validImageTypes[$size[2]];
            } else {
                $thumb_mime = '';
            }
            $thumb_filename = $attachmentOptions['name'] . '_thumb';
            $thumb_size = filesize($attachmentOptions['destination'] . '_thumb');
            $thumb_file_hash = getAttachmentFilename($thumb_filename, 0, null, true);
            $thumb_path = $attachmentOptions['destination'] . '_thumb';
            // We should check the file size and count here since thumbs are added to the existing totals.
            if (!empty($modSettings['automanage_attachments']) && $modSettings['automanage_attachments'] == 1 && !empty($modSettings['attachmentDirSizeLimit']) || !empty($modSettings['attachmentDirFileLimit'])) {
                $context['dir_size'] = isset($context['dir_size']) ? $context['dir_size'] += $thumb_size : ($context['dir_size'] = 0);
                $context['dir_files'] = isset($context['dir_files']) ? $context['dir_files']++ : ($context['dir_files'] = 0);
                // If the folder is full, try to create a new one and move the thumb to it.
                if ($context['dir_size'] > $modSettings['attachmentDirSizeLimit'] * 1024 || $context['dir_files'] + 2 > $modSettings['attachmentDirFileLimit']) {
                    if (automanage_attachments_by_space()) {
                        rename($thumb_path, $context['attach_dir'] . '/' . $thumb_filename);
                        $thumb_path = $context['attach_dir'] . '/' . $thumb_filename;
                        $context['dir_size'] = 0;
                        $context['dir_files'] = 0;
                    }
                }
            }
            // If a new folder has been already created. Gotta move this thumb there then.
            if ($modSettings['currentAttachmentUploadDir'] != $attachmentOptions['id_folder']) {
                rename($thumb_path, $context['attach_dir'] . '/' . $thumb_filename);
                $thumb_path = $context['attach_dir'] . '/' . $thumb_filename;
            }
            // To the database we go!
            $db->insert('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'attachment_type' => 'int', 'filename' => 'string-255', 'file_hash' => 'string-40', 'fileext' => 'string-8', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'mime_type' => 'string-20', 'approved' => 'int'), array($modSettings['currentAttachmentUploadDir'], (int) $attachmentOptions['post'], 3, $thumb_filename, $thumb_file_hash, $attachmentOptions['fileext'], $thumb_size, $thumb_width, $thumb_height, $thumb_mime, (int) $attachmentOptions['approved']), array('id_attach'));
            $attachmentOptions['thumb'] = $db->insert_id('{db_prefix}attachments', 'id_attach');
            if (!empty($attachmentOptions['thumb'])) {
                $db->query('', '
					UPDATE {db_prefix}attachments
					SET id_thumb = {int:id_thumb}
					WHERE id_attach = {int:id_attach}', array('id_thumb' => $attachmentOptions['thumb'], 'id_attach' => $attachmentOptions['id']));
                rename($thumb_path, getAttachmentFilename($thumb_filename, $attachmentOptions['thumb'], $modSettings['currentAttachmentUploadDir'], false, $thumb_file_hash));
            }
        }
    }
    return true;
}