Example #1
0
    /**
     * Parse Attachments
     */
    function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false)
    {
        global $config, $auth, $user, $phpbb_root_path, $phpEx, $db;
        $error = array();
        $num_attachments = sizeof($this->attachment_data);
        $this->filename_data['filecomment'] = utf8_normalize_nfc(request_var('filecomment', '', true));
        $upload_file = isset($_FILES[$form_name]) && $_FILES[$form_name]['name'] != 'none' && trim($_FILES[$form_name]['name']) ? true : false;
        $add_file = isset($_POST['add_file']) ? true : false;
        $delete_file = isset($_POST['delete_file']) ? true : false;
        // First of all adjust comments if changed
        $actual_comment_list = utf8_normalize_nfc(request_var('comment_list', array(''), true));
        foreach ($actual_comment_list as $comment_key => $comment) {
            if (!isset($this->attachment_data[$comment_key])) {
                continue;
            }
            if ($this->attachment_data[$comment_key]['attach_comment'] != $actual_comment_list[$comment_key]) {
                $this->attachment_data[$comment_key]['attach_comment'] = $actual_comment_list[$comment_key];
            }
        }
        $cfg = array();
        $cfg['max_attachments'] = $is_message ? $config['max_attachments_pm'] : $config['max_attachments'];
        $forum_id = $is_message ? 0 : $forum_id;
        if ($submit && in_array($mode, array('post', 'reply', 'quote', 'edit')) && $upload_file) {
            if ($num_attachments < $cfg['max_attachments'] || $auth->acl_get('a_') || $auth->acl_get('m_', $forum_id)) {
                $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message);
                $error = $filedata['error'];
                if ($filedata['post_attach'] && !sizeof($error)) {
                    $sql_ary = array('physical_filename' => $filedata['physical_filename'], 'attach_comment' => $this->filename_data['filecomment'], 'real_filename' => $filedata['real_filename'], 'extension' => $filedata['extension'], 'mimetype' => $filedata['mimetype'], 'filesize' => $filedata['filesize'], 'filetime' => $filedata['filetime'], 'thumbnail' => $filedata['thumbnail'], 'is_orphan' => 1, 'in_message' => $is_message ? 1 : 0, 'poster_id' => $user->data['user_id']);
                    $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
                    $new_entry = array('attach_id' => $db->sql_nextid(), 'is_orphan' => 1, 'real_filename' => $filedata['real_filename'], 'attach_comment' => $this->filename_data['filecomment']);
                    $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data);
                    $this->message = preg_replace('#\\[attachment=([0-9]+)\\](.*?)\\[\\/attachment\\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message);
                    $this->filename_data['filecomment'] = '';
                    // This Variable is set to false here, because Attachments are entered into the
                    // Database in two modes, one if the id_list is 0 and the second one if post_attach is true
                    // Since post_attach is automatically switched to true if an Attachment got added to the filesystem,
                    // but we are assigning an id of 0 here, we have to reset the post_attach variable to false.
                    //
                    // This is very relevant, because it could happen that the post got not submitted, but we do not
                    // know this circumstance here. We could be at the posting page or we could be redirected to the entered
                    // post. :)
                    $filedata['post_attach'] = false;
                }
            } else {
                $error[] = sprintf($user->lang['TOO_MANY_ATTACHMENTS'], $cfg['max_attachments']);
            }
        }
        if ($preview || $refresh || sizeof($error)) {
            // Perform actions on temporary attachments
            if ($delete_file) {
                include_once $phpbb_root_path . 'includes/functions_admin.' . $phpEx;
                $index = array_keys(request_var('delete_file', array(0 => 0)));
                $index = !empty($index) ? $index[0] : false;
                if ($index !== false && !empty($this->attachment_data[$index])) {
                    // delete selected attachment
                    if ($this->attachment_data[$index]['is_orphan']) {
                        $sql = 'SELECT attach_id, physical_filename, thumbnail
							FROM ' . ATTACHMENTS_TABLE . '
							WHERE attach_id = ' . (int) $this->attachment_data[$index]['attach_id'] . '
								AND is_orphan = 1
								AND poster_id = ' . $user->data['user_id'];
                        $result = $db->sql_query($sql);
                        $row = $db->sql_fetchrow($result);
                        $db->sql_freeresult($result);
                        if ($row) {
                            phpbb_unlink($row['physical_filename'], 'file');
                            if ($row['thumbnail']) {
                                phpbb_unlink($row['physical_filename'], 'thumbnail');
                            }
                            $db->sql_query('DELETE FROM ' . ATTACHMENTS_TABLE . ' WHERE attach_id = ' . (int) $this->attachment_data[$index]['attach_id']);
                        }
                    } else {
                        delete_attachments('attach', array(intval($this->attachment_data[$index]['attach_id'])));
                    }
                    unset($this->attachment_data[$index]);
                    $this->message = preg_replace('#\\[attachment=([0-9]+)\\](.*?)\\[\\/attachment\\]#e', "(\\1 == \$index) ? '' : ((\\1 > \$index) ? '[attachment=' . (\\1 - 1) . ']\\2[/attachment]' : '\\0')", $this->message);
                    // Reindex Array
                    $this->attachment_data = array_values($this->attachment_data);
                }
            } else {
                if (($add_file || $preview) && $upload_file) {
                    if ($num_attachments < $cfg['max_attachments'] || $auth->acl_gets('m_', 'a_', $forum_id)) {
                        $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message);
                        $error = array_merge($error, $filedata['error']);
                        if (!sizeof($error)) {
                            $sql_ary = array('physical_filename' => $filedata['physical_filename'], 'attach_comment' => $this->filename_data['filecomment'], 'real_filename' => $filedata['real_filename'], 'extension' => $filedata['extension'], 'mimetype' => $filedata['mimetype'], 'filesize' => $filedata['filesize'], 'filetime' => $filedata['filetime'], 'thumbnail' => $filedata['thumbnail'], 'is_orphan' => 1, 'in_message' => $is_message ? 1 : 0, 'poster_id' => $user->data['user_id']);
                            $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
                            $new_entry = array('attach_id' => $db->sql_nextid(), 'is_orphan' => 1, 'real_filename' => $filedata['real_filename'], 'attach_comment' => $this->filename_data['filecomment']);
                            $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data);
                            $this->message = preg_replace('#\\[attachment=([0-9]+)\\](.*?)\\[\\/attachment\\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message);
                            $this->filename_data['filecomment'] = '';
                        }
                    } else {
                        $error[] = sprintf($user->lang['TOO_MANY_ATTACHMENTS'], $cfg['max_attachments']);
                    }
                }
            }
        }
        foreach ($error as $error_msg) {
            $this->warn_msg[] = $error_msg;
        }
    }
/**
* Delete Attachments
*
* @param string $mode can be: post|message|topic|attach|user
* @param mixed $ids can be: post_ids, message_ids, topic_ids, attach_ids, user_ids
* @param bool $resync set this to false if you are deleting posts or topics
*/
function delete_attachments($mode, $ids, $resync = true)
{
    global $db, $config;
    if (is_array($ids) && sizeof($ids)) {
        $ids = array_unique($ids);
        $ids = array_map('intval', $ids);
    } else {
        $ids = array((int) $ids);
    }
    if (!sizeof($ids)) {
        return false;
    }
    switch ($mode) {
        case 'post':
        case 'message':
            $sql_id = 'post_msg_id';
            break;
        case 'topic':
            $sql_id = 'topic_id';
            break;
        case 'user':
            $sql_id = 'poster_id';
            break;
        case 'attach':
        default:
            $sql_id = 'attach_id';
            $mode = 'attach';
            break;
    }
    $post_ids = $message_ids = $topic_ids = $physical = array();
    // Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled)
    $sql = 'SELECT post_msg_id, topic_id, in_message, physical_filename, thumbnail, filesize, is_orphan
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set($sql_id, $ids);
    $result = $db->sql_query($sql);
    while ($row = $db->sql_fetchrow($result)) {
        // We only need to store post/message/topic ids if resync is enabled and the file is not orphaned
        if ($resync && !$row['is_orphan']) {
            if (!$row['in_message']) {
                $post_ids[] = $row['post_msg_id'];
                $topic_ids[] = $row['topic_id'];
            } else {
                $message_ids[] = $row['post_msg_id'];
            }
        }
        $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize'], 'is_orphan' => $row['is_orphan']);
    }
    $db->sql_freeresult($result);
    // Delete attachments
    $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . '
		WHERE ' . $db->sql_in_set($sql_id, $ids);
    $db->sql_query($sql);
    $num_deleted = $db->sql_affectedrows();
    if (!$num_deleted) {
        return 0;
    }
    // Delete attachments from filesystem
    $space_removed = $files_removed = 0;
    foreach ($physical as $file_ary) {
        if (phpbb_unlink($file_ary['filename'], 'file', true) && !$file_ary['is_orphan']) {
            // Only non-orphaned files count to the file size
            $space_removed += $file_ary['filesize'];
            $files_removed++;
        }
        if ($file_ary['thumbnail']) {
            phpbb_unlink($file_ary['filename'], 'thumbnail', true);
        }
    }
    if ($space_removed || $files_removed) {
        set_config('upload_dir_size', $config['upload_dir_size'] - $space_removed, true);
        set_config('num_files', $config['num_files'] - $files_removed, true);
    }
    // If we do not resync, we do not need to adjust any message, post, topic or user entries
    if (!$resync) {
        return $num_deleted;
    }
    // No more use for the original ids
    unset($ids);
    // Now, we need to resync posts, messages, topics. We go through every one of them
    $post_ids = array_unique($post_ids);
    $message_ids = array_unique($message_ids);
    $topic_ids = array_unique($topic_ids);
    // Update post indicators for posts now no longer having attachments
    if (sizeof($post_ids)) {
        $sql = 'UPDATE ' . POSTS_TABLE . '
			SET post_attachment = 0
			WHERE ' . $db->sql_in_set('post_id', $post_ids);
        $db->sql_query($sql);
    }
    // Update message table if messages are affected
    if (sizeof($message_ids)) {
        $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
			SET message_attachment = 0
			WHERE ' . $db->sql_in_set('msg_id', $message_ids);
        $db->sql_query($sql);
    }
    // Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic
    if (sizeof($topic_ids)) {
        // Just check which topics are still having an assigned attachment not orphaned by querying the attachments table (much less entries expected)
        $sql = 'SELECT topic_id
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
				AND is_orphan = 0';
        $result = $db->sql_query($sql);
        $remaining_ids = array();
        while ($row = $db->sql_fetchrow($result)) {
            $remaining_ids[] = $row['topic_id'];
        }
        $db->sql_freeresult($result);
        // Now only unset those ids remaining
        $topic_ids = array_diff($topic_ids, $remaining_ids);
        if (sizeof($topic_ids)) {
            $sql = 'UPDATE ' . TOPICS_TABLE . '
				SET topic_attachment = 0
				WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
            $db->sql_query($sql);
        }
    }
    return $num_deleted;
}
Example #3
0
    function main($id, $mode)
    {
        global $db, $user, $auth, $template, $cache;
        global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx;
        $user->add_lang(array('posting', 'viewtopic', 'acp/attachments'));
        $error = $notify = array();
        $submit = isset($_POST['submit']) ? true : false;
        $action = request_var('action', '');
        $form_key = 'acp_attach';
        add_form_key($form_key);
        if ($submit && !check_form_key($form_key)) {
            trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
        }
        switch ($mode) {
            case 'attach':
                $l_title = 'ACP_ATTACHMENT_SETTINGS';
                break;
            case 'extensions':
                $l_title = 'ACP_MANAGE_EXTENSIONS';
                break;
            case 'ext_groups':
                $l_title = 'ACP_EXTENSION_GROUPS';
                break;
            case 'orphan':
                $l_title = 'ACP_ORPHAN_ATTACHMENTS';
                break;
            default:
                trigger_error('NO_MODE', E_USER_ERROR);
                break;
        }
        $this->tpl_name = 'acp_attachments';
        $this->page_title = $l_title;
        $template->assign_vars(array('L_TITLE' => $user->lang[$l_title], 'L_TITLE_EXPLAIN' => $user->lang[$l_title . '_EXPLAIN'], 'U_ACTION' => $this->u_action));
        switch ($mode) {
            case 'attach':
                include_once $phpbb_root_path . 'includes/functions_posting.' . $phpEx;
                $sql = 'SELECT group_name, cat_id
					FROM ' . EXTENSION_GROUPS_TABLE . '
					WHERE cat_id > 0
					ORDER BY cat_id';
                $result = $db->sql_query($sql);
                $s_assigned_groups = array();
                while ($row = $db->sql_fetchrow($result)) {
                    $s_assigned_groups[$row['cat_id']][] = $row['group_name'];
                }
                $db->sql_freeresult($result);
                $l_legend_cat_images = $user->lang['SETTINGS_CAT_IMAGES'] . ' [' . $user->lang['ASSIGNED_GROUP'] . ': ' . (!empty($s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE]) ? implode(', ', $s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE]) : $user->lang['NO_EXT_GROUP']) . ']';
                $display_vars = array('title' => 'ACP_ATTACHMENT_SETTINGS', 'vars' => array('legend1' => 'ACP_ATTACHMENT_SETTINGS', 'img_max_width' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false), 'img_max_height' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false), 'img_link_width' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false), 'img_link_height' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int:0', 'type' => false, 'method' => false, 'explain' => false), 'allow_attachments' => array('lang' => 'ALLOW_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), 'upload_path' => array('lang' => 'UPLOAD_DIR', 'validate' => 'wpath', 'type' => 'text:25:100', 'explain' => true), 'display_order' => array('lang' => 'DISPLAY_ORDER', 'validate' => 'bool', 'type' => 'custom', 'method' => 'display_order', 'explain' => true), 'attachment_quota' => array('lang' => 'ATTACH_QUOTA', 'validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), 'max_filesize' => array('lang' => 'ATTACH_MAX_FILESIZE', 'validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), 'max_filesize_pm' => array('lang' => 'ATTACH_MAX_PM_FILESIZE', 'validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), 'max_attachments' => array('lang' => 'MAX_ATTACHMENTS', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => false), 'max_attachments_pm' => array('lang' => 'MAX_ATTACHMENTS_PM', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => false), 'secure_downloads' => array('lang' => 'SECURE_DOWNLOADS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'secure_allow_deny' => array('lang' => 'SECURE_ALLOW_DENY', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_allow_deny', 'explain' => true), 'secure_allow_empty_referer' => array('lang' => 'SECURE_EMPTY_REFERRER', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'check_attachment_content' => array('lang' => 'CHECK_CONTENT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'legend2' => $l_legend_cat_images, 'img_display_inlined' => array('lang' => 'DISPLAY_INLINED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'img_create_thumbnail' => array('lang' => 'CREATE_THUMBNAIL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'img_max_thumb_width' => array('lang' => 'MAX_THUMB_WIDTH', 'validate' => 'int', 'type' => 'text:7:15', 'explain' => true, 'append' => ' px'), 'img_min_thumb_filesize' => array('lang' => 'MIN_THUMB_FILESIZE', 'validate' => 'int', 'type' => 'text:7:15', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']), 'img_imagick' => array('lang' => 'IMAGICK_PATH', 'validate' => 'string', 'type' => 'text:20:200', 'explain' => true, 'append' => '&nbsp;&nbsp;<span>[ <a href="' . $this->u_action . '&amp;action=imgmagick">' . $user->lang['SEARCH_IMAGICK'] . '</a> ]</span>'), 'img_max' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' px'), 'img_link' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' px')));
                $this->new_config = $config;
                $cfg_array = isset($_REQUEST['config']) ? request_var('config', array('' => '')) : $this->new_config;
                $error = array();
                // We validate the complete config if whished
                validate_config_vars($display_vars['vars'], $cfg_array, $error);
                // Do not write values if there is an error
                if (sizeof($error)) {
                    $submit = false;
                }
                // We go through the display_vars to make sure no one is trying to set variables he/she is not allowed to...
                foreach ($display_vars['vars'] as $config_name => $null) {
                    if (!isset($cfg_array[$config_name]) || strpos($config_name, 'legend') !== false) {
                        continue;
                    }
                    $this->new_config[$config_name] = $config_value = $cfg_array[$config_name];
                    if (in_array($config_name, array('attachment_quota', 'max_filesize', 'max_filesize_pm'))) {
                        $size_var = request_var($config_name, '');
                        $this->new_config[$config_name] = $config_value = $size_var == 'kb' ? round($config_value * 1024) : ($size_var == 'mb' ? round($config_value * 1048576) : $config_value);
                    }
                    if ($submit) {
                        set_config($config_name, $config_value);
                    }
                }
                $this->perform_site_list();
                if ($submit) {
                    add_log('admin', 'LOG_CONFIG_ATTACH');
                    // Check Settings
                    $this->test_upload($error, $this->new_config['upload_path'], false);
                    if (!sizeof($error)) {
                        trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
                    }
                }
                $template->assign_var('S_ATTACHMENT_SETTINGS', true);
                if ($action == 'imgmagick') {
                    $this->new_config['img_imagick'] = $this->search_imagemagick();
                }
                // We strip eventually manual added convert program, we only want the patch
                if ($this->new_config['img_imagick']) {
                    // Change path separator
                    $this->new_config['img_imagick'] = str_replace('\\', '/', $this->new_config['img_imagick']);
                    $this->new_config['img_imagick'] = str_replace(array('convert', '.exe'), array('', ''), $this->new_config['img_imagick']);
                    // Check for trailing slash
                    if (substr($this->new_config['img_imagick'], -1) !== '/') {
                        $this->new_config['img_imagick'] .= '/';
                    }
                }
                $supported_types = get_supported_image_types();
                // Check Thumbnail Support
                if (!$this->new_config['img_imagick'] && (!isset($supported_types['format']) || !sizeof($supported_types['format']))) {
                    $this->new_config['img_create_thumbnail'] = 0;
                }
                $template->assign_vars(array('U_SEARCH_IMAGICK' => $this->u_action . '&amp;action=imgmagick', 'S_THUMBNAIL_SUPPORT' => !$this->new_config['img_imagick'] && (!isset($supported_types['format']) || !sizeof($supported_types['format'])) ? false : true));
                // Secure Download Options - Same procedure as with banning
                $allow_deny = $this->new_config['secure_allow_deny'] ? 'ALLOWED' : 'DISALLOWED';
                $sql = 'SELECT *
					FROM ' . SITELIST_TABLE;
                $result = $db->sql_query($sql);
                $defined_ips = '';
                $ips = array();
                while ($row = $db->sql_fetchrow($result)) {
                    $value = $row['site_ip'] ? $row['site_ip'] : $row['site_hostname'];
                    if ($value) {
                        $defined_ips .= '<option' . ($row['ip_exclude'] ? ' class="sep"' : '') . ' value="' . $row['site_id'] . '">' . $value . '</option>';
                        $ips[$row['site_id']] = $value;
                    }
                }
                $db->sql_freeresult($result);
                $template->assign_vars(array('S_SECURE_DOWNLOADS' => $this->new_config['secure_downloads'], 'S_DEFINED_IPS' => $defined_ips != '' ? true : false, 'S_WARNING' => sizeof($error) ? true : false, 'WARNING_MSG' => implode('<br />', $error), 'DEFINED_IPS' => $defined_ips, 'L_SECURE_TITLE' => $user->lang['DEFINE_' . $allow_deny . '_IPS'], 'L_IP_EXCLUDE' => $user->lang['EXCLUDE_FROM_' . $allow_deny . '_IP'], 'L_REMOVE_IPS' => $user->lang['REMOVE_' . $allow_deny . '_IPS']));
                // Output relevant options
                foreach ($display_vars['vars'] as $config_key => $vars) {
                    if (!is_array($vars) && strpos($config_key, 'legend') === false) {
                        continue;
                    }
                    if (strpos($config_key, 'legend') !== false) {
                        $template->assign_block_vars('options', array('S_LEGEND' => true, 'LEGEND' => isset($user->lang[$vars]) ? $user->lang[$vars] : $vars));
                        continue;
                    }
                    $type = explode(':', $vars['type']);
                    $l_explain = '';
                    if ($vars['explain'] && isset($vars['lang_explain'])) {
                        $l_explain = isset($user->lang[$vars['lang_explain']]) ? $user->lang[$vars['lang_explain']] : $vars['lang_explain'];
                    } else {
                        if ($vars['explain']) {
                            $l_explain = isset($user->lang[$vars['lang'] . '_EXPLAIN']) ? $user->lang[$vars['lang'] . '_EXPLAIN'] : '';
                        }
                    }
                    $content = build_cfg_template($type, $config_key, $this->new_config, $config_key, $vars);
                    if (empty($content)) {
                        continue;
                    }
                    $template->assign_block_vars('options', array('KEY' => $config_key, 'TITLE' => $user->lang[$vars['lang']], 'S_EXPLAIN' => $vars['explain'], 'TITLE_EXPLAIN' => $l_explain, 'CONTENT' => $content));
                    unset($display_vars['vars'][$config_key]);
                }
                break;
            case 'extensions':
                if ($submit || isset($_POST['add_extension_check'])) {
                    if ($submit) {
                        // Change Extensions ?
                        $extension_change_list = request_var('extension_change_list', array(0));
                        $group_select_list = request_var('group_select', array(0));
                        // Generate correct Change List
                        $extensions = array();
                        for ($i = 0, $size = sizeof($extension_change_list); $i < $size; $i++) {
                            $extensions[$extension_change_list[$i]]['group_id'] = $group_select_list[$i];
                        }
                        $sql = 'SELECT *
							FROM ' . EXTENSIONS_TABLE . '
							ORDER BY extension_id';
                        $result = $db->sql_query($sql);
                        while ($row = $db->sql_fetchrow($result)) {
                            if ($row['group_id'] != $extensions[$row['extension_id']]['group_id']) {
                                $sql = 'UPDATE ' . EXTENSIONS_TABLE . '
									SET group_id = ' . (int) $extensions[$row['extension_id']]['group_id'] . '
									WHERE extension_id = ' . $row['extension_id'];
                                $db->sql_query($sql);
                                add_log('admin', 'LOG_ATTACH_EXT_UPDATE', $row['extension']);
                            }
                        }
                        $db->sql_freeresult($result);
                        // Delete Extension?
                        $extension_id_list = request_var('extension_id_list', array(0));
                        if (sizeof($extension_id_list)) {
                            $sql = 'SELECT extension
								FROM ' . EXTENSIONS_TABLE . '
								WHERE ' . $db->sql_in_set('extension_id', $extension_id_list);
                            $result = $db->sql_query($sql);
                            $extension_list = '';
                            while ($row = $db->sql_fetchrow($result)) {
                                $extension_list .= $extension_list == '' ? $row['extension'] : ', ' . $row['extension'];
                            }
                            $db->sql_freeresult($result);
                            $sql = 'DELETE
								FROM ' . EXTENSIONS_TABLE . '
								WHERE ' . $db->sql_in_set('extension_id', $extension_id_list);
                            $db->sql_query($sql);
                            add_log('admin', 'LOG_ATTACH_EXT_DEL', $extension_list);
                        }
                    }
                    // Add Extension?
                    $add_extension = strtolower(request_var('add_extension', ''));
                    $add_extension_group = request_var('add_group_select', 0);
                    $add = isset($_POST['add_extension_check']) ? true : false;
                    if ($add_extension && $add) {
                        if (!sizeof($error)) {
                            $sql = 'SELECT extension_id
								FROM ' . EXTENSIONS_TABLE . "\n\t\t\t\t\t\t\t\tWHERE extension = '" . $db->sql_escape($add_extension) . "'";
                            $result = $db->sql_query($sql);
                            if ($row = $db->sql_fetchrow($result)) {
                                $error[] = sprintf($user->lang['EXTENSION_EXIST'], $add_extension);
                            }
                            $db->sql_freeresult($result);
                            if (!sizeof($error)) {
                                $sql_ary = array('group_id' => $add_extension_group, 'extension' => $add_extension);
                                $db->sql_query('INSERT INTO ' . EXTENSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
                                add_log('admin', 'LOG_ATTACH_EXT_ADD', $add_extension);
                            }
                        }
                    }
                    if (!sizeof($error)) {
                        $notify[] = $user->lang['EXTENSIONS_UPDATED'];
                    }
                    $cache->destroy('_extensions');
                }
                $template->assign_vars(array('S_EXTENSIONS' => true, 'ADD_EXTENSION' => isset($add_extension) ? $add_extension : '', 'GROUP_SELECT_OPTIONS' => isset($_POST['add_extension_check']) ? $this->group_select('add_group_select', $add_extension_group, 'extension_group') : $this->group_select('add_group_select', false, 'extension_group')));
                $sql = 'SELECT *
					FROM ' . EXTENSIONS_TABLE . '
					ORDER BY group_id, extension';
                $result = $db->sql_query($sql);
                if ($row = $db->sql_fetchrow($result)) {
                    $old_group_id = $row['group_id'];
                    do {
                        $s_spacer = false;
                        $current_group_id = $row['group_id'];
                        if ($old_group_id != $current_group_id) {
                            $s_spacer = true;
                            $old_group_id = $current_group_id;
                        }
                        $template->assign_block_vars('extensions', array('S_SPACER' => $s_spacer, 'EXTENSION_ID' => $row['extension_id'], 'EXTENSION' => $row['extension'], 'GROUP_OPTIONS' => $this->group_select('group_select[]', $row['group_id'])));
                    } while ($row = $db->sql_fetchrow($result));
                }
                $db->sql_freeresult($result);
                break;
            case 'ext_groups':
                $template->assign_var('S_EXTENSION_GROUPS', true);
                if ($submit) {
                    $action = request_var('action', '');
                    $group_id = request_var('g', 0);
                    if ($action != 'add' && $action != 'edit') {
                        trigger_error('NO_MODE', E_USER_ERROR);
                    }
                    if (!$group_id && $action == 'edit') {
                        trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
                    }
                    if ($group_id) {
                        $sql = 'SELECT *
							FROM ' . EXTENSION_GROUPS_TABLE . "\n\t\t\t\t\t\t\tWHERE group_id = {$group_id}";
                        $result = $db->sql_query($sql);
                        $ext_row = $db->sql_fetchrow($result);
                        $db->sql_freeresult($result);
                        if (!$ext_row) {
                            trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
                        }
                    } else {
                        $ext_row = array();
                    }
                    $group_name = utf8_normalize_nfc(request_var('group_name', '', true));
                    $new_group_name = $action == 'add' ? $group_name : ($ext_row['group_name'] != $group_name ? $group_name : '');
                    if (!$group_name) {
                        $error[] = $user->lang['NO_EXT_GROUP_NAME'];
                    }
                    // Check New Group Name
                    if ($new_group_name) {
                        $sql = 'SELECT group_id
							FROM ' . EXTENSION_GROUPS_TABLE . "\n\t\t\t\t\t\t\tWHERE LOWER(group_name) = '" . $db->sql_escape(utf8_strtolower($new_group_name)) . "'";
                        $result = $db->sql_query($sql);
                        if ($db->sql_fetchrow($result)) {
                            $error[] = sprintf($user->lang['EXTENSION_GROUP_EXIST'], $new_group_name);
                        }
                        $db->sql_freeresult($result);
                    }
                    if (!sizeof($error)) {
                        // Ok, build the update/insert array
                        $upload_icon = request_var('upload_icon', 'no_image');
                        $size_select = request_var('size_select', 'b');
                        $forum_select = request_var('forum_select', false);
                        $allowed_forums = request_var('allowed_forums', array(0));
                        $allow_in_pm = isset($_POST['allow_in_pm']) ? true : false;
                        $max_filesize = request_var('max_filesize', 0);
                        $max_filesize = $size_select == 'kb' ? round($max_filesize * 1024) : ($size_select == 'mb' ? round($max_filesize * 1048576) : $max_filesize);
                        $allow_group = isset($_POST['allow_group']) ? true : false;
                        if ($max_filesize == $config['max_filesize']) {
                            $max_filesize = 0;
                        }
                        if (!sizeof($allowed_forums)) {
                            $forum_select = false;
                        }
                        $group_ary = array('group_name' => $group_name, 'cat_id' => request_var('special_category', ATTACHMENT_CATEGORY_NONE), 'allow_group' => $allow_group ? 1 : 0, 'upload_icon' => $upload_icon == 'no_image' ? '' : $upload_icon, 'max_filesize' => $max_filesize, 'allowed_forums' => $forum_select ? serialize($allowed_forums) : '', 'allow_in_pm' => $allow_in_pm ? 1 : 0);
                        if ($action == 'add') {
                            $group_ary['download_mode'] = INLINE_LINK;
                        }
                        $sql = $action == 'add' ? 'INSERT INTO ' . EXTENSION_GROUPS_TABLE . ' ' : 'UPDATE ' . EXTENSION_GROUPS_TABLE . ' SET ';
                        $sql .= $db->sql_build_array($action == 'add' ? 'INSERT' : 'UPDATE', $group_ary);
                        $sql .= $action == 'edit' ? " WHERE group_id = {$group_id}" : '';
                        $db->sql_query($sql);
                        if ($action == 'add') {
                            $group_id = $db->sql_nextid();
                        }
                        add_log('admin', 'LOG_ATTACH_EXTGROUP_' . strtoupper($action), $group_name);
                    }
                    $extension_list = request_var('extensions', array(0));
                    if ($action == 'edit' && sizeof($extension_list)) {
                        $sql = 'UPDATE ' . EXTENSIONS_TABLE . "\n\t\t\t\t\t\t\tSET group_id = 0\n\t\t\t\t\t\t\tWHERE group_id = {$group_id}";
                        $db->sql_query($sql);
                    }
                    if (sizeof($extension_list)) {
                        $sql = 'UPDATE ' . EXTENSIONS_TABLE . "\n\t\t\t\t\t\t\tSET group_id = {$group_id}\n\t\t\t\t\t\t\tWHERE " . $db->sql_in_set('extension_id', $extension_list);
                        $db->sql_query($sql);
                    }
                    $cache->destroy('_extensions');
                    if (!sizeof($error)) {
                        $notify[] = $user->lang['SUCCESS_EXTENSION_GROUP_' . strtoupper($action)];
                    }
                }
                $cat_lang = array(ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'], ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'], ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'], ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'], ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'], ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES']);
                $group_id = request_var('g', 0);
                $action = isset($_POST['add']) ? 'add' : $action;
                switch ($action) {
                    case 'delete':
                        if (confirm_box(true)) {
                            $sql = 'SELECT group_name
								FROM ' . EXTENSION_GROUPS_TABLE . "\n\t\t\t\t\t\t\t\tWHERE group_id = {$group_id}";
                            $result = $db->sql_query($sql);
                            $group_name = (string) $db->sql_fetchfield('group_name');
                            $db->sql_freeresult($result);
                            $sql = 'DELETE
								FROM ' . EXTENSION_GROUPS_TABLE . "\n\t\t\t\t\t\t\t\tWHERE group_id = {$group_id}";
                            $db->sql_query($sql);
                            // Set corresponding Extensions to a pending Group
                            $sql = 'UPDATE ' . EXTENSIONS_TABLE . "\n\t\t\t\t\t\t\t\tSET group_id = 0\n\t\t\t\t\t\t\t\tWHERE group_id = {$group_id}";
                            $db->sql_query($sql);
                            add_log('admin', 'LOG_ATTACH_EXTGROUP_DEL', $group_name);
                            $cache->destroy('_extensions');
                            trigger_error($user->lang['EXTENSION_GROUP_DELETED'] . adm_back_link($this->u_action));
                        } else {
                            confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array('i' => $id, 'mode' => $mode, 'group_id' => $group_id, 'action' => 'delete')));
                        }
                        break;
                    case 'edit':
                        if (!$group_id) {
                            trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
                        }
                        $sql = 'SELECT *
							FROM ' . EXTENSION_GROUPS_TABLE . "\n\t\t\t\t\t\t\tWHERE group_id = {$group_id}";
                        $result = $db->sql_query($sql);
                        $ext_group_row = $db->sql_fetchrow($result);
                        $db->sql_freeresult($result);
                        $forum_ids = !$ext_group_row['allowed_forums'] ? array() : unserialize(trim($ext_group_row['allowed_forums']));
                        // no break;
                    // no break;
                    case 'add':
                        if ($action == 'add') {
                            $ext_group_row = array('group_name' => utf8_normalize_nfc(request_var('group_name', '', true)), 'cat_id' => 0, 'allow_group' => 1, 'allow_in_pm' => 1, 'upload_icon' => '', 'max_filesize' => 0);
                            $forum_ids = array();
                        }
                        $extensions = array();
                        $sql = 'SELECT *
							FROM ' . EXTENSIONS_TABLE . "\n\t\t\t\t\t\t\tWHERE group_id = {$group_id}\n\t\t\t\t\t\t\t\tOR group_id = 0\n\t\t\t\t\t\t\tORDER BY extension";
                        $result = $db->sql_query($sql);
                        $extensions = $db->sql_fetchrowset($result);
                        $db->sql_freeresult($result);
                        if ($ext_group_row['max_filesize'] == 0) {
                            $ext_group_row['max_filesize'] = (int) $config['max_filesize'];
                        }
                        $size_format = $ext_group_row['max_filesize'] >= 1048576 ? 'mb' : ($ext_group_row['max_filesize'] >= 1024 ? 'kb' : 'b');
                        $ext_group_row['max_filesize'] = get_formatted_filesize($ext_group_row['max_filesize'], false);
                        $img_path = $config['upload_icons_path'];
                        $filename_list = '';
                        $no_image_select = false;
                        $imglist = filelist($phpbb_root_path . $img_path);
                        if (sizeof($imglist)) {
                            $imglist = array_values($imglist);
                            $imglist = $imglist[0];
                            foreach ($imglist as $key => $img) {
                                if (!$ext_group_row['upload_icon']) {
                                    $no_image_select = true;
                                    $selected = '';
                                } else {
                                    $selected = $ext_group_row['upload_icon'] == $img ? ' selected="selected"' : '';
                                }
                                if (strlen($img) > 255) {
                                    continue;
                                }
                                $filename_list .= '<option value="' . htmlspecialchars($img) . '"' . $selected . '>' . htmlspecialchars($img) . '</option>';
                            }
                        }
                        $i = 0;
                        $assigned_extensions = '';
                        foreach ($extensions as $num => $row) {
                            if ($row['group_id'] == $group_id && $group_id) {
                                $assigned_extensions .= $i ? ', ' . $row['extension'] : $row['extension'];
                                $i++;
                            }
                        }
                        $s_extension_options = '';
                        foreach ($extensions as $row) {
                            $s_extension_options .= '<option' . (!$row['group_id'] ? ' class="disabled"' : '') . ' value="' . $row['extension_id'] . '"' . ($row['group_id'] == $group_id && $group_id ? ' selected="selected"' : '') . '>' . $row['extension'] . '</option>';
                        }
                        $template->assign_vars(array('PHPBB_ROOT_PATH' => $phpbb_root_path, 'IMG_PATH' => $img_path, 'ACTION' => $action, 'GROUP_ID' => $group_id, 'GROUP_NAME' => $ext_group_row['group_name'], 'ALLOW_GROUP' => $ext_group_row['allow_group'], 'ALLOW_IN_PM' => $ext_group_row['allow_in_pm'], 'UPLOAD_ICON_SRC' => $phpbb_root_path . $img_path . '/' . $ext_group_row['upload_icon'], 'EXTGROUP_FILESIZE' => $ext_group_row['max_filesize'], 'ASSIGNED_EXTENSIONS' => $assigned_extensions, 'S_CATEGORY_SELECT' => $this->category_select('special_category', $group_id, 'category'), 'S_EXT_GROUP_SIZE_OPTIONS' => size_select_options($size_format), 'S_EXTENSION_OPTIONS' => $s_extension_options, 'S_FILENAME_LIST' => $filename_list, 'S_EDIT_GROUP' => true, 'S_NO_IMAGE' => $no_image_select, 'S_FORUM_IDS' => sizeof($forum_ids) ? true : false, 'U_EXTENSIONS' => append_sid("{$phpbb_admin_path}index.{$phpEx}", "i={$id}&amp;mode=extensions"), 'U_BACK' => $this->u_action, 'L_LEGEND' => $user->lang[strtoupper($action) . '_EXTENSION_GROUP']));
                        $s_forum_id_options = '';
                        /** @todo use in-built function **/
                        $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id
							FROM ' . FORUMS_TABLE . '
							ORDER BY left_id ASC';
                        $result = $db->sql_query($sql, 600);
                        $right = $cat_right = $padding_inc = 0;
                        $padding = $forum_list = $holding = '';
                        $padding_store = array('0' => '');
                        while ($row = $db->sql_fetchrow($result)) {
                            if ($row['forum_type'] == FORUM_CAT && $row['left_id'] + 1 == $row['right_id']) {
                                // Non-postable forum with no subforums, don't display
                                continue;
                            }
                            if (!$auth->acl_get('f_list', $row['forum_id'])) {
                                // if the user does not have permissions to list this forum skip
                                continue;
                            }
                            if ($row['left_id'] < $right) {
                                $padding .= '&nbsp; &nbsp;';
                                $padding_store[$row['parent_id']] = $padding;
                            } else {
                                if ($row['left_id'] > $right + 1) {
                                    $padding = empty($padding_store[$row['parent_id']]) ? '' : $padding_store[$row['parent_id']];
                                }
                            }
                            $right = $row['right_id'];
                            $selected = in_array($row['forum_id'], $forum_ids) ? ' selected="selected"' : '';
                            if ($row['left_id'] > $cat_right) {
                                // make sure we don't forget anything
                                $s_forum_id_options .= $holding;
                                $holding = '';
                            }
                            if ($row['right_id'] - $row['left_id'] > 1) {
                                $cat_right = max($cat_right, $row['right_id']);
                                $holding .= '<option value="' . $row['forum_id'] . '"' . ($row['forum_type'] == FORUM_POST ? ' class="sep"' : '') . $selected . '>' . $padding . $row['forum_name'] . '</option>';
                            } else {
                                $s_forum_id_options .= $holding . '<option value="' . $row['forum_id'] . '"' . ($row['forum_type'] == FORUM_POST ? ' class="sep"' : '') . $selected . '>' . $padding . $row['forum_name'] . '</option>';
                                $holding = '';
                            }
                        }
                        if ($holding) {
                            $s_forum_id_options .= $holding;
                        }
                        $db->sql_freeresult($result);
                        unset($padding_store);
                        $template->assign_vars(array('S_FORUM_ID_OPTIONS' => $s_forum_id_options));
                        break;
                }
                $sql = 'SELECT *
					FROM ' . EXTENSION_GROUPS_TABLE . '
					ORDER BY allow_group DESC, allow_in_pm DESC, group_name';
                $result = $db->sql_query($sql);
                $old_allow_group = $old_allow_pm = 1;
                while ($row = $db->sql_fetchrow($result)) {
                    $s_add_spacer = $old_allow_group != $row['allow_group'] || $old_allow_pm != $row['allow_in_pm'] ? true : false;
                    $template->assign_block_vars('groups', array('S_ADD_SPACER' => $s_add_spacer, 'S_ALLOWED_IN_PM' => $row['allow_in_pm'] ? true : false, 'S_GROUP_ALLOWED' => $row['allow_group'] ? true : false, 'U_EDIT' => $this->u_action . "&amp;action=edit&amp;g={$row['group_id']}", 'U_DELETE' => $this->u_action . "&amp;action=delete&amp;g={$row['group_id']}", 'GROUP_NAME' => $row['group_name'], 'CATEGORY' => $cat_lang[$row['cat_id']]));
                    $old_allow_group = $row['allow_group'];
                    $old_allow_pm = $row['allow_in_pm'];
                }
                $db->sql_freeresult($result);
                break;
            case 'orphan':
                if ($submit) {
                    $delete_files = isset($_POST['delete']) ? array_keys(request_var('delete', array('' => 0))) : array();
                    $add_files = isset($_POST['add']) ? array_keys(request_var('add', array('' => 0))) : array();
                    $post_ids = request_var('post_id', array('' => 0));
                    if (sizeof($delete_files)) {
                        $sql = 'SELECT *
							FROM ' . ATTACHMENTS_TABLE . '
							WHERE ' . $db->sql_in_set('attach_id', $delete_files) . '
								AND is_orphan = 1';
                        $result = $db->sql_query($sql);
                        $delete_files = array();
                        while ($row = $db->sql_fetchrow($result)) {
                            phpbb_unlink($row['physical_filename'], 'file');
                            if ($row['thumbnail']) {
                                phpbb_unlink($row['physical_filename'], 'thumbnail');
                            }
                            $delete_files[$row['attach_id']] = $row['real_filename'];
                        }
                        $db->sql_freeresult($result);
                    }
                    if (sizeof($delete_files)) {
                        $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . '
							WHERE ' . $db->sql_in_set('attach_id', array_keys($delete_files));
                        $db->sql_query($sql);
                        add_log('admin', 'LOG_ATTACH_ORPHAN_DEL', implode(', ', $delete_files));
                        $notify[] = sprintf($user->lang['LOG_ATTACH_ORPHAN_DEL'], implode(', ', $delete_files));
                    }
                    $upload_list = array();
                    foreach ($add_files as $attach_id) {
                        if (!isset($delete_files[$attach_id]) && !empty($post_ids[$attach_id])) {
                            $upload_list[$attach_id] = $post_ids[$attach_id];
                        }
                    }
                    unset($add_files);
                    if (sizeof($upload_list)) {
                        $template->assign_var('S_UPLOADING_FILES', true);
                        $sql = 'SELECT forum_id, forum_name
							FROM ' . FORUMS_TABLE;
                        $result = $db->sql_query($sql);
                        $forum_names = array();
                        while ($row = $db->sql_fetchrow($result)) {
                            $forum_names[$row['forum_id']] = $row['forum_name'];
                        }
                        $db->sql_freeresult($result);
                        $sql = 'SELECT forum_id, topic_id, post_id, poster_id
							FROM ' . POSTS_TABLE . '
							WHERE ' . $db->sql_in_set('post_id', $upload_list);
                        $result = $db->sql_query($sql);
                        $post_info = array();
                        while ($row = $db->sql_fetchrow($result)) {
                            $post_info[$row['post_id']] = $row;
                        }
                        $db->sql_freeresult($result);
                        // Select those attachments we want to change...
                        $sql = 'SELECT *
							FROM ' . ATTACHMENTS_TABLE . '
							WHERE ' . $db->sql_in_set('attach_id', array_keys($upload_list)) . '
								AND is_orphan = 1';
                        $result = $db->sql_query($sql);
                        $files_added = $space_taken = 0;
                        while ($row = $db->sql_fetchrow($result)) {
                            $post_row = $post_info[$upload_list[$row['attach_id']]];
                            $template->assign_block_vars('upload', array('FILE_INFO' => sprintf($user->lang['UPLOADING_FILE_TO'], $row['real_filename'], $post_row['post_id']), 'S_DENIED' => !$auth->acl_get('f_attach', $post_row['forum_id']) ? true : false, 'L_DENIED' => !$auth->acl_get('f_attach', $post_row['forum_id']) ? sprintf($user->lang['UPLOAD_DENIED_FORUM'], $forum_names[$row['forum_id']]) : ''));
                            if (!$auth->acl_get('f_attach', $post_row['forum_id'])) {
                                continue;
                            }
                            // Adjust attachment entry
                            $sql_ary = array('in_message' => 0, 'is_orphan' => 0, 'poster_id' => $post_row['poster_id'], 'post_msg_id' => $post_row['post_id'], 'topic_id' => $post_row['topic_id']);
                            $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
								SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
								WHERE attach_id = ' . $row['attach_id'];
                            $db->sql_query($sql);
                            $sql = 'UPDATE ' . POSTS_TABLE . '
								SET post_attachment = 1
								WHERE post_id = ' . $post_row['post_id'];
                            $db->sql_query($sql);
                            $sql = 'UPDATE ' . TOPICS_TABLE . '
								SET topic_attachment = 1
								WHERE topic_id = ' . $post_row['topic_id'];
                            $db->sql_query($sql);
                            $space_taken += $row['filesize'];
                            $files_added++;
                            add_log('admin', 'LOG_ATTACH_FILEUPLOAD', $post_row['post_id'], $row['real_filename']);
                        }
                        $db->sql_freeresult($result);
                        if ($files_added) {
                            set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true);
                            set_config('num_files', $config['num_files'] + $files_added, true);
                        }
                    }
                }
                $template->assign_vars(array('S_ORPHAN' => true));
                // Just get the files with is_orphan set and older than 3 hours
                $sql = 'SELECT *
					FROM ' . ATTACHMENTS_TABLE . '
					WHERE is_orphan = 1
						AND filetime < ' . (time() - 3 * 60 * 60) . '
					ORDER BY filetime DESC';
                $result = $db->sql_query($sql);
                while ($row = $db->sql_fetchrow($result)) {
                    $template->assign_block_vars('orphan', array('FILESIZE' => get_formatted_filesize($row['filesize']), 'FILETIME' => $user->format_date($row['filetime']), 'REAL_FILENAME' => basename($row['real_filename']), 'PHYSICAL_FILENAME' => basename($row['physical_filename']), 'ATTACH_ID' => $row['attach_id'], 'POST_IDS' => !empty($post_ids[$row['attach_id']]) ? $post_ids[$row['attach_id']] : '', 'U_FILE' => append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'mode=view&amp;id=' . $row['attach_id'])));
                }
                $db->sql_freeresult($result);
                break;
        }
        if (sizeof($error)) {
            $template->assign_vars(array('S_WARNING' => true, 'WARNING_MSG' => implode('<br />', $error)));
        }
        if (sizeof($notify)) {
            $template->assign_vars(array('S_NOTIFY' => true, 'NOTIFY_MSG' => implode('<br />', $notify)));
        }
    }
Example #4
0
    /**
     * Parse Attachments
     */
    function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false)
    {
        global $config, $auth, $user, $phpbb_root_path, $phpEx, $db, $request;
        $error = array();
        $num_attachments = sizeof($this->attachment_data);
        $this->filename_data['filecomment'] = $request->variable('filecomment', '', true);
        $upload = $request->file($form_name);
        $upload_file = !empty($upload) && $upload['name'] !== 'none' && trim($upload['name']);
        $add_file = isset($_POST['add_file']) ? true : false;
        $delete_file = isset($_POST['delete_file']) ? true : false;
        // First of all adjust comments if changed
        $actual_comment_list = $request->variable('comment_list', array(''), true);
        foreach ($actual_comment_list as $comment_key => $comment) {
            if (!isset($this->attachment_data[$comment_key])) {
                continue;
            }
            if ($this->attachment_data[$comment_key]['attach_comment'] != $actual_comment_list[$comment_key]) {
                $this->attachment_data[$comment_key]['attach_comment'] = $actual_comment_list[$comment_key];
            }
        }
        $cfg = array();
        $cfg['max_attachments'] = $is_message ? $config['max_attachments_pm'] : $config['max_attachments'];
        $forum_id = $is_message ? 0 : $forum_id;
        if ($submit && in_array($mode, array('post', 'reply', 'quote', 'edit')) && $upload_file) {
            if ($num_attachments < $cfg['max_attachments'] || $auth->acl_get('a_') || $auth->acl_get('m_', $forum_id)) {
                $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message);
                $error = $filedata['error'];
                if ($filedata['post_attach'] && !sizeof($error)) {
                    $sql_ary = array('physical_filename' => $filedata['physical_filename'], 'attach_comment' => $this->filename_data['filecomment'], 'real_filename' => $filedata['real_filename'], 'extension' => $filedata['extension'], 'mimetype' => $filedata['mimetype'], 'filesize' => $filedata['filesize'], 'filetime' => $filedata['filetime'], 'thumbnail' => $filedata['thumbnail'], 'is_orphan' => 1, 'in_message' => $is_message ? 1 : 0, 'poster_id' => $user->data['user_id']);
                    $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
                    $new_entry = array('attach_id' => $db->sql_nextid(), 'is_orphan' => 1, 'real_filename' => $filedata['real_filename'], 'attach_comment' => $this->filename_data['filecomment'], 'filesize' => $filedata['filesize']);
                    $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data);
                    $this->message = preg_replace_callback('#\\[attachment=([0-9]+)\\](.*?)\\[\\/attachment\\]#', function ($match) {
                        return '[attachment=' . ($match[1] + 1) . ']' . $match[2] . '[/attachment]';
                    }, $this->message);
                    $this->filename_data['filecomment'] = '';
                    // This Variable is set to false here, because Attachments are entered into the
                    // Database in two modes, one if the id_list is 0 and the second one if post_attach is true
                    // Since post_attach is automatically switched to true if an Attachment got added to the filesystem,
                    // but we are assigning an id of 0 here, we have to reset the post_attach variable to false.
                    //
                    // This is very relevant, because it could happen that the post got not submitted, but we do not
                    // know this circumstance here. We could be at the posting page or we could be redirected to the entered
                    // post. :)
                    $filedata['post_attach'] = false;
                }
            } else {
                $error[] = $user->lang('TOO_MANY_ATTACHMENTS', (int) $cfg['max_attachments']);
            }
        }
        if ($preview || $refresh || sizeof($error)) {
            if (isset($this->plupload) && $this->plupload->is_active()) {
                $json_response = new \phpbb\json_response();
            }
            // Perform actions on temporary attachments
            if ($delete_file) {
                include_once $phpbb_root_path . 'includes/functions_admin.' . $phpEx;
                $index = array_keys($request->variable('delete_file', array(0 => 0)));
                $index = !empty($index) ? $index[0] : false;
                if ($index !== false && !empty($this->attachment_data[$index])) {
                    // delete selected attachment
                    if ($this->attachment_data[$index]['is_orphan']) {
                        $sql = 'SELECT attach_id, physical_filename, thumbnail
							FROM ' . ATTACHMENTS_TABLE . '
							WHERE attach_id = ' . (int) $this->attachment_data[$index]['attach_id'] . '
								AND is_orphan = 1
								AND poster_id = ' . $user->data['user_id'];
                        $result = $db->sql_query($sql);
                        $row = $db->sql_fetchrow($result);
                        $db->sql_freeresult($result);
                        if ($row) {
                            phpbb_unlink($row['physical_filename'], 'file');
                            if ($row['thumbnail']) {
                                phpbb_unlink($row['physical_filename'], 'thumbnail');
                            }
                            $db->sql_query('DELETE FROM ' . ATTACHMENTS_TABLE . ' WHERE attach_id = ' . (int) $this->attachment_data[$index]['attach_id']);
                        }
                    } else {
                        delete_attachments('attach', array(intval($this->attachment_data[$index]['attach_id'])));
                    }
                    unset($this->attachment_data[$index]);
                    $this->message = preg_replace_callback('#\\[attachment=([0-9]+)\\](.*?)\\[\\/attachment\\]#', function ($match) use($index) {
                        return $match[1] == $index ? '' : ($match[1] > $index ? '[attachment=' . ($match[1] - 1) . ']' . $match[2] . '[/attachment]' : $match[0]);
                    }, $this->message);
                    // Reindex Array
                    $this->attachment_data = array_values($this->attachment_data);
                    if (isset($this->plupload) && $this->plupload->is_active()) {
                        $json_response->send($this->attachment_data);
                    }
                }
            } else {
                if (($add_file || $preview) && $upload_file) {
                    if ($num_attachments < $cfg['max_attachments'] || $auth->acl_gets('m_', 'a_', $forum_id)) {
                        $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message, false, $this->mimetype_guesser, $this->plupload);
                        $error = array_merge($error, $filedata['error']);
                        if (!sizeof($error)) {
                            $sql_ary = array('physical_filename' => $filedata['physical_filename'], 'attach_comment' => $this->filename_data['filecomment'], 'real_filename' => $filedata['real_filename'], 'extension' => $filedata['extension'], 'mimetype' => $filedata['mimetype'], 'filesize' => $filedata['filesize'], 'filetime' => $filedata['filetime'], 'thumbnail' => $filedata['thumbnail'], 'is_orphan' => 1, 'in_message' => $is_message ? 1 : 0, 'poster_id' => $user->data['user_id']);
                            $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
                            $new_entry = array('attach_id' => $db->sql_nextid(), 'is_orphan' => 1, 'real_filename' => $filedata['real_filename'], 'attach_comment' => $this->filename_data['filecomment'], 'filesize' => $filedata['filesize']);
                            $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data);
                            $this->message = preg_replace_callback('#\\[attachment=([0-9]+)\\](.*?)\\[\\/attachment\\]#', function ($match) {
                                return '[attachment=' . ($match[1] + 1) . ']' . $match[2] . '[/attachment]';
                            }, $this->message);
                            $this->filename_data['filecomment'] = '';
                            if (isset($this->plupload) && $this->plupload->is_active()) {
                                $download_url = append_sid("{$phpbb_root_path}download/file.{$phpEx}", 'mode=view&amp;id=' . $new_entry['attach_id']);
                                // Send the client the attachment data to maintain state
                                $json_response->send(array('data' => $this->attachment_data, 'download_url' => $download_url));
                            }
                        }
                    } else {
                        $error[] = $user->lang('TOO_MANY_ATTACHMENTS', (int) $cfg['max_attachments']);
                    }
                    if (!empty($error) && isset($this->plupload) && $this->plupload->is_active()) {
                        // If this is a plupload (and thus ajax) request, give the
                        // client the first error we have
                        $json_response->send(array('jsonrpc' => '2.0', 'id' => 'id', 'error' => array('code' => 105, 'message' => current($error))));
                    }
                }
            }
        }
        foreach ($error as $error_msg) {
            $this->warn_msg[] = $error_msg;
        }
    }
function delete_attachments($mode, $ids, $resync = TRUE)
{
    global $_CLASS, $config;
    if (is_array($ids)) {
        $ids = array_unique($ids);
    }
    if (!sizeof($ids)) {
        return false;
    }
    $sql_id = $mode == 'user' ? 'poster_id' : ($mode == 'post' ? 'post_msg_id' : ($mode == 'topic' ? 'topic_id' : 'attach_id'));
    $post_ids = $topic_ids = $physical = array();
    // Collect post and topics ids for later use
    if ($mode == 'attach' || $mode == 'user' || $mode == 'topic' && $resync) {
        $sql = 'SELECT post_msg_id as post_id, topic_id, physical_filename, thumbnail, filesize
			FROM ' . FORUMS_ATTACHMENTS_TABLE . '
			WHERE ' . $sql_id . ' IN (' . implode(', ', $ids) . ')';
        $result = $_CLASS['core_db']->query($sql);
        while ($row = $_CLASS['core_db']->fetch_row_assoc($result)) {
            $post_ids[] = $row['post_id'];
            $topic_ids[] = $row['topic_id'];
            $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize']);
        }
        $_CLASS['core_db']->free_result($result);
    }
    if ($mode == 'post') {
        $sql = 'SELECT topic_id, physical_filename, thumbnail, filesize
			FROM ' . FORUMS_ATTACHMENTS_TABLE . '
			WHERE post_msg_id IN (' . implode(', ', $ids) . ')
				AND in_message = 0';
        $result = $_CLASS['core_db']->query($sql);
        while ($row = $_CLASS['core_db']->fetch_row_assoc($result)) {
            $topic_ids[] = $row['topic_id'];
            $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize']);
        }
        $_CLASS['core_db']->free_result($result);
    }
    // Delete attachments
    $_CLASS['core_db']->query('DELETE FROM ' . FORUMS_ATTACHMENTS_TABLE . ' WHERE ' . $sql_id . ' IN (' . implode(', ', $ids) . ')');
    $num_deleted = $_CLASS['core_db']->affected_rows();
    if (!$num_deleted) {
        return 0;
    }
    // Delete attachments from filesystem
    $space_removed = $files_removed = 0;
    foreach ($physical as $file_ary) {
        if (phpbb_unlink($file_ary['filename'], 'file')) {
            $space_removed += $file_ary['filesize'];
            $files_removed++;
        }
        if ($file_ary['thumbnail']) {
            phpbb_unlink($file_ary['filename'], 'thumbnail');
        }
    }
    set_config('upload_dir_size', $config['upload_dir_size'] - $space_removed, true);
    set_config('num_files', $config['num_files'] - $files_removed, true);
    if ($mode == 'topic' && !$resync) {
        return $num_deleted;
    }
    if ($mode == 'post') {
        $post_ids = $ids;
    }
    unset($ids);
    $post_ids = array_unique($post_ids);
    $topic_ids = array_unique($topic_ids);
    // Update post indicators
    if (sizeof($post_ids)) {
        if ($mode == 'post' || $mode == 'topic') {
            $_CLASS['core_db']->query('UPDATE ' . FORUMS_POSTS_TABLE . ' 
				SET post_attachment = 0
				WHERE post_id IN (' . implode(', ', $post_ids) . ')');
        }
        if ($mode == 'user' || $mode == 'attach') {
            $remaining = array();
            $sql = 'SELECT post_msg_id
					FROM ' . FORUMS_ATTACHMENTS_TABLE . ' 
					WHERE post_msg_id IN (' . implode(', ', $post_ids) . ')
						AND in_message = 0';
            $result = $_CLASS['core_db']->query($sql);
            while ($row = $_CLASS['core_db']->fetch_row_assoc($result)) {
                $remaining[] = $row['post_msg_id'];
            }
            $_CLASS['core_db']->free_result($result);
            $unset_ids = array_diff($post_ids, $remaining);
            if (sizeof($unset_ids)) {
                $_CLASS['core_db']->query('UPDATE ' . FORUMS_POSTS_TABLE . ' 
					SET post_attachment = 0
					WHERE post_id IN (' . implode(', ', $unset_ids) . ')');
            }
            $remaining = array();
            $sql = 'SELECT post_msg_id
					FROM ' . FORUMS_ATTACHMENTS_TABLE . ' 
					WHERE post_msg_id IN (' . implode(', ', $post_ids) . ')
						AND in_message = 1';
            $result = $_CLASS['core_db']->query($sql);
            while ($row = $_CLASS['core_db']->fetch_row_assoc($result)) {
                $remaining[] = $row['post_msg_id'];
            }
            $_CLASS['core_db']->free_result($result);
            $unset_ids = array_diff($post_ids, $remaining);
            if (sizeof($unset_ids)) {
                $_CLASS['core_db']->query('UPDATE ' . FORUMS_PRIVMSGS_TABLE . ' 
					SET message_attachment = 0
					WHERE msg_id IN (' . implode(', ', $unset_ids) . ')');
            }
        }
    }
    if (sizeof($topic_ids)) {
        // Update topic indicator
        if ($mode == 'topic') {
            $_CLASS['core_db']->query('UPDATE ' . FORUMS_TOPICS_TABLE . '
				SET topic_attachment = 0
				WHERE topic_id IN (' . implode(', ', $topic_ids) . ')');
        }
        if ($mode == 'post' || $mode == 'user' || $mode == 'attach') {
            $remaining = array();
            $sql = 'SELECT topic_id
					FROM ' . FORUMS_ATTACHMENTS_TABLE . ' 
					WHERE topic_id IN (' . implode(', ', $topic_ids) . ')';
            $result = $_CLASS['core_db']->query($sql);
            while ($row = $_CLASS['core_db']->fetch_row_assoc($result)) {
                $remaining[] = $row['topic_id'];
            }
            $_CLASS['core_db']->free_result($result);
            $unset_ids = array_diff($topic_ids, $remaining);
            if (sizeof($unset_ids)) {
                $_CLASS['core_db']->query('UPDATE ' . FORUMS_TOPICS_TABLE . ' 
					SET topic_attachment = 0
					WHERE topic_id IN (' . implode(', ', $unset_ids) . ')');
            }
        }
    }
    return $num_deleted;
}
function delete_forum_content($forum_id)
{
    global $_CLASS, $site_file_root;
    require_once $site_file_root . 'includes/forums/functions_posting.php';
    $_CLASS['core_db']->transaction();
    switch ($_CLASS['core_db']->db_layer) {
        // Needs updating and testing
        /*		case 'mysql4':
        		case 'mysqli':
        			// Select then delete all attachments
        			$sql = 'SELECT a.topic_id
        				FROM ' . POSTS_TABLE . ' p, ' . ATTACHMENTS_TABLE . " a
        				WHERE p.forum_id = $forum_id
        					AND a.in_message = 0
        					AND a.topic_id = p.topic_id";
        			$result = $_CLASS['core_db']->query($sql);	
        		
        			$topic_ids = array();
        			while ($row = $_CLASS['core_db']->fetch_row_assoc($result))
        			{
        				$topic_ids[] = $row['topic_id'];
        			}
        			$_CLASS['core_db']->free_result($result);
        			
        			delete_attachments('topic', $topic_ids, false);
        
        			// Delete everything else and thank MySQL for offering multi-table deletion
        			$tables_ary = array(
        				BOOKMARKS_TABLE 	=> 'bm.topic_id',
        				SEARCH_MATCH_TABLE	=> 'wm.post_id',
        				REPORTS_TABLE		=> 're.post_id',
        				TOPICS_WATCH_TABLE	=> 'tw.topic_id',
        				TOPICS_TRACK_TABLE	=> 'tt.topic_id',
        				POLL_OPTIONS_TABLE	=> 'po.topic_id',
        				POLL_VOTES_TABLE	=> 'pv.topic_id'
        			);
        
        			$sql = 'DELETE QUICK FROM ' . POSTS_TABLE;
        			$sql_using = "\nUSING " . POSTS_TABLE . ' p';
        			$sql_where = "\nWHERE p.forum_id = $forum_id\n";
        			$sql_optimise = 'OPTIMIZE TABLE . ' . POSTS_TABLE;
        
        			foreach ($tables_ary as $table => $field)
        			{
        				$sql .= ", $table";
        				$sql_using .= ", $table " . strtok($field, '.');
        				$sql_where .= "\nAND $field = p." . strtok('');
        				$sql_optimise .= ', ' . $table;
        			}
        
        			$_CLASS['core_db']->query($sql . $sql_using . $sql_where);
        
        			$tables_ary = array(FORUMS_ACCESS_TABLE, TOPICS_TABLE, FORUMS_TRACK_TABLE, FORUMS_WATCH_TABLE, ACL_GROUPS_TABLE, ACL_USERS_TABLE, MODERATOR_TABLE, LOG_TABLE);
        			foreach ($tables_ary as $table)
        			{
        				$_CLASS['core_db']->query("DELETE QUICK FROM $table WHERE forum_id = $forum_id");
        				$sql_optimise .= ', ' . $table;
        			}
        
        			// Now optimise a hell lot of tables
        			$_CLASS['core_db']->query($sql_optimise);
        		break;
        */
        default:
            // Select then delete all attachments
            $sql = 'SELECT a.attach_id, a.physical_filename, a.thumbnail
				FROM ' . FORUMS_POSTS_TABLE . ' p, ' . FORUMS_ATTACHMENTS_TABLE . " a\n\t\t\t\tWHERE p.forum_id = {$forum_id}\n\t\t\t\t\tAND a.in_message = 0\n\t\t\t\t\tAND a.post_msg_id = p.post_id";
            $result = $_CLASS['core_db']->query($sql);
            $attach_ids = array();
            while ($row = $_CLASS['core_db']->fetch_row_assoc($result)) {
                $attach_ids[] = $row['attach_id'];
                phpbb_unlink($row['physical_filename'], 'file');
                if ($row['thumbnail']) {
                    phpbb_unlink($row['physical_filename'], 'thumbnail');
                }
            }
            $_CLASS['core_db']->free_result($result);
            if (count($attach_ids)) {
                $attach_id_list = implode(',', array_unique($attach_ids));
                $_CLASS['core_db']->query('DELETE FROM ' . FORUMS_ATTACHMENTS_TABLE . " WHERE attach_id IN ({$attach_id_list})");
                unset($attach_ids, $attach_id_list);
            }
            // Delete everything else and curse your DB for not offering multi-table deletion
            $tables_ary = array('post_id' => array(FORUMS_SEARCH_MATCH_TABLE, FORUMS_REPORTS_TABLE), 'topic_id' => array(FORUMS_BOOKMARKS_TABLE, FORUMS_WATCH_TABLE, FORUMS_TRACK_TABLE, FORUMS_POLL_OPTIONS_TABLE, FORUMS_POLL_VOTES_TABLE));
            foreach ($tables_ary as $field => $tables) {
                $start = 0;
                $id_array = array();
                $sql = "SELECT {$field}\n\t\t\t\t\tFROM " . FORUMS_POSTS_TABLE . '
					WHERE forum_id = ' . $forum_id;
                $result = $_CLASS['core_db']->query($sql);
                while ($row = $_CLASS['core_db']->fetch_row_assoc($result)) {
                    $id_array[] = $row[$field];
                }
                $_CLASS['core_db']->free_result($result);
                if (empty($id_array)) {
                    continue;
                }
                foreach ($tables as $table) {
                    $_CLASS['core_db']->query("DELETE FROM {$table} WHERE {$field} IN (" . implode(',', $id_array) . ')');
                }
            }
            unset($id_array);
            $table_ary = array(FORUMS_POSTS_TABLE, FORUMS_TRACK_TABLE, FORUMS_WATCH_TABLE, FORUMS_TOPICS_TABLE, FORUMS_ACL_TABLE, FORUMS_MODERATOR_TABLE, FORUMS_LOG_TABLE);
            foreach ($table_ary as $table) {
                $_CLASS['core_db']->query("DELETE FROM {$table} WHERE forum_id = {$forum_id}");
            }
            break;
    }
    $_CLASS['core_db']->transaction('commit');
    // NEED to have this done at the end, maybe a cran
    $tables = array_unique(array_merge($tables_ary['post_id'], $tables_ary['topic_id'], $table_ary, array(FORUMS_ATTACHMENTS_TABLE)));
    $_CLASS['core_db']->optimize_tables($tables);
}
 function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false)
 {
     global $config, $_CLASS, $site_file_root, $forum_id;
     $error = array();
     $num_attachments = sizeof($this->attachment_data);
     $this->filename_data['filecomment'] = request_var('filecomment', '', true);
     $upload_file = isset($_FILES[$form_name]) && $_FILES[$form_name]['name'] != 'none' && trim($_FILES[$form_name]['name']) ? true : false;
     $add_file = isset($_POST['add_file']);
     $delete_file = isset($_POST['delete_file']);
     $edit_comment = isset($_POST['edit_comment']);
     $cfg = array();
     $cfg['max_attachments'] = $is_message ? $config['max_attachments_pm'] : $config['max_attachments'];
     $forum_id = $is_message ? 0 : $forum_id;
     if ($submit && in_array($mode, array('post', 'reply', 'quote', 'edit')) && $upload_file) {
         if ($num_attachments < $cfg['max_attachments'] || $_CLASS['auth']->acl_gets('m_', 'a_')) {
             $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message);
             $error = $filedata['error'];
             if ($filedata['post_attach'] && !sizeof($error)) {
                 $new_entry = array('physical_filename' => $filedata['physical_filename'], 'comment' => $this->filename_data['filecomment'], 'real_filename' => $filedata['real_filename'], 'extension' => $filedata['extension'], 'mimetype' => $filedata['mimetype'], 'filesize' => $filedata['filesize'], 'filetime' => $filedata['filetime'], 'attach_id' => 0, 'thumbnail' => $filedata['thumbnail']);
                 $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data);
                 $this->message = preg_replace('#\\[attachment=([0-9]+)\\](.*?)\\[\\/attachment\\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message);
                 $this->filename_data['filecomment'] = '';
                 // This Variable is set to false here, because Attachments are entered into the
                 // Database in two modes, one if the id_list is 0 and the second one if post_attach is true
                 // Since post_attach is automatically switched to true if an Attachment got added to the filesystem,
                 // but we are assigning an id of 0 here, we have to reset the post_attach variable to false.
                 //
                 // This is very relevant, because it could happen that the post got not submitted, but we do not
                 // know this circumstance here. We could be at the posting page or we could be redirected to the entered
                 // post. :)
                 $filedata['post_attach'] = false;
             }
         } else {
             $error[] = sprintf($_CLASS['core_user']->lang['TOO_MANY_ATTACHMENTS'], $cfg['max_attachments']);
         }
     }
     if ($preview || $refresh || sizeof($error)) {
         // Perform actions on temporary attachments
         if ($delete_file) {
             $index = (int) key($_POST['delete_file']);
             // delete selected attachment
             if (!$this->attachment_data[$index]['attach_id']) {
                 phpbb_unlink($this->attachment_data[$index]['physical_filename'], 'file');
                 if ($this->attachment_data[$index]['thumbnail']) {
                     phpbb_unlink($this->attachment_data[$index]['physical_filename'], 'thumbnail');
                 }
             } else {
                 delete_attachments('attach', array(intval($this->attachment_data[$index]['attach_id'])));
             }
             unset($this->attachment_data[$index]);
             $this->message = preg_replace('#\\[attachment=([0-9]+)\\](.*?)\\[\\/attachment\\]#e', "(\\1 == \$index) ? '' : ((\\1 > \$index) ? '[attachment=' . (\\1 - 1) . ']\\2[/attachment]' : '\\0')", $this->message);
             // Reindex Array
             $this->attachment_data = array_values($this->attachment_data);
         } else {
             if ($edit_comment || $add_file || $preview) {
                 if ($edit_comment) {
                     $actual_comment_list = request_var('comment_list', array(''));
                     foreach ($actual_comment_list as $index => $entry) {
                         $this->attachment_data[$index]['comment'] = preg_replace('#&amp;(\\#[0-9]+;)#', '&\\1', $entry);
                     }
                 }
                 if (($add_file || $preview) && $upload_file) {
                     if ($num_attachments < $cfg['max_attachments'] || $_CLASS['auth']->acl_gets('m_', 'a_')) {
                         $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message);
                         $error = array_merge($error, $filedata['error']);
                         if (!sizeof($error)) {
                             $new_entry = array('physical_filename' => $filedata['physical_filename'], 'comment' => $this->filename_data['filecomment'], 'real_filename' => $filedata['real_filename'], 'extension' => $filedata['extension'], 'mimetype' => $filedata['mimetype'], 'filesize' => $filedata['filesize'], 'filetime' => $filedata['filetime'], 'attach_id' => 0, 'thumbnail' => $filedata['thumbnail']);
                             $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data);
                             $this->message = preg_replace('#\\[attachment=([0-9]+)\\](.*?)\\[\\/attachment\\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message);
                             $this->filename_data['filecomment'] = '';
                         }
                     } else {
                         $error[] = sprintf($_CLASS['core_user']->lang['TOO_MANY_ATTACHMENTS'], $cfg['max_attachments']);
                     }
                 }
             }
         }
     }
     foreach ($error as $error_msg) {
         $this->warn_msg[] = $error_msg;
     }
 }
/**
* Delete Attachments
*
* @param string $mode can be: post|message|topic|attach|user
* @param mixed $ids can be: post_ids, message_ids, topic_ids, attach_ids, user_ids
* @param bool $resync set this to false if you are deleting posts or topics
*/
function delete_attachments($mode, $ids, $resync = true)
{
    global $db, $config, $phpbb_dispatcher;
    // 0 is as bad as an empty array
    if (empty($ids)) {
        return false;
    }
    if (is_array($ids)) {
        $ids = array_unique($ids);
        $ids = array_map('intval', $ids);
    } else {
        $ids = array((int) $ids);
    }
    $sql_where = '';
    switch ($mode) {
        case 'post':
        case 'message':
            $sql_id = 'post_msg_id';
            $sql_where = ' AND in_message = ' . ($mode == 'message' ? 1 : 0);
            break;
        case 'topic':
            $sql_id = 'topic_id';
            break;
        case 'user':
            $sql_id = 'poster_id';
            break;
        case 'attach':
        default:
            $sql_id = 'attach_id';
            $mode = 'attach';
            break;
    }
    $post_ids = $message_ids = $topic_ids = $physical = array();
    /**
     * Perform additional actions before collecting data for attachment(s) deletion
     *
     * @event core.delete_attachments_collect_data_before
     * @var	string	mode			Variable containing attachments deletion mode, can be: post|message|topic|attach|user
     * @var	mixed	ids				Array or comma separated list of ids corresponding to the mode
     * @var	bool	resync			Flag indicating if posts/messages/topics should be synchronized
     * @var	string	sql_id			The field name to collect/delete data for depending on the mode
     * @since 3.1.7-RC1
     */
    $vars = array('mode', 'ids', 'resync', 'sql_id');
    extract($phpbb_dispatcher->trigger_event('core.delete_attachments_collect_data_before', compact($vars)));
    // Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled)
    $sql = 'SELECT post_msg_id, topic_id, in_message, physical_filename, thumbnail, filesize, is_orphan
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set($sql_id, $ids);
    $sql .= $sql_where;
    $result = $db->sql_query($sql);
    while ($row = $db->sql_fetchrow($result)) {
        // We only need to store post/message/topic ids if resync is enabled and the file is not orphaned
        if ($resync && !$row['is_orphan']) {
            if (!$row['in_message']) {
                $post_ids[] = $row['post_msg_id'];
                $topic_ids[] = $row['topic_id'];
            } else {
                $message_ids[] = $row['post_msg_id'];
            }
        }
        $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize'], 'is_orphan' => $row['is_orphan']);
    }
    $db->sql_freeresult($result);
    /**
     * Perform additional actions before attachment(s) deletion
     *
     * @event core.delete_attachments_before
     * @var	string	mode			Variable containing attachments deletion mode, can be: post|message|topic|attach|user
     * @var	mixed	ids				Array or comma separated list of ids corresponding to the mode
     * @var	bool	resync			Flag indicating if posts/messages/topics should be synchronized
     * @var	string	sql_id			The field name to collect/delete data for depending on the mode
     * @var	array	post_ids		Array with post ids for deleted attachment(s)
     * @var	array	topic_ids		Array with topic ids for deleted attachment(s)
     * @var	array	message_ids		Array with private message ids for deleted attachment(s)
     * @var	array	physical		Array with deleted attachment(s) physical file(s) data
     * @since 3.1.7-RC1
     */
    $vars = array('mode', 'ids', 'resync', 'sql_id', 'post_ids', 'topic_ids', 'message_ids', 'physical');
    extract($phpbb_dispatcher->trigger_event('core.delete_attachments_before', compact($vars)));
    // Delete attachments
    $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . '
		WHERE ' . $db->sql_in_set($sql_id, $ids);
    $sql .= $sql_where;
    $db->sql_query($sql);
    $num_deleted = $db->sql_affectedrows();
    /**
     * Perform additional actions after attachment(s) deletion from the database
     *
     * @event core.delete_attachments_from_database_after
     * @var	string	mode			Variable containing attachments deletion mode, can be: post|message|topic|attach|user
     * @var	mixed	ids				Array or comma separated list of ids corresponding to the mode
     * @var	bool	resync			Flag indicating if posts/messages/topics should be synchronized
     * @var	string	sql_id			The field name to collect/delete data for depending on the mode
     * @var	array	post_ids		Array with post ids for deleted attachment(s)
     * @var	array	topic_ids		Array with topic ids for deleted attachment(s)
     * @var	array	message_ids		Array with private message ids for deleted attachment(s)
     * @var	array	physical		Array with deleted attachment(s) physical file(s) data
     * @var	int		num_deleted		The number of deleted attachment(s) from the database
     * @since 3.1.7-RC1
     */
    $vars = array('mode', 'ids', 'resync', 'sql_id', 'post_ids', 'topic_ids', 'message_ids', 'physical', 'num_deleted');
    extract($phpbb_dispatcher->trigger_event('core.delete_attachments_from_database_after', compact($vars)));
    if (!$num_deleted) {
        return 0;
    }
    // Delete attachments from filesystem
    $space_removed = $files_removed = 0;
    foreach ($physical as $file_ary) {
        if (phpbb_unlink($file_ary['filename'], 'file', true) && !$file_ary['is_orphan']) {
            // Only non-orphaned files count to the file size
            $space_removed += $file_ary['filesize'];
            $files_removed++;
        }
        if ($file_ary['thumbnail']) {
            phpbb_unlink($file_ary['filename'], 'thumbnail', true);
        }
    }
    /**
     * Perform additional actions after attachment(s) deletion from the filesystem
     *
     * @event core.delete_attachments_from_filesystem_after
     * @var	string	mode			Variable containing attachments deletion mode, can be: post|message|topic|attach|user
     * @var	mixed	ids				Array or comma separated list of ids corresponding to the mode
     * @var	bool	resync			Flag indicating if posts/messages/topics should be synchronized
     * @var	string	sql_id			The field name to collect/delete data for depending on the mode
     * @var	array	post_ids		Array with post ids for deleted attachment(s)
     * @var	array	topic_ids		Array with topic ids for deleted attachment(s)
     * @var	array	message_ids		Array with private message ids for deleted attachment(s)
     * @var	array	physical		Array with deleted attachment(s) physical file(s) data
     * @var	int		num_deleted		The number of deleted attachment(s) from the database
     * @var	int		space_removed	The size of deleted files(s) from the filesystem
     * @var	int		files_removed	The number of deleted file(s) from the filesystem
     * @since 3.1.7-RC1
     */
    $vars = array('mode', 'ids', 'resync', 'sql_id', 'post_ids', 'topic_ids', 'message_ids', 'physical', 'num_deleted', 'space_removed', 'files_removed');
    extract($phpbb_dispatcher->trigger_event('core.delete_attachments_from_filesystem_after', compact($vars)));
    if ($space_removed || $files_removed) {
        set_config_count('upload_dir_size', $space_removed * -1, true);
        set_config_count('num_files', $files_removed * -1, true);
    }
    // If we do not resync, we do not need to adjust any message, post, topic or user entries
    if (!$resync) {
        return $num_deleted;
    }
    // No more use for the original ids
    unset($ids);
    // Now, we need to resync posts, messages, topics. We go through every one of them
    $post_ids = array_unique($post_ids);
    $message_ids = array_unique($message_ids);
    $topic_ids = array_unique($topic_ids);
    // Update post indicators for posts now no longer having attachments
    if (sizeof($post_ids)) {
        // Just check which posts are still having an assigned attachment not orphaned by querying the attachments table
        $sql = 'SELECT post_msg_id
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . '
				AND in_message = 0
				AND is_orphan = 0';
        $result = $db->sql_query($sql);
        $remaining_ids = array();
        while ($row = $db->sql_fetchrow($result)) {
            $remaining_ids[] = $row['post_msg_id'];
        }
        $db->sql_freeresult($result);
        // Now only unset those ids remaining
        $post_ids = array_diff($post_ids, $remaining_ids);
        if (sizeof($post_ids)) {
            $sql = 'UPDATE ' . POSTS_TABLE . '
				SET post_attachment = 0
				WHERE ' . $db->sql_in_set('post_id', $post_ids);
            $db->sql_query($sql);
        }
    }
    // Update message table if messages are affected
    if (sizeof($message_ids)) {
        // Just check which messages are still having an assigned attachment not orphaned by querying the attachments table
        $sql = 'SELECT post_msg_id
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set('post_msg_id', $message_ids) . '
				AND in_message = 1
				AND is_orphan = 0';
        $result = $db->sql_query($sql);
        $remaining_ids = array();
        while ($row = $db->sql_fetchrow($result)) {
            $remaining_ids[] = $row['post_msg_id'];
        }
        $db->sql_freeresult($result);
        // Now only unset those ids remaining
        $message_ids = array_diff($message_ids, $remaining_ids);
        if (sizeof($message_ids)) {
            $sql = 'UPDATE ' . PRIVMSGS_TABLE . '
				SET message_attachment = 0
				WHERE ' . $db->sql_in_set('msg_id', $message_ids);
            $db->sql_query($sql);
        }
    }
    // Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic
    if (sizeof($topic_ids)) {
        // Just check which topics are still having an assigned attachment not orphaned by querying the attachments table (much less entries expected)
        $sql = 'SELECT topic_id
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . '
				AND is_orphan = 0';
        $result = $db->sql_query($sql);
        $remaining_ids = array();
        while ($row = $db->sql_fetchrow($result)) {
            $remaining_ids[] = $row['topic_id'];
        }
        $db->sql_freeresult($result);
        // Now only unset those ids remaining
        $topic_ids = array_diff($topic_ids, $remaining_ids);
        if (sizeof($topic_ids)) {
            $sql = 'UPDATE ' . TOPICS_TABLE . '
				SET topic_attachment = 0
				WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
            $db->sql_query($sql);
        }
    }
    return $num_deleted;
}
<h1><?php echo $_CLASS['core_user']->lang[$l_title]; ?></h1>

<p><?php echo $_CLASS['core_user']->lang[$l_title . '_EXPLAIN']; ?></p>

<?php

if ($submit && $mode == 'orphan')
{
	$delete_files = (isset($_POST['delete'])) ? array_keys(request_var('delete', array('' => 0))) : array();
	$add_files = (isset($_POST['add'])) ? array_keys(request_var('add', array('' => 0))) : array();
	$post_ids = request_var('post_id', 0);

	foreach ($delete_files as $delete)
	{
		phpbb_unlink($delete);
		phpbb_unlink($delete, 'thumbnail');
	}

	if (sizeof($delete_files))
	{
		add_log('admin', sprintf($_CLASS['core_user']->lang['LOG_ATTACH_ORPHAN_DEL'], implode(', ', $delete_files)));
		$notify[] = sprintf($_CLASS['core_user']->lang['LOG_ATTACH_ORPHAN_DEL'], implode(', ', $delete_files));
	}

	$upload_list = array();
	foreach ($add_files as $file)
	{
		if (!in_array($file, $delete_files) && $post_ids[$file])
		{
			$upload_list[$post_ids[$file]] = $file;
		}
Example #10
0
/**
* Delete Attachments
*
* @param string $mode can be: post|topic|attach|user
* @param mixed $ids can be: post_ids, topic_ids, attach_ids, user_ids
* @param bool $resync set this to false if you are deleting posts or topics
*/
function delete_attachments($mode, $ids, $resync = true)
{
	global $db, $config;

	if (is_array($ids) && sizeof($ids))
	{
		$ids = array_unique($ids);
		$ids = array_map('intval', $ids);
	}
	else
	{
		$ids = array((int) $ids);
	}

	if (!sizeof($ids))
	{
		return false;
	}

	$sql_id = ($mode == 'user') ? 'poster_id' : (($mode == 'post') ? 'post_msg_id' : (($mode == 'topic') ? 'topic_id' : 'attach_id'));

	$post_ids = $topic_ids = $physical = array();

	// Collect post and topics ids for later use
	if ($mode == 'attach' || $mode == 'user' || ($mode == 'topic' && $resync))
	{
		$sql = 'SELECT post_msg_id as post_id, topic_id, physical_filename, thumbnail, filesize
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set($sql_id, $ids);
		$result = $db->sql_query($sql);

		while ($row = $db->sql_fetchrow($result))
		{
			$post_ids[] = $row['post_id'];
			$topic_ids[] = $row['topic_id'];
			$physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize']);
		}
		$db->sql_freeresult($result);
	}

	if ($mode == 'post')
	{
		$sql = 'SELECT topic_id, physical_filename, thumbnail, filesize
			FROM ' . ATTACHMENTS_TABLE . '
			WHERE ' . $db->sql_in_set('post_msg_id', $ids) . '
				AND in_message = 0';
		$result = $db->sql_query($sql);

		while ($row = $db->sql_fetchrow($result))
		{
			$topic_ids[] = $row['topic_id'];
			$physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize']);
		}
		$db->sql_freeresult($result);
	}

	// Delete attachments
	$sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . '
		WHERE ' . $db->sql_in_set($sql_id, $ids);
	$db->sql_query($sql);
	$num_deleted = $db->sql_affectedrows();

	if (!$num_deleted)
	{
		return 0;
	}

	// Delete attachments from filesystem
	$space_removed = $files_removed = 0;
	foreach ($physical as $file_ary)
	{
		if (phpbb_unlink($file_ary['filename'], 'file', true))
		{
			$space_removed += $file_ary['filesize'];
			$files_removed++;
		}

		if ($file_ary['thumbnail'])
		{
			phpbb_unlink($file_ary['filename'], 'thumbnail', true);
		}
	}
	set_config('upload_dir_size', $config['upload_dir_size'] - $space_removed, true);
	set_config('num_files', $config['num_files'] - $files_removed, true);

	if ($mode == 'topic' && !$resync)
	{
		return $num_deleted;
	}

	if ($mode == 'post')
	{
		$post_ids = $ids;
	}
	unset($ids);

	$post_ids = array_unique($post_ids);
	$topic_ids = array_unique($topic_ids);

	// Update post indicators
	if (sizeof($post_ids))
	{
		if ($mode == 'post' || $mode == 'topic')
		{
			$sql = 'UPDATE ' . POSTS_TABLE . '
				SET post_attachment = 0
				WHERE ' . $db->sql_in_set('post_id', $post_ids);
			$db->sql_query($sql);
		}

		if ($mode == 'user' || $mode == 'attach')
		{
			$remaining = array();

			$sql = 'SELECT post_msg_id
				FROM ' . ATTACHMENTS_TABLE . '
				WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . '
					AND in_message = 0';
			$result = $db->sql_query($sql);

			while ($row = $db->sql_fetchrow($result))
			{
				$remaining[] = $row['post_msg_id'];		
			}
			$db->sql_freeresult($result);

			$unset_ids = array_diff($post_ids, $remaining);

			if (sizeof($unset_ids))
			{
				$sql = 'UPDATE ' . POSTS_TABLE . '
					SET post_attachment = 0
					WHERE ' . $db->sql_in_set('post_id', $unset_ids);
				$db->sql_query($sql);
			}

			$remaining = array();

			$sql = 'SELECT post_msg_id
				FROM ' . ATTACHMENTS_TABLE . '
				WHERE ' . $db->sql_in_set('post_msg_id', $post_ids) . '
					AND in_message = 1';
			$result = $db->sql_query($sql);

			while ($row = $db->sql_fetchrow($result))
			{
				$remaining[] = $row['post_msg_id'];		
			}
			$db->sql_freeresult($result);

			$unset_ids = array_diff($post_ids, $remaining);

			if (sizeof($unset_ids))
			{
				$sql = 'UPDATE ' . PRIVMSGS_TABLE . '
					SET message_attachment = 0
					WHERE ' . $db->sql_in_set('msg_id', $unset_ids);
				$db->sql_query($sql);
			}
		}
	}

	if (sizeof($topic_ids))
	{
		// Update topic indicator
		if ($mode == 'topic')
		{
			$sql = 'UPDATE ' . TOPICS_TABLE . '
				SET topic_attachment = 0
				WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
			$db->sql_query($sql);
		}

		if ($mode == 'post' || $mode == 'user' || $mode == 'attach')
		{
			$remaining = array();

			$sql = 'SELECT topic_id
				FROM ' . ATTACHMENTS_TABLE . '
				WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
			$result = $db->sql_query($sql);

			while ($row = $db->sql_fetchrow($result))
			{
				$remaining[] = $row['topic_id'];		
			}
			$db->sql_freeresult($result);

			$unset_ids = array_diff($topic_ids, $remaining);

			if (sizeof($unset_ids))
			{
				$sql = 'UPDATE ' . TOPICS_TABLE . '
					SET topic_attachment = 0
					WHERE ' . $db->sql_in_set('topic_id', $unset_ids);
				$db->sql_query($sql);
			}
		}
	}

	return $num_deleted;
}