Beispiel #1
0
/**
 * downloads a file from a url and stores it locally for avatar use by id_member.
 * - supports GIF, JPG, PNG, BMP and WBMP formats.
 * - detects if GD2 is available.
 * - uses resizeImageFile() to resize to max_width by max_height, and saves the result to a file.
 * - updates the database info for the member's avatar.
 * - returns whether the download and resize was successful.
 *
 * @param string $temporary_path, the full path to the temporary file
 * @param int $memID, member ID
 * @param int $max_width
 * @param int $max_height
 * @return bool, whether the download and resize was successful.
 *
 */
function downloadAvatar($url, $memID, $max_width, $max_height)
{
    global $modSettings, $sourcedir, $smcFunc;
    $ext = !empty($modSettings['avatar_download_png']) ? 'png' : 'jpeg';
    $destName = 'avatar_' . $memID . '_' . time() . '.' . $ext;
    // Just making sure there is a non-zero member.
    if (empty($memID)) {
        return false;
    }
    require_once $sourcedir . '/ManageAttachments.php';
    removeAttachments(array('id_member' => $memID));
    $id_folder = !empty($modSettings['currentAttachmentUploadDir']) ? $modSettings['currentAttachmentUploadDir'] : 1;
    $avatar_hash = empty($modSettings['custom_avatar_enabled']) ? getAttachmentFilename($destName, false, null, true) : '';
    $smcFunc['db_insert']('', '{db_prefix}attachments', array('id_member' => 'int', 'attachment_type' => 'int', 'filename' => 'string-255', 'file_hash' => 'string-255', 'fileext' => 'string-8', 'size' => 'int', 'id_folder' => 'int'), array($memID, empty($modSettings['custom_avatar_enabled']) ? 0 : 1, $destName, $avatar_hash, $ext, 1, $id_folder), array('id_attach'));
    $attachID = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
    // Retain this globally in case the script wants it.
    $modSettings['new_avatar_data'] = array('id' => $attachID, 'filename' => $destName, 'type' => empty($modSettings['custom_avatar_enabled']) ? 0 : 1);
    $destName = (empty($modSettings['custom_avatar_enabled']) ? is_array($modSettings['attachmentUploadDir']) ? $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']] : $modSettings['attachmentUploadDir'] : $modSettings['custom_avatar_dir']) . '/' . $destName . '.tmp';
    // Resize it.
    if (!empty($modSettings['avatar_download_png'])) {
        $success = resizeImageFile($url, $destName, $max_width, $max_height, 3);
    } else {
        $success = resizeImageFile($url, $destName, $max_width, $max_height);
    }
    // Remove the .tmp extension.
    $destName = substr($destName, 0, -4);
    if ($success) {
        // Walk the right path.
        if (!empty($modSettings['currentAttachmentUploadDir'])) {
            if (!is_array($modSettings['attachmentUploadDir'])) {
                $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
            }
            $path = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
        } else {
            $path = $modSettings['attachmentUploadDir'];
        }
        // Remove the .tmp extension from the attachment.
        if (rename($destName . '.tmp', empty($avatar_hash) ? $destName : $path . '/' . $attachID . '_' . $avatar_hash)) {
            $destName = empty($avatar_hash) ? $destName : $path . '/' . $attachID . '_' . $avatar_hash;
            list($width, $height) = getimagesize($destName);
            $mime_type = 'image/' . $ext;
            // Write filesize in the database.
            $smcFunc['db_query']('', '
				UPDATE {db_prefix}attachments
				SET size = {int:filesize}, width = {int:width}, height = {int:height},
					mime_type = {string:mime_type}
				WHERE id_attach = {int:current_attachment}', array('filesize' => filesize($destName), 'width' => (int) $width, 'height' => (int) $height, 'current_attachment' => $attachID, 'mime_type' => $mime_type));
            return true;
        } else {
            return false;
        }
    } else {
        $smcFunc['db_query']('', '
			DELETE FROM {db_prefix}attachments
			WHERE id_attach = {int:current_attachment}', array('current_attachment' => $attachID));
        @unlink($destName . '.tmp');
        return false;
    }
}
 /**
  * Called from a mouse click,
  * works out what we want to do with attachments and actions it.
  * Accessed by ?action=attachapprove
  */
 public function action_attachapprove()
 {
     global $user_info;
     // Security is our primary concern...
     checkSession('get');
     // If it approve or delete?
     $is_approve = !isset($_GET['sa']) || $_GET['sa'] != 'reject' ? true : false;
     $attachments = array();
     require_once SUBSDIR . '/ManageAttachments.subs.php';
     // If we are approving all ID's in a message , get the ID's.
     if ($_GET['sa'] == 'all' && !empty($_GET['mid'])) {
         $id_msg = (int) $_GET['mid'];
         $attachments = attachmentsOfMessage($id_msg);
     } elseif (!empty($_GET['aid'])) {
         $attachments[] = (int) $_GET['aid'];
     }
     if (empty($attachments)) {
         fatal_lang_error('no_access', false);
     }
     // @todo nb: this requires permission to approve posts, not manage attachments
     // Now we have some ID's cleaned and ready to approve, but first - let's check we have permission!
     $allowed_boards = !empty($user_info['mod_cache']['ap']) ? $user_info['mod_cache']['ap'] : boardsAllowedTo('approve_posts');
     if ($allowed_boards == array(0)) {
         $approve_query = '';
     } elseif (!empty($allowed_boards)) {
         $approve_query = ' AND m.id_board IN (' . implode(',', $allowed_boards) . ')';
     } else {
         $approve_query = ' AND 0';
     }
     // Validate the attachments exist and have the right approval state.
     $attachments = validateAttachments($attachments, $approve_query);
     // Set up a return link based off one of the attachments for this message
     $attach_home = attachmentBelongsTo($attachments[0]);
     $redirect = 'topic=' . $attach_home['id_topic'] . '.msg' . $attach_home['id_msg'] . '#msg' . $attach_home['id_msg'];
     if (empty($attachments)) {
         fatal_lang_error('no_access', false);
     }
     // Finally, we are there. Follow through!
     if ($is_approve) {
         // Checked and deemed worthy.
         approveAttachments($attachments);
     } else {
         removeAttachments(array('id_attach' => $attachments, 'do_logging' => true));
     }
     // We approved or removed, either way we reset those numbers
     cache_put_data('num_menu_errors', null, 900);
     // Return to the topic....
     redirectexit($redirect);
 }
    /**
     * View all unapproved attachments.
     */
    public function action_unapproved_attachments()
    {
        global $txt, $scripturl, $context, $user_info, $modSettings;
        $context['page_title'] = $txt['mc_unapproved_attachments'];
        // Once again, permissions are king!
        $approve_boards = !empty($user_info['mod_cache']['ap']) ? $user_info['mod_cache']['ap'] : boardsAllowedTo('approve_posts');
        if ($approve_boards == array(0)) {
            $approve_query = '';
        } elseif (!empty($approve_boards)) {
            $approve_query = ' AND m.id_board IN (' . implode(',', $approve_boards) . ')';
        } else {
            $approve_query = ' AND 0';
        }
        // Get together the array of things to act on, if any.
        $attachments = array();
        if (isset($_GET['approve'])) {
            $attachments[] = (int) $_GET['approve'];
        } elseif (isset($_GET['delete'])) {
            $attachments[] = (int) $_GET['delete'];
        } elseif (isset($_POST['item'])) {
            foreach ($_POST['item'] as $item) {
                $attachments[] = (int) $item;
            }
        }
        // Are we approving or deleting?
        if (isset($_GET['approve']) || isset($_POST['do']) && $_POST['do'] == 'approve') {
            $curAction = 'approve';
        } elseif (isset($_GET['delete']) || isset($_POST['do']) && $_POST['do'] == 'delete') {
            $curAction = 'delete';
        }
        // Something to do, let's do it!
        if (!empty($attachments) && isset($curAction)) {
            checkSession('request');
            // This will be handy.
            require_once SUBSDIR . '/ManageAttachments.subs.php';
            // Confirm the attachments are eligible for changing!
            $attachments = validateAttachments($attachments, $approve_query);
            // Assuming it wasn't all like, proper illegal, we can do the approving.
            if (!empty($attachments)) {
                if ($curAction == 'approve') {
                    approveAttachments($attachments);
                } else {
                    removeAttachments(array('id_attach' => $attachments, 'do_logging' => true));
                }
                cache_put_data('num_menu_errors', null, 900);
            }
        }
        require_once SUBSDIR . '/GenericList.class.php';
        require_once SUBSDIR . '/ManageAttachments.subs.php';
        $listOptions = array('id' => 'mc_unapproved_attach', 'width' => '100%', 'items_per_page' => $modSettings['defaultMaxMessages'], 'no_items_label' => $txt['mc_unapproved_attachments_none_found'], 'base_href' => $scripturl . '?action=moderate;area=attachmod;sa=attachments', 'default_sort_col' => 'attach_name', 'get_items' => array('function' => 'list_getUnapprovedAttachments', 'params' => array($approve_query)), 'get_count' => array('function' => 'list_getNumUnapprovedAttachments', 'params' => array($approve_query)), 'columns' => array('attach_name' => array('header' => array('value' => $txt['mc_unapproved_attach_name']), 'data' => array('db' => 'filename'), 'sort' => array('default' => 'a.filename', 'reverse' => 'a.filename DESC')), 'attach_size' => array('header' => array('value' => $txt['mc_unapproved_attach_size']), 'data' => array('db' => 'size'), 'sort' => array('default' => 'a.size', 'reverse' => 'a.size DESC')), 'attach_poster' => array('header' => array('value' => $txt['mc_unapproved_attach_poster']), 'data' => array('function' => create_function('$data', '
							return $data[\'poster\'][\'link\'];')), 'sort' => array('default' => 'm.id_member', 'reverse' => 'm.id_member DESC')), 'date' => array('header' => array('value' => $txt['date'], 'style' => 'width: 18%;'), 'data' => array('db' => 'time', 'class' => 'smalltext', 'style' => 'white-space:nowrap;'), 'sort' => array('default' => 'm.poster_time', 'reverse' => 'm.poster_time DESC')), 'message' => array('header' => array('value' => $txt['post']), 'data' => array('function' => create_function('$data', '
							global $modSettings;

							return \'<a href="\' . $data[\'message\'][\'href\'] . \'">\' . Util::shorten_text($data[\'message\'][\'subject\'], !empty($modSettings[\'subject_length\']) ? $modSettings[\'subject_length\'] : 24) . \'</a>\';'), 'class' => 'smalltext', 'style' => 'width:15em;'), 'sort' => array('default' => 'm.subject', 'reverse' => 'm.subject DESC')), 'action' => array('header' => array('value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);" />', 'style' => 'width: 4%'), 'data' => array('sprintf' => array('format' => '<input type="checkbox" name="item[]" value="%1$d" class="input_check" />', 'params' => array('id' => false))))), 'form' => array('href' => $scripturl . '?action=moderate;area=attachmod;sa=attachments', 'include_sort' => true, 'include_start' => true, 'hidden_fields' => array($context['session_var'] => $context['session_id']), 'token' => 'mod-ap'), 'additional_rows' => array(array('position' => 'bottom_of_list', 'value' => '
						<select name="do" onchange="if (this.value != 0 &amp;&amp; confirm(\'' . $txt['mc_unapproved_sure'] . '\')) submit();">
							<option value="0">' . $txt['with_selected'] . ':</option>
							<option value="0" disabled="disabled">' . str_repeat('&#8212;', strlen($txt['approve'])) . '</option>
							<option value="approve">' . (isBrowser('ie8') ? '&#187;' : '&#10148;') . '&nbsp;' . $txt['approve'] . '</option>
							<option value="delete">' . (isBrowser('ie8') ? '&#187;' : '&#10148;') . '&nbsp;' . $txt['delete'] . '</option>
						</select>
						<noscript><input type="submit" name="ml_go" value="' . $txt['go'] . '" class="right_submit" /></noscript>', 'class' => 'floatright')));
        // Create the request list.
        createToken('mod-ap');
        createList($listOptions);
        $context['sub_template'] = 'show_list';
        $context['default_list'] = 'mc_unapproved_attach';
        $context[$context['moderation_menu_name']]['tab_data'] = array('title' => $txt['mc_unapproved_attachments'], 'help' => '', 'description' => $txt['mc_unapproved_attachments_desc']);
    }
Beispiel #4
0
function deleteMembers($users, $check_not_admin = false)
{
    global $sourcedir, $modSettings, $user_info, $backend_subdir;
    // Try give us a while to sort this out...
    @set_time_limit(600);
    // Try to get some more memory.
    if (@ini_get('memory_limit') < 128) {
        @ini_set('memory_limit', '128M');
    }
    // If it's not an array, make it so!
    if (!is_array($users)) {
        $users = array($users);
    } else {
        $users = array_unique($users);
    }
    // Make sure there's no void user in here.
    $users = array_diff($users, array(0));
    // How many are they deleting?
    if (empty($users)) {
        return;
    } elseif (count($users) == 1) {
        list($user) = $users;
        if ($user == $user_info['id']) {
            isAllowedTo('profile_remove_own');
        } else {
            isAllowedTo('profile_remove_any');
        }
    } else {
        foreach ($users as $k => $v) {
            $users[$k] = (int) $v;
        }
        // Deleting more than one?  You can't have more than one account...
        isAllowedTo('profile_remove_any');
    }
    // Get their names for logging purposes.
    $request = smf_db_query('
		SELECT id_member, member_name, CASE WHEN id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0 THEN 1 ELSE 0 END AS is_admin
		FROM {db_prefix}members
		WHERE id_member IN ({array_int:user_list})
		LIMIT ' . count($users), array('user_list' => $users, 'admin_group' => 1));
    $admins = array();
    $user_log_details = array();
    while ($row = mysql_fetch_assoc($request)) {
        if ($row['is_admin']) {
            $admins[] = $row['id_member'];
        }
        $user_log_details[$row['id_member']] = array($row['id_member'], $row['member_name']);
    }
    mysql_free_result($request);
    if (empty($user_log_details)) {
        return;
    }
    // Make sure they aren't trying to delete administrators if they aren't one.  But don't bother checking if it's just themself.
    if (!empty($admins) && ($check_not_admin || !allowedTo('admin_forum') && (count($users) != 1 || $users[0] != $user_info['id']))) {
        $users = array_diff($users, $admins);
        foreach ($admins as $id) {
            unset($user_log_details[$id]);
        }
    }
    // No one left?
    if (empty($users)) {
        return;
    }
    // Log the action - regardless of who is deleting it.
    $log_inserts = array();
    foreach ($user_log_details as $user) {
        // Integration rocks!
        HookAPI::callHook('integrate_delete_member', array($user[0]));
        // Add it to the administration log for future reference.
        $log_inserts[] = array(time(), 3, $user_info['id'], $user_info['ip'], 'delete_member', 0, 0, 0, serialize(array('member' => $user[0], 'name' => $user[1], 'member_acted' => $user_info['name'])));
        // Remove any cached data if enabled.
        if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2) {
            CacheAPI::putCache('user_settings-' . $user[0], null, 60);
        }
    }
    // Do the actual logging...
    if (!empty($log_inserts) && !empty($modSettings['modlog_enabled'])) {
        smf_db_insert('', '{db_prefix}log_actions', array('log_time' => 'int', 'id_log' => 'int', 'id_member' => 'int', 'ip' => 'string-16', 'action' => 'string', 'id_board' => 'int', 'id_topic' => 'int', 'id_msg' => 'int', 'extra' => 'string-65534'), $log_inserts, array('id_action'));
    }
    // Make these peoples' posts guest posts.
    smf_db_query('
		UPDATE {db_prefix}messages
		SET id_member = {int:guest_id}, poster_email = {string:blank_email}
		WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'blank_email' => '', 'users' => $users));
    smf_db_query('
		UPDATE {db_prefix}polls
		SET id_member = {int:guest_id}
		WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    // Make these peoples' posts guest first posts and last posts.
    smf_db_query('
		UPDATE {db_prefix}topics
		SET id_member_started = {int:guest_id}
		WHERE id_member_started IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    smf_db_query('
		UPDATE {db_prefix}topics
		SET id_member_updated = {int:guest_id}
		WHERE id_member_updated IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    smf_db_query('
		UPDATE {db_prefix}log_actions
		SET id_member = {int:guest_id}
		WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    smf_db_query('
		UPDATE {db_prefix}log_banned
		SET id_member = {int:guest_id}
		WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    smf_db_query('
		UPDATE {db_prefix}log_errors
		SET id_member = {int:guest_id}
		WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    // Delete the member.
    smf_db_query('
		DELETE FROM {db_prefix}members
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // Delete the logs...
    smf_db_query('
		DELETE FROM {db_prefix}log_actions
		WHERE id_log = {int:log_type}
			AND id_member IN ({array_int:users})', array('log_type' => 2, 'users' => $users));
    smf_db_query('
		DELETE FROM {db_prefix}log_boards
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    smf_db_query('
		DELETE FROM {db_prefix}log_comments
		WHERE id_recipient IN ({array_int:users})
			AND comment_type = {string:warntpl}', array('users' => $users, 'warntpl' => 'warntpl'));
    smf_db_query('
		DELETE FROM {db_prefix}log_group_requests
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    smf_db_query('
		DELETE FROM {db_prefix}log_karma
		WHERE id_target IN ({array_int:users})
			OR id_executor IN ({array_int:users})', array('users' => $users));
    smf_db_query('
		DELETE FROM {db_prefix}log_mark_read
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    smf_db_query('
		DELETE FROM {db_prefix}log_notify
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    smf_db_query('
		DELETE FROM {db_prefix}log_online
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    smf_db_query('
		DELETE FROM {db_prefix}log_subscribed
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    smf_db_query('
		DELETE FROM {db_prefix}log_topics
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    smf_db_query('
		DELETE FROM {db_prefix}collapsed_categories
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // delete activities and corresponding notifications
    smf_db_query('
		DELETE a.*, n.* FROM {db_prefix}log_activities AS a LEFT JOIN {db_prefix}log_notifications AS n ON (n.id_act = a.id_act)
		WHERE a.id_member IN ({array_int:users})', array('users' => $users));
    // Make their votes appear as guest votes - at least it keeps the totals right.
    //!!! Consider adding back in cookie protection.
    smf_db_query('
		UPDATE {db_prefix}log_polls
		SET id_member = {int:guest_id}
		WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    // Delete personal messages.
    require_once $sourcedir . '/PersonalMessage.php';
    deleteMessages(null, null, $users);
    smf_db_query('
		UPDATE {db_prefix}personal_messages
		SET id_member_from = {int:guest_id}
		WHERE id_member_from IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    // They no longer exist, so we don't know who it was sent to.
    smf_db_query('
		DELETE FROM {db_prefix}pm_recipients
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    smf_db_query('
		DELETE FROM {db_prefix}drafts WHERE id_member IN ({array_int:members})', array('members' => $users));
    // Delete avatar.
    require_once $sourcedir . '/lib/Subs-ManageAttachments.php';
    removeAttachments(array('id_member' => $users));
    // It's over, no more moderation for you.
    smf_db_query('
		DELETE FROM {db_prefix}moderators
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    smf_db_query('
		DELETE FROM {db_prefix}group_moderators
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // If you don't exist we can't ban you.
    smf_db_query('
		DELETE FROM {db_prefix}ban_items
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // Remove individual theme settings.
    smf_db_query('
		DELETE FROM {db_prefix}themes
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // These users are nobody's buddy nomore.
    $request = smf_db_query('
		SELECT id_member, pm_ignore_list, buddy_list
		FROM {db_prefix}members
		WHERE FIND_IN_SET({raw:pm_ignore_list}, pm_ignore_list) != 0 OR FIND_IN_SET({raw:buddy_list}, buddy_list) != 0', array('pm_ignore_list' => implode(', pm_ignore_list) != 0 OR FIND_IN_SET(', $users), 'buddy_list' => implode(', buddy_list) != 0 OR FIND_IN_SET(', $users)));
    while ($row = mysql_fetch_assoc($request)) {
        smf_db_query('
			UPDATE {db_prefix}members
			SET
				pm_ignore_list = {string:pm_ignore_list},
				buddy_list = {string:buddy_list}
			WHERE id_member = {int:id_member}', array('id_member' => $row['id_member'], 'pm_ignore_list' => implode(',', array_diff(explode(',', $row['pm_ignore_list']), $users)), 'buddy_list' => implode(',', array_diff(explode(',', $row['buddy_list']), $users))));
    }
    mysql_free_result($request);
    // Make sure no member's birthday is still sticking in the calendar...
    updateSettings(array('calendar_updated' => time()));
    updateStats('member');
}
Beispiel #5
0
function Post2()
{
    global $board, $topic, $txt, $modSettings, $sourcedir, $context;
    global $user_info, $board_info, $options, $smcFunc;
    // Sneaking off, are we?
    if (empty($_POST) && empty($topic)) {
        redirectexit('action=post;board=' . $board . '.0');
    } elseif (empty($_POST) && !empty($topic)) {
        redirectexit('action=post;topic=' . $topic . '.0');
    }
    // No need!
    $context['robot_no_index'] = true;
    // If we came from WYSIWYG then turn it back into BBC regardless.
    if (!empty($_REQUEST['message_mode']) && isset($_REQUEST['message'])) {
        require_once $sourcedir . '/Subs-Editor.php';
        $_REQUEST['message'] = html_to_bbc($_REQUEST['message']);
        // We need to unhtml it now as it gets done shortly.
        $_REQUEST['message'] = un_htmlspecialchars($_REQUEST['message']);
        // We need this for everything else.
        $_POST['message'] = $_REQUEST['message'];
    }
    // Previewing? Go back to start.
    if (isset($_REQUEST['preview'])) {
        return Post();
    }
    // Prevent double submission of this form.
    checkSubmitOnce('check');
    // No errors as yet.
    $post_errors = array();
    // If the session has timed out, let the user re-submit their form.
    if (checkSession('post', '', false) != '') {
        $post_errors[] = 'session_timeout';
    }
    // Wrong verification code?
    if (!$user_info['is_admin'] && !$user_info['is_mod'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || $user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1)) {
        require_once $sourcedir . '/Subs-Editor.php';
        $verificationOptions = array('id' => 'post');
        $context['require_verification'] = create_control_verification($verificationOptions, true);
        if (is_array($context['require_verification'])) {
            $post_errors = array_merge($post_errors, $context['require_verification']);
        }
    }
    require_once $sourcedir . '/Subs-Post.php';
    loadLanguage('Post');
    // If this isn't a new topic load the topic info that we need.
    if (!empty($topic)) {
        $request = $smcFunc['db_query']('', '
			SELECT locked, is_sticky, id_poll, approved, id_first_msg, id_last_msg, id_member_started, id_board
			FROM {db_prefix}topics
			WHERE id_topic = {int:current_topic}
			LIMIT 1', array('current_topic' => $topic));
        $topic_info = $smcFunc['db_fetch_assoc']($request);
        $smcFunc['db_free_result']($request);
        // Though the topic should be there, it might have vanished.
        if (!is_array($topic_info)) {
            fatal_lang_error('topic_doesnt_exist');
        }
        // Did this topic suddenly move? Just checking...
        if ($topic_info['id_board'] != $board) {
            fatal_lang_error('not_a_topic');
        }
    }
    // Replying to a topic?
    if (!empty($topic) && !isset($_REQUEST['msg'])) {
        // Don't allow a post if it's locked.
        if ($topic_info['locked'] != 0 && !allowedTo('moderate_board')) {
            fatal_lang_error('topic_locked', false);
        }
        // Sorry, multiple polls aren't allowed... yet.  You should stop giving me ideas :P.
        if (isset($_REQUEST['poll']) && $topic_info['id_poll'] > 0) {
            unset($_REQUEST['poll']);
        }
        // Do the permissions and approval stuff...
        $becomesApproved = true;
        if ($topic_info['id_member_started'] != $user_info['id']) {
            if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_any') && !allowedTo('post_reply_any')) {
                $becomesApproved = false;
            } else {
                isAllowedTo('post_reply_any');
            }
        } elseif (!allowedTo('post_reply_any')) {
            if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_own') && !allowedTo('post_reply_own')) {
                $becomesApproved = false;
            } else {
                isAllowedTo('post_reply_own');
            }
        }
        if (isset($_POST['lock'])) {
            // Nothing is changed to the lock.
            if (empty($topic_info['locked']) && empty($_POST['lock']) || !empty($_POST['lock']) && !empty($topic_info['locked'])) {
                unset($_POST['lock']);
            } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $topic_info['id_member_started']) {
                unset($_POST['lock']);
            } elseif (!allowedTo('lock_any')) {
                // You cannot override a moderator lock.
                if ($topic_info['locked'] == 1) {
                    unset($_POST['lock']);
                } else {
                    $_POST['lock'] = empty($_POST['lock']) ? 0 : 2;
                }
            } else {
                $_POST['lock'] = empty($_POST['lock']) ? 0 : 1;
            }
        }
        // So you wanna (un)sticky this...let's see.
        if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || $_POST['sticky'] == $topic_info['is_sticky'] || !allowedTo('make_sticky'))) {
            unset($_POST['sticky']);
        }
        // If the number of replies has changed, if the setting is enabled, go back to Post() - which handles the error.
        if (empty($options['no_new_reply_warning']) && isset($_POST['last_msg']) && $topic_info['id_last_msg'] > $_POST['last_msg']) {
            $_REQUEST['preview'] = true;
            return Post();
        }
        $posterIsGuest = $user_info['is_guest'];
    } elseif (empty($topic)) {
        // Now don't be silly, new topics will get their own id_msg soon enough.
        unset($_REQUEST['msg'], $_POST['msg'], $_GET['msg']);
        // Do like, the permissions, for safety and stuff...
        $becomesApproved = true;
        if ($modSettings['postmod_active'] && !allowedTo('post_new') && allowedTo('post_unapproved_topics')) {
            $becomesApproved = false;
        } else {
            isAllowedTo('post_new');
        }
        if (isset($_POST['lock'])) {
            // New topics are by default not locked.
            if (empty($_POST['lock'])) {
                unset($_POST['lock']);
            } elseif (!allowedTo(array('lock_any', 'lock_own'))) {
                unset($_POST['lock']);
            } else {
                $_POST['lock'] = allowedTo('lock_any') ? 1 : 2;
            }
        }
        if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || empty($_POST['sticky']) || !allowedTo('make_sticky'))) {
            unset($_POST['sticky']);
        }
        $posterIsGuest = $user_info['is_guest'];
    } elseif (isset($_REQUEST['msg']) && !empty($topic)) {
        $_REQUEST['msg'] = (int) $_REQUEST['msg'];
        $request = $smcFunc['db_query']('', '
			SELECT id_member, poster_name, poster_email, poster_time, approved
			FROM {db_prefix}messages
			WHERE id_msg = {int:id_msg}
			LIMIT 1', array('id_msg' => $_REQUEST['msg']));
        if ($smcFunc['db_num_rows']($request) == 0) {
            fatal_lang_error('cant_find_messages', false);
        }
        $row = $smcFunc['db_fetch_assoc']($request);
        $smcFunc['db_free_result']($request);
        if (!empty($topic_info['locked']) && !allowedTo('moderate_board')) {
            fatal_lang_error('topic_locked', false);
        }
        if (isset($_POST['lock'])) {
            // Nothing changes to the lock status.
            if (empty($_POST['lock']) && empty($topic_info['locked']) || !empty($_POST['lock']) && !empty($topic_info['locked'])) {
                unset($_POST['lock']);
            } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $topic_info['id_member_started']) {
                unset($_POST['lock']);
            } elseif (!allowedTo('lock_any')) {
                // You're not allowed to break a moderator's lock.
                if ($topic_info['locked'] == 1) {
                    unset($_POST['lock']);
                } else {
                    $_POST['lock'] = empty($_POST['lock']) ? 0 : 2;
                }
            } else {
                $_POST['lock'] = empty($_POST['lock']) ? 0 : 1;
            }
        }
        // Change the sticky status of this topic?
        if (isset($_POST['sticky']) && (!allowedTo('make_sticky') || $_POST['sticky'] == $topic_info['is_sticky'])) {
            unset($_POST['sticky']);
        }
        if ($row['id_member'] == $user_info['id'] && !allowedTo('modify_any')) {
            if ((!$modSettings['postmod_active'] || $row['approved']) && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time()) {
                fatal_lang_error('modify_post_time_passed', false);
            } elseif ($topic_info['id_member_started'] == $user_info['id'] && !allowedTo('modify_own')) {
                isAllowedTo('modify_replies');
            } else {
                isAllowedTo('modify_own');
            }
        } elseif ($topic_info['id_member_started'] == $user_info['id'] && !allowedTo('modify_any')) {
            isAllowedTo('modify_replies');
            // If you're modifying a reply, I say it better be logged...
            $moderationAction = true;
        } else {
            isAllowedTo('modify_any');
            // Log it, assuming you're not modifying your own post.
            if ($row['id_member'] != $user_info['id']) {
                $moderationAction = true;
            }
        }
        $posterIsGuest = empty($row['id_member']);
        // Can they approve it?
        $can_approve = allowedTo('approve_posts');
        $becomesApproved = $modSettings['postmod_active'] ? $can_approve && !$row['approved'] ? !empty($_REQUEST['approve']) ? 1 : 0 : $row['approved'] : 1;
        $approve_has_changed = $row['approved'] != $becomesApproved;
        if (!allowedTo('moderate_forum') || !$posterIsGuest) {
            $_POST['guestname'] = $row['poster_name'];
            $_POST['email'] = $row['poster_email'];
        }
    }
    // If the poster is a guest evaluate the legality of name and email.
    if ($posterIsGuest) {
        $_POST['guestname'] = !isset($_POST['guestname']) ? '' : trim($_POST['guestname']);
        $_POST['email'] = !isset($_POST['email']) ? '' : trim($_POST['email']);
        if ($_POST['guestname'] == '' || $_POST['guestname'] == '_') {
            $post_errors[] = 'no_name';
        }
        if ($smcFunc['strlen']($_POST['guestname']) > 25) {
            $post_errors[] = 'long_name';
        }
        if (empty($modSettings['guest_post_no_email'])) {
            // Only check if they changed it!
            if (!isset($row) || $row['poster_email'] != $_POST['email']) {
                if (!allowedTo('moderate_forum') && (!isset($_POST['email']) || $_POST['email'] == '')) {
                    $post_errors[] = 'no_email';
                }
                if (!allowedTo('moderate_forum') && preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', $_POST['email']) == 0) {
                    $post_errors[] = 'bad_email';
                }
            }
            // Now make sure this email address is not banned from posting.
            isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt['guest_title']));
        }
        // In case they are making multiple posts this visit, help them along by storing their name.
        if (empty($post_errors)) {
            $_SESSION['guest_name'] = $_POST['guestname'];
            $_SESSION['guest_email'] = $_POST['email'];
        }
    }
    // Check the subject and message.
    if (!isset($_POST['subject']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['subject'])) === '') {
        $post_errors[] = 'no_subject';
    }
    if (!isset($_POST['message']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['message']), ENT_QUOTES) === '') {
        $post_errors[] = 'no_message';
    } elseif (!empty($modSettings['max_messageLength']) && $smcFunc['strlen']($_POST['message']) > $modSettings['max_messageLength']) {
        $post_errors[] = 'long_message';
    } else {
        // Prepare the message a bit for some additional testing.
        $_POST['message'] = $smcFunc['htmlspecialchars']($_POST['message'], ENT_QUOTES);
        // Preparse code. (Zef)
        if ($user_info['is_guest']) {
            $user_info['name'] = $_POST['guestname'];
        }
        preparsecode($_POST['message']);
        // Let's see if there's still some content left without the tags.
        if ($smcFunc['htmltrim'](strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['message'], '[html]') === false)) {
            $post_errors[] = 'no_message';
        }
    }
    if (isset($_POST['calendar']) && !isset($_REQUEST['deleteevent']) && $smcFunc['htmltrim']($_POST['evtitle']) === '') {
        $post_errors[] = 'no_event';
    }
    // You are not!
    if (isset($_POST['message']) && strtolower($_POST['message']) == 'i am the administrator.' && !$user_info['is_admin']) {
        fatal_error('Knave! Masquerader! Charlatan!', false);
    }
    // Validate the poll...
    if (isset($_REQUEST['poll']) && $modSettings['pollMode'] == '1') {
        if (!empty($topic) && !isset($_REQUEST['msg'])) {
            fatal_lang_error('no_access', false);
        }
        // This is a new topic... so it's a new poll.
        if (empty($topic)) {
            isAllowedTo('poll_post');
        } elseif ($user_info['id'] == $topic_info['id_member_started'] && !allowedTo('poll_add_any')) {
            isAllowedTo('poll_add_own');
        } else {
            isAllowedTo('poll_add_any');
        }
        if (!isset($_POST['question']) || trim($_POST['question']) == '') {
            $post_errors[] = 'no_question';
        }
        $_POST['options'] = empty($_POST['options']) ? array() : htmltrim__recursive($_POST['options']);
        // Get rid of empty ones.
        foreach ($_POST['options'] as $k => $option) {
            if ($option == '') {
                unset($_POST['options'][$k], $_POST['options'][$k]);
            }
        }
        // What are you going to vote between with one choice?!?
        if (count($_POST['options']) < 2) {
            $post_errors[] = 'poll_few';
        }
    }
    if ($posterIsGuest) {
        // If user is a guest, make sure the chosen name isn't taken.
        require_once $sourcedir . '/Subs-Members.php';
        if (isReservedName($_POST['guestname'], 0, true, false) && (!isset($row['poster_name']) || $_POST['guestname'] != $row['poster_name'])) {
            $post_errors[] = 'bad_name';
        }
    } elseif (!isset($_REQUEST['msg'])) {
        $_POST['guestname'] = $user_info['username'];
        $_POST['email'] = $user_info['email'];
    }
    // Any mistakes?
    if (!empty($post_errors)) {
        loadLanguage('Errors');
        // Previewing.
        $_REQUEST['preview'] = true;
        $context['post_error'] = array('messages' => array());
        foreach ($post_errors as $post_error) {
            $context['post_error'][$post_error] = true;
            if ($post_error == 'long_message') {
                $txt['error_' . $post_error] = sprintf($txt['error_' . $post_error], $modSettings['max_messageLength']);
            }
            $context['post_error']['messages'][] = $txt['error_' . $post_error];
        }
        return Post();
    }
    // Make sure the user isn't spamming the board.
    if (!isset($_REQUEST['msg'])) {
        spamProtection('post');
    }
    // At about this point, we're posting and that's that.
    ignore_user_abort(true);
    @set_time_limit(300);
    // Add special html entities to the subject, name, and email.
    $_POST['subject'] = strtr($smcFunc['htmlspecialchars']($_POST['subject']), array("\r" => '', "\n" => '', "\t" => ''));
    $_POST['guestname'] = htmlspecialchars($_POST['guestname']);
    $_POST['email'] = htmlspecialchars($_POST['email']);
    // At this point, we want to make sure the subject isn't too long.
    if ($smcFunc['strlen']($_POST['subject']) > 100) {
        $_POST['subject'] = $smcFunc['substr']($_POST['subject'], 0, 100);
    }
    // Make the poll...
    if (isset($_REQUEST['poll'])) {
        // Make sure that the user has not entered a ridiculous number of options..
        if (empty($_POST['poll_max_votes']) || $_POST['poll_max_votes'] <= 0) {
            $_POST['poll_max_votes'] = 1;
        } elseif ($_POST['poll_max_votes'] > count($_POST['options'])) {
            $_POST['poll_max_votes'] = count($_POST['options']);
        } else {
            $_POST['poll_max_votes'] = (int) $_POST['poll_max_votes'];
        }
        $_POST['poll_expire'] = (int) $_POST['poll_expire'];
        $_POST['poll_expire'] = $_POST['poll_expire'] > 9999 ? 9999 : ($_POST['poll_expire'] < 0 ? 0 : $_POST['poll_expire']);
        // Just set it to zero if it's not there..
        if (!isset($_POST['poll_hide'])) {
            $_POST['poll_hide'] = 0;
        } else {
            $_POST['poll_hide'] = (int) $_POST['poll_hide'];
        }
        $_POST['poll_change_vote'] = isset($_POST['poll_change_vote']) ? 1 : 0;
        $_POST['poll_guest_vote'] = isset($_POST['poll_guest_vote']) ? 1 : 0;
        // Make sure guests are actually allowed to vote generally.
        if ($_POST['poll_guest_vote']) {
            require_once $sourcedir . '/Subs-Members.php';
            $allowedVoteGroups = groupsAllowedTo('poll_vote', $board);
            if (!in_array(-1, $allowedVoteGroups['allowed'])) {
                $_POST['poll_guest_vote'] = 0;
            }
        }
        // If the user tries to set the poll too far in advance, don't let them.
        if (!empty($_POST['poll_expire']) && $_POST['poll_expire'] < 1) {
            fatal_lang_error('poll_range_error', false);
        } elseif (empty($_POST['poll_expire']) && $_POST['poll_hide'] == 2) {
            $_POST['poll_hide'] = 1;
        }
        // Clean up the question and answers.
        $_POST['question'] = htmlspecialchars($_POST['question']);
        $_POST['question'] = $smcFunc['truncate']($_POST['question'], 255);
        $_POST['question'] = preg_replace('~&amp;#(\\d{4,5}|[2-9]\\d{2,4}|1[2-9]\\d);~', '&#$1;', $_POST['question']);
        $_POST['options'] = htmlspecialchars__recursive($_POST['options']);
    }
    // Check if they are trying to delete any current attachments....
    if (isset($_REQUEST['msg'], $_POST['attach_del']) && (allowedTo('post_attachment') || $modSettings['postmod_active'] && allowedTo('post_unapproved_attachments'))) {
        $del_temp = array();
        foreach ($_POST['attach_del'] as $i => $dummy) {
            $del_temp[$i] = (int) $dummy;
        }
        require_once $sourcedir . '/ManageAttachments.php';
        $attachmentQuery = array('attachment_type' => 0, 'id_msg' => (int) $_REQUEST['msg'], 'not_id_attach' => $del_temp);
        removeAttachments($attachmentQuery);
    }
    // ...or attach a new file...
    if (isset($_FILES['attachment']['name']) || !empty($_SESSION['temp_attachments']) && empty($_POST['from_qr'])) {
        // Verify they can post them!
        if (!$modSettings['postmod_active'] || !allowedTo('post_unapproved_attachments')) {
            isAllowedTo('post_attachment');
        }
        // Make sure we're uploading to the right place.
        if (!empty($modSettings['currentAttachmentUploadDir'])) {
            if (!is_array($modSettings['attachmentUploadDir'])) {
                $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
            }
            // The current directory, of course!
            $current_attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
        } else {
            $current_attach_dir = $modSettings['attachmentUploadDir'];
        }
        // If this isn't a new post, check the current attachments.
        if (isset($_REQUEST['msg'])) {
            $request = $smcFunc['db_query']('', '
				SELECT COUNT(*), SUM(size)
				FROM {db_prefix}attachments
				WHERE id_msg = {int:id_msg}
					AND attachment_type = {int:attachment_type}', array('id_msg' => (int) $_REQUEST['msg'], 'attachment_type' => 0));
            list($quantity, $total_size) = $smcFunc['db_fetch_row']($request);
            $smcFunc['db_free_result']($request);
        } else {
            $quantity = 0;
            $total_size = 0;
        }
        if (!empty($_SESSION['temp_attachments'])) {
            foreach ($_SESSION['temp_attachments'] as $attachID => $name) {
                if (preg_match('~^post_tmp_' . $user_info['id'] . '_\\d+$~', $attachID) == 0) {
                    continue;
                }
                if (!empty($_POST['attach_del']) && !in_array($attachID, $_POST['attach_del'])) {
                    unset($_SESSION['temp_attachments'][$attachID]);
                    @unlink($current_attach_dir . '/' . $attachID);
                    continue;
                }
                $_FILES['attachment']['tmp_name'][] = $attachID;
                $_FILES['attachment']['name'][] = $name;
                $_FILES['attachment']['size'][] = filesize($current_attach_dir . '/' . $attachID);
                list($_FILES['attachment']['width'][], $_FILES['attachment']['height'][]) = @getimagesize($current_attach_dir . '/' . $attachID);
                unset($_SESSION['temp_attachments'][$attachID]);
            }
        }
        if (!isset($_FILES['attachment']['name'])) {
            $_FILES['attachment']['tmp_name'] = array();
        }
        $attachIDs = array();
        foreach ($_FILES['attachment']['tmp_name'] as $n => $dummy) {
            if ($_FILES['attachment']['name'][$n] == '') {
                continue;
            }
            // Have we reached the maximum number of files we are allowed?
            $quantity++;
            if (!empty($modSettings['attachmentNumPerPostLimit']) && $quantity > $modSettings['attachmentNumPerPostLimit']) {
                checkSubmitOnce('free');
                fatal_lang_error('attachments_limit_per_post', false, array($modSettings['attachmentNumPerPostLimit']));
            }
            // Check the total upload size for this post...
            $total_size += $_FILES['attachment']['size'][$n];
            if (!empty($modSettings['attachmentPostLimit']) && $total_size > $modSettings['attachmentPostLimit'] * 1024) {
                checkSubmitOnce('free');
                fatal_lang_error('file_too_big', false, array($modSettings['attachmentPostLimit']));
            }
            $attachmentOptions = array('post' => isset($_REQUEST['msg']) ? $_REQUEST['msg'] : 0, 'poster' => $user_info['id'], 'name' => $_FILES['attachment']['name'][$n], 'tmp_name' => $_FILES['attachment']['tmp_name'][$n], 'size' => $_FILES['attachment']['size'][$n], 'approved' => !$modSettings['postmod_active'] || allowedTo('post_attachment'));
            if (createAttachment($attachmentOptions)) {
                $attachIDs[] = $attachmentOptions['id'];
                if (!empty($attachmentOptions['thumb'])) {
                    $attachIDs[] = $attachmentOptions['thumb'];
                }
            } else {
                if (in_array('could_not_upload', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_lang_error('attach_timeout', 'critical');
                }
                if (in_array('too_large', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_lang_error('file_too_big', false, array($modSettings['attachmentSizeLimit']));
                }
                if (in_array('bad_extension', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_error($attachmentOptions['name'] . '.<br />' . $txt['cant_upload_type'] . ' ' . $modSettings['attachmentExtensions'] . '.', false);
                }
                if (in_array('directory_full', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_lang_error('ran_out_of_space', 'critical');
                }
                if (in_array('bad_filename', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_error(basename($attachmentOptions['name']) . '.<br />' . $txt['restricted_filename'] . '.', 'critical');
                }
                if (in_array('taken_filename', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_lang_error('filename_exists');
                }
                if (in_array('bad_attachment', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_lang_error('bad_attachment');
                }
            }
        }
    }
    // Make the poll...
    if (isset($_REQUEST['poll'])) {
        // Create the poll.
        $smcFunc['db_insert']('', '{db_prefix}polls', array('question' => 'string-255', 'hide_results' => 'int', 'max_votes' => 'int', 'expire_time' => 'int', 'id_member' => 'int', 'poster_name' => 'string-255', 'change_vote' => 'int', 'guest_vote' => 'int'), array($_POST['question'], $_POST['poll_hide'], $_POST['poll_max_votes'], empty($_POST['poll_expire']) ? 0 : time() + $_POST['poll_expire'] * 3600 * 24, $user_info['id'], $_POST['guestname'], $_POST['poll_change_vote'], $_POST['poll_guest_vote']), array('id_poll'));
        $id_poll = $smcFunc['db_insert_id']('{db_prefix}polls', 'id_poll');
        // Create each answer choice.
        $i = 0;
        $pollOptions = array();
        foreach ($_POST['options'] as $option) {
            $pollOptions[] = array($id_poll, $i, $option);
            $i++;
        }
        $smcFunc['db_insert']('insert', '{db_prefix}poll_choices', array('id_poll' => 'int', 'id_choice' => 'int', 'label' => 'string-255'), $pollOptions, array('id_poll', 'id_choice'));
    } else {
        $id_poll = 0;
    }
    // Creating a new topic?
    $newTopic = empty($_REQUEST['msg']) && empty($topic);
    $_POST['icon'] = !empty($attachIDs) && $_POST['icon'] == 'xx' ? 'clip' : $_POST['icon'];
    // Collect all parameters for the creation or modification of a post.
    $msgOptions = array('id' => empty($_REQUEST['msg']) ? 0 : (int) $_REQUEST['msg'], 'subject' => $_POST['subject'], 'body' => $_POST['message'], 'icon' => preg_replace('~[\\./\\\\*:"\'<>]~', '', $_POST['icon']), 'smileys_enabled' => !isset($_POST['ns']), 'attachments' => empty($attachIDs) ? array() : $attachIDs, 'approved' => $becomesApproved);
    $topicOptions = array('id' => empty($topic) ? 0 : $topic, 'board' => $board, 'poll' => isset($_REQUEST['poll']) ? $id_poll : null, 'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null, 'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null, 'mark_as_read' => true, 'is_approved' => !$modSettings['postmod_active'] || empty($topic) || !empty($board_info['cur_topic_approved']));
    $posterOptions = array('id' => $user_info['id'], 'name' => $_POST['guestname'], 'email' => $_POST['email'], 'update_post_count' => !$user_info['is_guest'] && !isset($_REQUEST['msg']) && $board_info['posts_count']);
    // This is an already existing message. Edit it.
    if (!empty($_REQUEST['msg'])) {
        // Have admins allowed people to hide their screwups?
        if (time() - $row['poster_time'] > $modSettings['edit_wait_time'] || $user_info['id'] != $row['id_member']) {
            $msgOptions['modify_time'] = time();
            $msgOptions['modify_name'] = $user_info['name'];
        }
        // This will save some time...
        if (empty($approve_has_changed)) {
            unset($msgOptions['approved']);
        }
        modifyPost($msgOptions, $topicOptions, $posterOptions);
    } else {
        createPost($msgOptions, $topicOptions, $posterOptions);
        if (isset($topicOptions['id'])) {
            $topic = $topicOptions['id'];
        }
    }
    // Editing or posting an event?
    if (isset($_POST['calendar']) && (!isset($_REQUEST['eventid']) || $_REQUEST['eventid'] == -1)) {
        require_once $sourcedir . '/Subs-Calendar.php';
        // Make sure they can link an event to this post.
        canLinkEvent();
        // Insert the event.
        $eventOptions = array('board' => $board, 'topic' => $topic, 'title' => $_POST['evtitle'], 'member' => $user_info['id'], 'start_date' => sprintf('%04d-%02d-%02d', $_POST['year'], $_POST['month'], $_POST['day']), 'span' => isset($_POST['span']) && $_POST['span'] > 0 ? min((int) $modSettings['cal_maxspan'], (int) $_POST['span'] - 1) : 0);
        insertEvent($eventOptions);
    } elseif (isset($_POST['calendar'])) {
        $_REQUEST['eventid'] = (int) $_REQUEST['eventid'];
        // Validate the post...
        require_once $sourcedir . '/Subs-Calendar.php';
        validateEventPost();
        // If you're not allowed to edit any events, you have to be the poster.
        if (!allowedTo('calendar_edit_any')) {
            // Get the event's poster.
            $request = $smcFunc['db_query']('', '
				SELECT id_member
				FROM {db_prefix}calendar
				WHERE id_event = {int:id_event}', array('id_event' => $_REQUEST['eventid']));
            $row2 = $smcFunc['db_fetch_assoc']($request);
            $smcFunc['db_free_result']($request);
            // Silly hacker, Trix are for kids. ...probably trademarked somewhere, this is FAIR USE! (parody...)
            isAllowedTo('calendar_edit_' . ($row2['id_member'] == $user_info['id'] ? 'own' : 'any'));
        }
        // Delete it?
        if (isset($_REQUEST['deleteevent'])) {
            $smcFunc['db_query']('', '
				DELETE FROM {db_prefix}calendar
				WHERE id_event = {int:id_event}', array('id_event' => $_REQUEST['eventid']));
        } else {
            $span = !empty($modSettings['cal_allowspan']) && !empty($_REQUEST['span']) ? min((int) $modSettings['cal_maxspan'], (int) $_REQUEST['span'] - 1) : 0;
            $start_time = mktime(0, 0, 0, (int) $_REQUEST['month'], (int) $_REQUEST['day'], (int) $_REQUEST['year']);
            $smcFunc['db_query']('', '
				UPDATE {db_prefix}calendar
				SET end_date = {date:end_date},
					start_date = {date:start_date},
					title = {string:title}
				WHERE id_event = {int:id_event}', array('end_date' => strftime('%Y-%m-%d', $start_time + $span * 86400), 'start_date' => strftime('%Y-%m-%d', $start_time), 'id_event' => $_REQUEST['eventid'], 'title' => $smcFunc['htmlspecialchars']($_REQUEST['evtitle'], ENT_QUOTES)));
        }
        updateSettings(array('calendar_updated' => time()));
    }
    // Marking read should be done even for editing messages....
    // Mark all the parents read.  (since you just posted and they will be unread.)
    if (!$user_info['is_guest'] && !empty($board_info['parent_boards'])) {
        $smcFunc['db_query']('', '
			UPDATE {db_prefix}log_boards
			SET id_msg = {int:id_msg}
			WHERE id_member = {int:current_member}
				AND id_board IN ({array_int:board_list})', array('current_member' => $user_info['id'], 'board_list' => array_keys($board_info['parent_boards']), 'id_msg' => $modSettings['maxMsgID']));
    }
    // Turn notification on or off.  (note this just blows smoke if it's already on or off.)
    if (!empty($_POST['notify']) && allowedTo('mark_any_notify')) {
        $smcFunc['db_insert']('ignore', '{db_prefix}log_notify', array('id_member' => 'int', 'id_topic' => 'int', 'id_board' => 'int'), array($user_info['id'], $topic, 0), array('id_member', 'id_topic', 'id_board'));
    } elseif (!$newTopic) {
        $smcFunc['db_query']('', '
			DELETE FROM {db_prefix}log_notify
			WHERE id_member = {int:current_member}
				AND id_topic = {int:current_topic}', array('current_member' => $user_info['id'], 'current_topic' => $topic));
    }
    // Log an act of moderation - modifying.
    if (!empty($moderationAction)) {
        logAction('modify', array('topic' => $topic, 'message' => (int) $_REQUEST['msg'], 'member' => $row['id_member'], 'board' => $board));
    }
    if (isset($_POST['lock']) && $_POST['lock'] != 2) {
        logAction('lock', array('topic' => $topicOptions['id'], 'board' => $topicOptions['board']));
    }
    if (isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics'])) {
        logAction('sticky', array('topic' => $topicOptions['id'], 'board' => $topicOptions['board']));
    }
    // Notify any members who have notification turned on for this topic - only do this if it's going to be approved(!)
    if ($becomesApproved) {
        if ($newTopic) {
            $notifyData = array('body' => $_POST['message'], 'subject' => $_POST['subject'], 'name' => $user_info['name'], 'poster' => $user_info['id'], 'msg' => $msgOptions['id'], 'board' => $board, 'topic' => $topic);
            notifyMembersBoard($notifyData);
        } elseif (empty($_REQUEST['msg'])) {
            // Only send it to everyone if the topic is approved, otherwise just to the topic starter if they want it.
            if ($topic_info['approved']) {
                sendNotifications($topic, 'reply');
            } else {
                sendNotifications($topic, 'reply', array(), $topic_info['id_member_started']);
            }
        }
    }
    // Returning to the topic?
    if (!empty($_REQUEST['goback'])) {
        // Mark the board as read.... because it might get confusing otherwise.
        $smcFunc['db_query']('', '
			UPDATE {db_prefix}log_boards
			SET id_msg = {int:maxMsgID}
			WHERE id_member = {int:current_member}
				AND id_board = {int:current_board}', array('current_board' => $board, 'current_member' => $user_info['id'], 'maxMsgID' => $modSettings['maxMsgID']));
    }
    if ($board_info['num_topics'] == 0) {
        cache_put_data('board-' . $board, null, 120);
    }
    if (!empty($_POST['announce_topic'])) {
        redirectexit('action=announce;sa=selectgroup;topic=' . $topic . (!empty($_POST['move']) && allowedTo('move_any') ? ';move' : '') . (empty($_REQUEST['goback']) ? '' : ';goback'));
    }
    if (!empty($_POST['move']) && allowedTo('move_any')) {
        redirectexit('action=movetopic;topic=' . $topic . '.0' . (empty($_REQUEST['goback']) ? '' : ';goback'));
    }
    // Return to post if the mod is on.
    if (isset($_REQUEST['msg']) && !empty($_REQUEST['goback'])) {
        redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg'], $context['browser']['is_ie']);
    } elseif (!empty($_REQUEST['goback'])) {
        redirectexit('topic=' . $topic . '.new#new', $context['browser']['is_ie']);
    } else {
        redirectexit('board=' . $board . '.0');
    }
}
Beispiel #6
0
/**
 * Remove a specific message (including permission checks).
 * - normally, local and global should be the localCookies and globalCookies settings, respectively.
 * - uses boardurl to determine these two things.
 *
 * @param int $message The message id
 * @param bool $decreasePostCount if true users' post count will be reduced
 * @return array an array to set the cookie on with domain and path in it, in that order
 */
function removeMessage($message, $decreasePostCount = true)
{
    global $board, $sourcedir, $modSettings, $user_info, $smcFunc, $context;
    if (empty($message) || !is_numeric($message)) {
        return false;
    }
    $request = $smcFunc['db_query']('', '
		SELECT
			m.id_member, m.icon, m.poster_time, m.subject,' . (empty($modSettings['search_custom_index_config']) ? '' : ' m.body,') . '
			m.approved, t.id_topic, t.id_first_msg, t.id_last_msg, t.num_replies, t.id_board,
			t.id_member_started AS id_member_poster,
			b.count_posts
		FROM {db_prefix}messages AS m
			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = t.id_board)
		WHERE m.id_msg = {int:id_msg}
		LIMIT 1', array('id_msg' => $message));
    if ($smcFunc['db_num_rows']($request) == 0) {
        return false;
    }
    $row = $smcFunc['db_fetch_assoc']($request);
    $smcFunc['db_free_result']($request);
    if (empty($board) || $row['id_board'] != $board) {
        $delete_any = boardsAllowedTo('delete_any');
        if (!in_array(0, $delete_any) && !in_array($row['id_board'], $delete_any)) {
            $delete_own = boardsAllowedTo('delete_own');
            $delete_own = in_array(0, $delete_own) || in_array($row['id_board'], $delete_own);
            $delete_replies = boardsAllowedTo('delete_replies');
            $delete_replies = in_array(0, $delete_replies) || in_array($row['id_board'], $delete_replies);
            if ($row['id_member'] == $user_info['id']) {
                if (!$delete_own) {
                    if ($row['id_member_poster'] == $user_info['id']) {
                        if (!$delete_replies) {
                            fatal_lang_error('cannot_delete_replies', 'permission');
                        }
                    } else {
                        fatal_lang_error('cannot_delete_own', 'permission');
                    }
                } elseif (($row['id_member_poster'] != $user_info['id'] || !$delete_replies) && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + $modSettings['edit_disable_time'] * 60 < time()) {
                    fatal_lang_error('modify_post_time_passed', false);
                }
            } elseif ($row['id_member_poster'] == $user_info['id']) {
                if (!$delete_replies) {
                    fatal_lang_error('cannot_delete_replies', 'permission');
                }
            } else {
                fatal_lang_error('cannot_delete_any', 'permission');
            }
        }
        // Can't delete an unapproved message, if you can't see it!
        if ($modSettings['postmod_active'] && !$row['approved'] && $row['id_member'] != $user_info['id'] && !(in_array(0, $delete_any) || in_array($row['id_board'], $delete_any))) {
            $approve_posts = boardsAllowedTo('approve_posts');
            if (!in_array(0, $approve_posts) && !in_array($row['id_board'], $approve_posts)) {
                return false;
            }
        }
    } else {
        // Check permissions to delete this message.
        if ($row['id_member'] == $user_info['id']) {
            if (!allowedTo('delete_own')) {
                if ($row['id_member_poster'] == $user_info['id'] && !allowedTo('delete_any')) {
                    isAllowedTo('delete_replies');
                } elseif (!allowedTo('delete_any')) {
                    isAllowedTo('delete_own');
                }
            } elseif (!allowedTo('delete_any') && ($row['id_member_poster'] != $user_info['id'] || !allowedTo('delete_replies')) && !empty($modSettings['edit_disable_time']) && $row['poster_time'] + $modSettings['edit_disable_time'] * 60 < time()) {
                fatal_lang_error('modify_post_time_passed', false);
            }
        } elseif ($row['id_member_poster'] == $user_info['id'] && !allowedTo('delete_any')) {
            isAllowedTo('delete_replies');
        } else {
            isAllowedTo('delete_any');
        }
        if ($modSettings['postmod_active'] && !$row['approved'] && $row['id_member'] != $user_info['id'] && !allowedTo('delete_own')) {
            isAllowedTo('approve_posts');
        }
    }
    // Close any moderation reports for this message.
    $smcFunc['db_query']('', '
		UPDATE {db_prefix}log_reported
		SET closed = {int:is_closed}
		WHERE id_msg = {int:id_msg}', array('is_closed' => 1, 'id_msg' => $message));
    if ($smcFunc['db_affected_rows']() != 0) {
        require_once $sourcedir . '/ModerationCenter.php';
        updateSettings(array('last_mod_report_action' => time()));
        recountOpenReports();
    }
    // Delete the *whole* topic, but only if the topic consists of one message.
    if ($row['id_first_msg'] == $message) {
        if (empty($board) || $row['id_board'] != $board) {
            $remove_any = boardsAllowedTo('remove_any');
            $remove_any = in_array(0, $remove_any) || in_array($row['id_board'], $remove_any);
            if (!$remove_any) {
                $remove_own = boardsAllowedTo('remove_own');
                $remove_own = in_array(0, $remove_own) || in_array($row['id_board'], $remove_own);
            }
            if ($row['id_member'] != $user_info['id'] && !$remove_any) {
                fatal_lang_error('cannot_remove_any', 'permission');
            } elseif (!$remove_any && !$remove_own) {
                fatal_lang_error('cannot_remove_own', 'permission');
            }
        } else {
            // Check permissions to delete a whole topic.
            if ($row['id_member'] != $user_info['id']) {
                isAllowedTo('remove_any');
            } elseif (!allowedTo('remove_any')) {
                isAllowedTo('remove_own');
            }
        }
        // ...if there is only one post.
        if (!empty($row['num_replies'])) {
            fatal_lang_error('delFirstPost', false);
        }
        removeTopics($row['id_topic']);
        return true;
    }
    // Deleting a recycled message can not lower anyone's post count.
    if ($row['icon'] == 'recycled') {
        $decreasePostCount = false;
    }
    // This is the last post, update the last post on the board.
    if ($row['id_last_msg'] == $message) {
        // Find the last message, set it, and decrease the post count.
        $request = $smcFunc['db_query']('', '
			SELECT id_msg, id_member
			FROM {db_prefix}messages
			WHERE id_topic = {int:id_topic}
				AND id_msg != {int:id_msg}
			ORDER BY ' . ($modSettings['postmod_active'] ? 'approved DESC, ' : '') . 'id_msg DESC
			LIMIT 1', array('id_topic' => $row['id_topic'], 'id_msg' => $message));
        $row2 = $smcFunc['db_fetch_assoc']($request);
        $smcFunc['db_free_result']($request);
        $smcFunc['db_query']('', '
			UPDATE {db_prefix}topics
			SET
				id_last_msg = {int:id_last_msg},
				id_member_updated = {int:id_member_updated}' . (!$modSettings['postmod_active'] || $row['approved'] ? ',
				num_replies = CASE WHEN num_replies = {int:no_replies} THEN 0 ELSE num_replies - 1 END' : ',
				unapproved_posts = CASE WHEN unapproved_posts = {int:no_unapproved} THEN 0 ELSE unapproved_posts - 1 END') . '
			WHERE id_topic = {int:id_topic}', array('id_last_msg' => $row2['id_msg'], 'id_member_updated' => $row2['id_member'], 'no_replies' => 0, 'no_unapproved' => 0, 'id_topic' => $row['id_topic']));
    } else {
        $smcFunc['db_query']('', '
			UPDATE {db_prefix}topics
			SET ' . ($row['approved'] ? '
				num_replies = CASE WHEN num_replies = {int:no_replies} THEN 0 ELSE num_replies - 1 END' : '
				unapproved_posts = CASE WHEN unapproved_posts = {int:no_unapproved} THEN 0 ELSE unapproved_posts - 1 END') . '
			WHERE id_topic = {int:id_topic}', array('no_replies' => 0, 'no_unapproved' => 0, 'id_topic' => $row['id_topic']));
    }
    // Default recycle to false.
    $recycle = false;
    // If recycle topics has been set, make a copy of this message in the recycle board.
    // Make sure we're not recycling messages that are already on the recycle board.
    if (!empty($modSettings['recycle_enable']) && $row['id_board'] != $modSettings['recycle_board'] && $row['icon'] != 'recycled') {
        // Check if the recycle board exists and if so get the read status.
        $request = $smcFunc['db_query']('', '
			SELECT (IFNULL(lb.id_msg, 0) >= b.id_msg_updated) AS is_seen, id_last_msg
			FROM {db_prefix}boards AS b
				LEFT JOIN {db_prefix}log_boards AS lb ON (lb.id_board = b.id_board AND lb.id_member = {int:current_member})
			WHERE b.id_board = {int:recycle_board}', array('current_member' => $user_info['id'], 'recycle_board' => $modSettings['recycle_board']));
        if ($smcFunc['db_num_rows']($request) == 0) {
            fatal_lang_error('recycle_no_valid_board');
        }
        list($isRead, $last_board_msg) = $smcFunc['db_fetch_row']($request);
        $smcFunc['db_free_result']($request);
        // Is there an existing topic in the recycle board to group this post with?
        $request = $smcFunc['db_query']('', '
			SELECT id_topic, id_first_msg, id_last_msg
			FROM {db_prefix}topics
			WHERE id_previous_topic = {int:id_previous_topic}
				AND id_board = {int:recycle_board}', array('id_previous_topic' => $row['id_topic'], 'recycle_board' => $modSettings['recycle_board']));
        list($id_recycle_topic, $first_topic_msg, $last_topic_msg) = $smcFunc['db_fetch_row']($request);
        $smcFunc['db_free_result']($request);
        // Insert a new topic in the recycle board if $id_recycle_topic is empty.
        if (empty($id_recycle_topic)) {
            $smcFunc['db_insert']('', '{db_prefix}topics', array('id_board' => 'int', 'id_member_started' => 'int', 'id_member_updated' => 'int', 'id_first_msg' => 'int', 'id_last_msg' => 'int', 'unapproved_posts' => 'int', 'approved' => 'int', 'id_previous_topic' => 'int'), array($modSettings['recycle_board'], $row['id_member'], $row['id_member'], $message, $message, 0, 1, $row['id_topic']), array('id_topic'));
        }
        // Capture the ID of the new topic...
        $topicID = empty($id_recycle_topic) ? $smcFunc['db_insert_id']('{db_prefix}topics', 'id_topic') : $id_recycle_topic;
        // If the topic creation went successful, move the message.
        if ($topicID > 0) {
            $smcFunc['db_query']('', '
				UPDATE {db_prefix}messages
				SET
					id_topic = {int:id_topic},
					id_board = {int:recycle_board},
					icon = {string:recycled},
					approved = {int:is_approved}
				WHERE id_msg = {int:id_msg}', array('id_topic' => $topicID, 'recycle_board' => $modSettings['recycle_board'], 'id_msg' => $message, 'recycled' => 'recycled', 'is_approved' => 1));
            // Take any reported posts with us...
            $smcFunc['db_query']('', '
				UPDATE {db_prefix}log_reported
				SET
					id_topic = {int:id_topic},
					id_board = {int:recycle_board}
				WHERE id_msg = {int:id_msg}', array('id_topic' => $topicID, 'recycle_board' => $modSettings['recycle_board'], 'id_msg' => $message));
            // Mark recycled topic as read.
            if (!$user_info['is_guest']) {
                $smcFunc['db_insert']('replace', '{db_prefix}log_topics', array('id_topic' => 'int', 'id_member' => 'int', 'id_msg' => 'int'), array($topicID, $user_info['id'], $modSettings['maxMsgID']), array('id_topic', 'id_member'));
            }
            // Mark recycle board as seen, if it was marked as seen before.
            if (!empty($isRead) && !$user_info['is_guest']) {
                $smcFunc['db_insert']('replace', '{db_prefix}log_boards', array('id_board' => 'int', 'id_member' => 'int', 'id_msg' => 'int'), array($modSettings['recycle_board'], $user_info['id'], $modSettings['maxMsgID']), array('id_board', 'id_member'));
            }
            // Add one topic and post to the recycle bin board.
            $smcFunc['db_query']('', '
				UPDATE {db_prefix}boards
				SET
					num_topics = num_topics + {int:num_topics_inc},
					num_posts = num_posts + 1' . ($message > $last_board_msg ? ', id_last_msg = {int:id_merged_msg}' : '') . '
				WHERE id_board = {int:recycle_board}', array('num_topics_inc' => empty($id_recycle_topic) ? 1 : 0, 'recycle_board' => $modSettings['recycle_board'], 'id_merged_msg' => $message));
            // Lets increase the num_replies, and the first/last message ID as appropriate.
            if (!empty($id_recycle_topic)) {
                $smcFunc['db_query']('', '
					UPDATE {db_prefix}topics
					SET num_replies = num_replies + 1' . ($message > $last_topic_msg ? ', id_last_msg = {int:id_merged_msg}' : '') . ($message < $first_topic_msg ? ', id_first_msg = {int:id_merged_msg}' : '') . '
					WHERE id_topic = {int:id_recycle_topic}', array('id_recycle_topic' => $id_recycle_topic, 'id_merged_msg' => $message));
            }
            // Make sure this message isn't getting deleted later on.
            $recycle = true;
            // Make sure we update the search subject index.
            updateStats('subject', $topicID, $row['subject']);
        }
        // If it wasn't approved don't keep it in the queue.
        if (!$row['approved']) {
            $smcFunc['db_query']('', '
				DELETE FROM {db_prefix}approval_queue
				WHERE id_msg = {int:id_msg}
					AND id_attach = {int:id_attach}', array('id_msg' => $message, 'id_attach' => 0));
        }
    }
    $smcFunc['db_query']('', '
		UPDATE {db_prefix}boards
		SET ' . ($row['approved'] ? '
			num_posts = CASE WHEN num_posts = {int:no_posts} THEN 0 ELSE num_posts - 1 END' : '
			unapproved_posts = CASE WHEN unapproved_posts = {int:no_unapproved} THEN 0 ELSE unapproved_posts - 1 END') . '
		WHERE id_board = {int:id_board}', array('no_posts' => 0, 'no_unapproved' => 0, 'id_board' => $row['id_board']));
    // If the poster was registered and the board this message was on incremented
    // the member's posts when it was posted, decrease his or her post count.
    if (!empty($row['id_member']) && $decreasePostCount && empty($row['count_posts']) && $row['approved']) {
        updateMemberData($row['id_member'], array('posts' => '-'));
    }
    // Only remove posts if they're not recycled.
    if (!$recycle) {
        // Remove the message!
        $smcFunc['db_query']('', '
			DELETE FROM {db_prefix}messages
			WHERE id_msg = {int:id_msg}', array('id_msg' => $message));
        if (!empty($modSettings['search_custom_index_config'])) {
            $customIndexSettings = unserialize($modSettings['search_custom_index_config']);
            $words = text2words($row['body'], $customIndexSettings['bytes_per_word'], true);
            if (!empty($words)) {
                $smcFunc['db_query']('', '
					DELETE FROM {db_prefix}log_search_words
					WHERE id_word IN ({array_int:word_list})
						AND id_msg = {int:id_msg}', array('word_list' => $words, 'id_msg' => $message));
            }
        }
        // Delete attachment(s) if they exist.
        require_once $sourcedir . '/ManageAttachments.php';
        $attachmentQuery = array('attachment_type' => 0, 'id_msg' => $message);
        removeAttachments($attachmentQuery);
        // Allow mods to remove message related data of their own (likes, maybe?)
        call_integration_hook('integrate_remove_message', array($message));
    }
    // Update the pesky statistics.
    updateStats('message');
    updateStats('topic');
    updateSettings(array('calendar_updated' => time()));
    // And now to update the last message of each board we messed with.
    require_once $sourcedir . '/Subs-Post.php';
    if ($recycle) {
        updateLastMessages(array($row['id_board'], $modSettings['recycle_board']));
    } else {
        updateLastMessages($row['id_board']);
    }
    return false;
}
function ApproveAttach()
{
    global $smcFunc;
    // Security is our primary concern...
    checkSession('get');
    // If it approve or delete?
    $is_approve = !isset($_GET['sa']) || $_GET['sa'] != 'reject' ? true : false;
    $attachments = array();
    // If we are approving all ID's in a message , get the ID's.
    if ($_GET['sa'] == 'all' && !empty($_GET['mid'])) {
        $id_msg = (int) $_GET['mid'];
        $request = $smcFunc['db_query']('', '
			SELECT id_attach
			FROM {db_prefix}attachments
			WHERE id_msg = {int:id_msg}
				AND approved = {int:is_approved}
				AND attachment_type = {int:attachment_type}', array('id_msg' => $id_msg, 'is_approved' => 0, 'attachment_type' => 0));
        while ($row = $smcFunc['db_fetch_assoc']($request)) {
            $attachments[] = $row['id_attach'];
        }
        $smcFunc['db_free_result']($request);
    } elseif (!empty($_GET['aid'])) {
        $attachments[] = (int) $_GET['aid'];
    }
    if (empty($attachments)) {
        fatal_lang_error('no_access', false);
    }
    // Now we have some ID's cleaned and ready to approve, but first - let's check we have permission!
    $allowed_boards = boardsAllowedTo('approve_posts');
    // Validate the attachments exist and are the right approval state.
    $request = $smcFunc['db_query']('', '
		SELECT a.id_attach, m.id_board, m.id_msg, m.id_topic
		FROM {db_prefix}attachments AS a
			INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)
		WHERE a.id_attach IN ({array_int:attachments})
			AND a.attachment_type = {int:attachment_type}
			AND a.approved = {int:is_approved}', array('attachments' => $attachments, 'attachment_type' => 0, 'is_approved' => 0));
    $attachments = array();
    while ($row = $smcFunc['db_fetch_assoc']($request)) {
        // We can only add it if we can approve in this board!
        if ($allowed_boards = array(0) || in_array($row['id_board'], $allowed_boards)) {
            $attachments[] = $row['id_attach'];
            // Also come up witht he redirection URL.
            $redirect = 'topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg'];
        }
    }
    $smcFunc['db_free_result']($request);
    if (empty($attachments)) {
        fatal_lang_error('no_access', false);
    }
    // Finally, we are there. Follow through!
    if ($is_approve) {
        ApproveAttachments($attachments);
    } else {
        removeAttachments(array('id_attach' => $attachments));
    }
    // Return to the topic....
    redirectexit($redirect);
}
Beispiel #8
0
function makeAvatarChanges($memID, &$post_errors)
{
    global $modSettings, $sourcedir, $db_prefix;
    if (!isset($_POST['avatar_choice']) || empty($memID)) {
        return;
    }
    require_once $sourcedir . '/ManageAttachments.php';
    $uploadDir = empty($modSettings['custom_avatar_enabled']) ? $modSettings['attachmentUploadDir'] : $modSettings['custom_avatar_dir'];
    $downloadedExternalAvatar = false;
    if ($_POST['avatar_choice'] == 'external' && allowedTo('profile_remote_avatar') && strtolower(substr($_POST['userpicpersonal'], 0, 7)) == 'http://' && strlen($_POST['userpicpersonal']) > 7 && !empty($modSettings['avatar_download_external'])) {
        if (!is_writable($uploadDir)) {
            fatal_lang_error('attachments_no_write');
        }
        require_once $sourcedir . '/Subs-Package.php';
        $url = parse_url($_POST['userpicpersonal']);
        $contents = fetch_web_data('http://' . $url['host'] . (empty($url['port']) ? '' : ':' . $url['port']) . $url['path']);
        if ($contents != false && ($tmpAvatar = fopen($uploadDir . '/avatar_tmp_' . $memID, 'wb'))) {
            fwrite($tmpAvatar, $contents);
            fclose($tmpAvatar);
            $downloadedExternalAvatar = true;
            $_FILES['attachment']['tmp_name'] = $uploadDir . '/avatar_tmp_' . $memID;
        }
    }
    if ($_POST['avatar_choice'] == 'server_stored' && allowedTo('profile_server_avatar')) {
        $_POST['avatar'] = strtr(empty($_POST['file']) ? empty($_POST['cat']) ? '' : $_POST['cat'] : $_POST['file'], array('&amp;' => '&'));
        $_POST['avatar'] = preg_match('~^([\\w _!@%*=\\-#()\\[\\]&.,]+/)?[\\w _!@%*=\\-#()\\[\\]&.,]+$~', $_POST['avatar']) != 0 && preg_match('/\\.\\./', $_POST['avatar']) == 0 && file_exists($modSettings['avatar_directory'] . '/' . $_POST['avatar']) ? $_POST['avatar'] == 'blank.gif' ? '' : $_POST['avatar'] : '';
        // Get rid of their old avatar. (if uploaded.)
        removeAttachments('a.ID_MEMBER = ' . $memID);
    } elseif ($_POST['avatar_choice'] == 'external' && allowedTo('profile_remote_avatar') && strtolower(substr($_POST['userpicpersonal'], 0, 7)) == 'http://' && empty($modSettings['avatar_download_external'])) {
        // Remove any attached avatar...
        removeAttachments('a.ID_MEMBER = ' . $memID);
        $_POST['avatar'] = preg_replace('~action(=|%3d)(?!dlattach)~i', 'action-', $_POST['userpicpersonal']);
        if ($_POST['avatar'] == 'http://' || $_POST['avatar'] == 'http:///') {
            $_POST['avatar'] = '';
        } elseif (substr($_POST['avatar'], 0, 7) != 'http://') {
            $post_errors[] = 'bad_avatar';
        } elseif (!empty($modSettings['avatar_max_height_external']) || !empty($modSettings['avatar_max_width_external'])) {
            // Now let's validate the avatar.
            $sizes = url_image_size($_POST['avatar']);
            if (is_array($sizes) && ($sizes[0] > $modSettings['avatar_max_width_external'] && !empty($modSettings['avatar_max_width_external']) || $sizes[1] > $modSettings['avatar_max_height_external'] && !empty($modSettings['avatar_max_height_external']))) {
                // Houston, we have a problem. The avatar is too large!!
                if ($modSettings['avatar_action_too_large'] == 'option_refuse') {
                    $post_errors[] = 'bad_avatar';
                } elseif ($modSettings['avatar_action_too_large'] == 'option_download_and_resize') {
                    require_once $sourcedir . '/Subs-Graphics.php';
                    if (downloadAvatar($_POST['avatar'], $memID, $modSettings['avatar_max_width_external'], $modSettings['avatar_max_height_external'])) {
                        $_POST['avatar'] = '';
                    } else {
                        $post_errors[] = 'bad_avatar';
                    }
                }
            }
        }
    } elseif ($_POST['avatar_choice'] == 'upload' && allowedTo('profile_upload_avatar') || $downloadedExternalAvatar) {
        if (isset($_FILES['attachment']['name']) && $_FILES['attachment']['name'] != '' || $downloadedExternalAvatar) {
            // Get the dimensions of the image.
            if (!$downloadedExternalAvatar) {
                if (!is_writable($uploadDir)) {
                    fatal_lang_error('attachments_no_write');
                }
                if (!move_uploaded_file($_FILES['attachment']['tmp_name'], $uploadDir . '/avatar_tmp_' . $memID)) {
                    fatal_lang_error('smf124');
                }
                $_FILES['attachment']['tmp_name'] = $uploadDir . '/avatar_tmp_' . $memID;
            }
            $sizes = @getimagesize($_FILES['attachment']['tmp_name']);
            // No size, then it's probably not a valid pic.
            if ($sizes === false) {
                $post_errors[] = 'bad_avatar';
            } elseif (!empty($modSettings['avatar_max_width_upload']) && $sizes[0] > $modSettings['avatar_max_width_upload'] || !empty($modSettings['avatar_max_height_upload']) && $sizes[1] > $modSettings['avatar_max_height_upload']) {
                if (!empty($modSettings['avatar_resize_upload'])) {
                    // Attempt to chmod it.
                    @chmod($uploadDir . '/avatar_tmp_' . $memID, 0644);
                    require_once $sourcedir . '/Subs-Graphics.php';
                    downloadAvatar($uploadDir . '/avatar_tmp_' . $memID, $memID, $modSettings['avatar_max_width_upload'], $modSettings['avatar_max_height_upload']);
                } else {
                    $post_errors[] = 'bad_avatar';
                }
            } elseif (is_array($sizes)) {
                // Though not an exhaustive list, better safe than sorry.
                $fp = fopen($_FILES['attachment']['tmp_name'], 'rb');
                if (!$fp) {
                    fatal_lang_error('smf124');
                }
                // Now try to find an infection.
                while (!feof($fp)) {
                    if (preg_match('~(iframe|\\<\\?php|\\<\\?[\\s=]|\\<%[\\s=]|html|eval|body|script\\W)~', fgets($fp, 4096)) === 1) {
                        if (file_exists($uploadDir . '/avatar_tmp_' . $memID)) {
                            @unlink($uploadDir . '/avatar_tmp_' . $memID);
                        }
                        fatal_lang_error('smf124');
                    }
                }
                fclose($fp);
                $extensions = array('1' => '.gif', '2' => '.jpg', '3' => '.png', '6' => '.bmp');
                $extension = isset($extensions[$sizes[2]]) ? $extensions[$sizes[2]] : '.bmp';
                $destName = 'avatar_' . $memID . $extension;
                list($width, $height) = getimagesize($_FILES['attachment']['tmp_name']);
                // Remove previous attachments this member might have had.
                removeAttachments('a.ID_MEMBER = ' . $memID);
                $file_hash = empty($modSettings['custom_avatar_enabled']) ? getAttachmentFilename($destName, false, true) : '';
                db_query("\n\t\t\t\t\tINSERT INTO {$db_prefix}attachments\n\t\t\t\t\t\t(ID_MEMBER, attachmentType, filename, file_hash, size, width, height)\n\t\t\t\t\tVALUES ({$memID}, " . (empty($modSettings['custom_avatar_enabled']) ? '0' : '1') . ", '{$destName}', '" . (empty($file_hash) ? "" : "{$file_hash}") . "', " . filesize($_FILES['attachment']['tmp_name']) . ", " . (int) $width . ", " . (int) $height . ")", __FILE__, __LINE__);
                $attachID = db_insert_id();
                // Try to move this avatar.
                $destinationPath = $uploadDir . '/' . (empty($file_hash) ? $destName : $attachID . '_' . $file_hash);
                if (!rename($_FILES['attachment']['tmp_name'], $destinationPath)) {
                    // The move failed, get rid of it and die.
                    db_query("\n\t\t\t\t\t\tDELETE FROM {$db_prefix}attachments\n\t\t\t\t\t\tWHERE ID_ATTACH = {$attachID}", __FILE__, __LINE__);
                    fatal_lang_error('smf124');
                }
                // Attempt to chmod it.
                @chmod($destinationPath, 0644);
            }
            $_POST['avatar'] = '';
            // Delete any temporary file.
            if (file_exists($uploadDir . '/avatar_tmp_' . $memID)) {
                @unlink($uploadDir . '/avatar_tmp_' . $memID);
            }
        } else {
            $_POST['avatar'] = '';
        }
    } else {
        $_POST['avatar'] = '';
    }
}
Beispiel #9
0
function profileSaveAvatarData(&$value)
{
    global $modSettings, $sourcedir, $smcFunc, $profile_vars, $cur_profile, $context;
    $memID = $context['id_member'];
    if (empty($memID) && !empty($context['password_auth_failed'])) {
        return false;
    }
    require_once $sourcedir . '/ManageAttachments.php';
    // We need to know where we're going to be putting it..
    if (!empty($modSettings['custom_avatar_enabled'])) {
        $uploadDir = $modSettings['custom_avatar_dir'];
        $id_folder = 1;
    } elseif (!empty($modSettings['currentAttachmentUploadDir'])) {
        if (!is_array($modSettings['attachmentUploadDir'])) {
            $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
        }
        // Just use the current path for temp files.
        $uploadDir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
        $id_folder = $modSettings['currentAttachmentUploadDir'];
    } else {
        $uploadDir = $modSettings['attachmentUploadDir'];
        $id_folder = 1;
    }
    $downloadedExternalAvatar = false;
    if ($value == 'external' && allowedTo('profile_remote_avatar') && strtolower(substr($_POST['userpicpersonal'], 0, 7)) == 'http://' && strlen($_POST['userpicpersonal']) > 7 && !empty($modSettings['avatar_download_external'])) {
        if (!is_writable($uploadDir)) {
            fatal_lang_error('attachments_no_write', 'critical');
        }
        require_once $sourcedir . '/Subs-Package.php';
        $url = parse_url($_POST['userpicpersonal']);
        $contents = fetch_web_data('http://' . $url['host'] . (empty($url['port']) ? '' : ':' . $url['port']) . str_replace(' ', '%20', trim($url['path'])));
        if ($contents != false && ($tmpAvatar = fopen($uploadDir . '/avatar_tmp_' . $memID, 'wb'))) {
            fwrite($tmpAvatar, $contents);
            fclose($tmpAvatar);
            $downloadedExternalAvatar = true;
            $_FILES['attachment']['tmp_name'] = $uploadDir . '/avatar_tmp_' . $memID;
        }
    }
    if ($value == 'none') {
        $profile_vars['avatar'] = '';
        // Reset the attach ID.
        $cur_profile['id_attach'] = 0;
        $cur_profile['attachment_type'] = 0;
        $cur_profile['filename'] = '';
        removeAttachments(array('id_member' => $memID));
    } elseif ($value == 'server_stored' && allowedTo('profile_server_avatar')) {
        $profile_vars['avatar'] = strtr(empty($_POST['file']) ? empty($_POST['cat']) ? '' : $_POST['cat'] : $_POST['file'], array('&amp;' => '&'));
        $profile_vars['avatar'] = preg_match('~^([\\w _!@%*=\\-#()\\[\\]&.,]+/)?[\\w _!@%*=\\-#()\\[\\]&.,]+$~', $profile_vars['avatar']) != 0 && preg_match('/\\.\\./', $profile_vars['avatar']) == 0 && file_exists($modSettings['avatar_directory'] . '/' . $profile_vars['avatar']) ? $profile_vars['avatar'] == 'blank.gif' ? '' : $profile_vars['avatar'] : '';
        // Clear current profile...
        $cur_profile['id_attach'] = 0;
        $cur_profile['attachment_type'] = 0;
        $cur_profile['filename'] = '';
        // Get rid of their old avatar. (if uploaded.)
        removeAttachments(array('id_member' => $memID));
    } elseif ($value == 'external' && allowedTo('profile_remote_avatar') && strtolower(substr($_POST['userpicpersonal'], 0, 7)) == 'http://' && empty($modSettings['avatar_download_external'])) {
        // We need these clean...
        $cur_profile['id_attach'] = 0;
        $cur_profile['attachment_type'] = 0;
        $cur_profile['filename'] = '';
        // Remove any attached avatar...
        removeAttachments(array('id_member' => $memID));
        $profile_vars['avatar'] = str_replace('%20', '', preg_replace('~action(?:=|%3d)(?!dlattach)~i', 'action-', $_POST['userpicpersonal']));
        if ($profile_vars['avatar'] == 'http://' || $profile_vars['avatar'] == 'http:///') {
            $profile_vars['avatar'] = '';
        } elseif (substr($profile_vars['avatar'], 0, 7) != 'http://') {
            return 'bad_avatar';
        } elseif (!empty($modSettings['avatar_max_height_external']) || !empty($modSettings['avatar_max_width_external'])) {
            // Now let's validate the avatar.
            $sizes = url_image_size($profile_vars['avatar']);
            if (is_array($sizes) && ($sizes[0] > $modSettings['avatar_max_width_external'] && !empty($modSettings['avatar_max_width_external']) || $sizes[1] > $modSettings['avatar_max_height_external'] && !empty($modSettings['avatar_max_height_external']))) {
                // Houston, we have a problem. The avatar is too large!!
                if ($modSettings['avatar_action_too_large'] == 'option_refuse') {
                    return 'bad_avatar';
                } elseif ($modSettings['avatar_action_too_large'] == 'option_download_and_resize') {
                    require_once $sourcedir . '/Subs-Graphics.php';
                    if (downloadAvatar($profile_vars['avatar'], $memID, $modSettings['avatar_max_width_external'], $modSettings['avatar_max_height_external'])) {
                        $profile_vars['avatar'] = '';
                        $cur_profile['id_attach'] = $modSettings['new_avatar_data']['id'];
                        $cur_profile['filename'] = $modSettings['new_avatar_data']['filename'];
                        $cur_profile['attachment_type'] = $modSettings['new_avatar_data']['type'];
                    } else {
                        return 'bad_avatar';
                    }
                }
            }
        }
    } elseif ($value == 'upload' && allowedTo('profile_upload_avatar') || $downloadedExternalAvatar) {
        if (isset($_FILES['attachment']['name']) && $_FILES['attachment']['name'] != '' || $downloadedExternalAvatar) {
            // Get the dimensions of the image.
            if (!$downloadedExternalAvatar) {
                if (!is_writable($uploadDir)) {
                    fatal_lang_error('attachments_no_write', 'critical');
                }
                if (!move_uploaded_file($_FILES['attachment']['tmp_name'], $uploadDir . '/avatar_tmp_' . $memID)) {
                    fatal_lang_error('attach_timeout', 'critical');
                }
                $_FILES['attachment']['tmp_name'] = $uploadDir . '/avatar_tmp_' . $memID;
            }
            $sizes = @getimagesize($_FILES['attachment']['tmp_name']);
            // No size, then it's probably not a valid pic.
            if ($sizes === false) {
                return 'bad_avatar';
            } elseif (!empty($modSettings['avatar_max_width_upload']) && $sizes[0] > $modSettings['avatar_max_width_upload'] || !empty($modSettings['avatar_max_height_upload']) && $sizes[1] > $modSettings['avatar_max_height_upload']) {
                if (!empty($modSettings['avatar_resize_upload'])) {
                    // Attempt to chmod it.
                    @chmod($uploadDir . '/avatar_tmp_' . $memID, 0644);
                    require_once $sourcedir . '/Subs-Graphics.php';
                    if (!downloadAvatar($uploadDir . '/avatar_tmp_' . $memID, $memID, $modSettings['avatar_max_width_upload'], $modSettings['avatar_max_height_upload'])) {
                        return 'bad_avatar';
                    }
                    // Reset attachment avatar data.
                    $cur_profile['id_attach'] = $modSettings['new_avatar_data']['id'];
                    $cur_profile['filename'] = $modSettings['new_avatar_data']['filename'];
                    $cur_profile['attachment_type'] = $modSettings['new_avatar_data']['type'];
                } else {
                    return 'bad_avatar';
                }
            } elseif (is_array($sizes)) {
                // Now try to find an infection.
                require_once $sourcedir . '/Subs-Graphics.php';
                if (!checkImageContents($_FILES['attachment']['tmp_name'], !empty($modSettings['avatar_paranoid']))) {
                    // It's bad. Try to re-encode the contents?
                    if (empty($modSettings['avatar_reencode']) || !reencodeImage($_FILES['attachment']['tmp_name'], $sizes[2])) {
                        return 'bad_avatar';
                    }
                    // We were successful. However, at what price?
                    $sizes = @getimagesize($_FILES['attachment']['tmp_name']);
                    // Hard to believe this would happen, but can you bet?
                    if ($sizes === false) {
                        return 'bad_avatar';
                    }
                }
                $extensions = array('1' => 'gif', '2' => 'jpg', '3' => 'png', '6' => 'bmp');
                $extension = isset($extensions[$sizes[2]]) ? $extensions[$sizes[2]] : 'bmp';
                $mime_type = 'image/' . ($extension === 'jpg' ? 'jpeg' : ($extension === 'bmp' ? 'x-ms-bmp' : $extension));
                $destName = 'avatar_' . $memID . '_' . time() . '.' . $extension;
                list($width, $height) = getimagesize($_FILES['attachment']['tmp_name']);
                $file_hash = empty($modSettings['custom_avatar_enabled']) ? getAttachmentFilename($destName, false, null, true) : '';
                // Remove previous attachments this member might have had.
                removeAttachments(array('id_member' => $memID));
                $smcFunc['db_insert']('', '{db_prefix}attachments', array('id_member' => 'int', 'attachment_type' => 'int', 'filename' => 'string', 'file_hash' => 'string', 'fileext' => 'string', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'mime_type' => 'string', 'id_folder' => 'int'), array($memID, empty($modSettings['custom_avatar_enabled']) ? 0 : 1, $destName, $file_hash, $extension, filesize($_FILES['attachment']['tmp_name']), (int) $width, (int) $height, $mime_type, $id_folder), array('id_attach'));
                $cur_profile['id_attach'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
                $cur_profile['filename'] = $destName;
                $cur_profile['attachment_type'] = empty($modSettings['custom_avatar_enabled']) ? 0 : 1;
                $destinationPath = $uploadDir . '/' . (empty($file_hash) ? $destName : $cur_profile['id_attach'] . '_' . $file_hash);
                if (!rename($_FILES['attachment']['tmp_name'], $destinationPath)) {
                    // I guess a man can try.
                    removeAttachments(array('id_member' => $memID));
                    fatal_lang_error('attach_timeout', 'critical');
                }
                // Attempt to chmod it.
                @chmod($uploadDir . '/' . $destinationPath, 0644);
            }
            $profile_vars['avatar'] = '';
            // Delete any temporary file.
            if (file_exists($uploadDir . '/avatar_tmp_' . $memID)) {
                @unlink($uploadDir . '/avatar_tmp_' . $memID);
            }
        } else {
            $profile_vars['avatar'] = '';
        }
    } else {
        $profile_vars['avatar'] = '';
    }
    // Setup the profile variables so it shows things right on display!
    $cur_profile['avatar'] = $profile_vars['avatar'];
    return false;
}
Beispiel #10
0
/**
 * Update an attachment's thumbnail
 *
 * @package Attachments
 * @param string $filename
 * @param int $id_attach
 * @param int $id_msg
 * @param int $old_id_thumb = 0
 * @return array The updated information
 */
function updateAttachmentThumbnail($filename, $id_attach, $id_msg, $old_id_thumb = 0)
{
    global $modSettings;
    $attachment = array('id_attach' => $id_attach);
    require_once SUBSDIR . '/Graphics.subs.php';
    if (createThumbnail($filename, $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) {
        // So what folder are we putting this image in?
        $id_folder_thumb = getAttachmentPathID();
        // Calculate the size of the created thumbnail.
        $size = @getimagesize($filename . '_thumb');
        list($attachment['thumb_width'], $attachment['thumb_height']) = $size;
        $thumb_size = filesize($filename . '_thumb');
        // These are the only valid image types.
        $validImageTypes = array(1 => 'gif', 2 => 'jpeg', 3 => 'png', 5 => 'psd', 6 => 'bmp', 7 => 'tiff', 8 => 'tiff', 9 => 'jpeg', 14 => 'iff');
        // What about the extension?
        $thumb_ext = isset($validImageTypes[$size[2]]) ? $validImageTypes[$size[2]] : '';
        // Figure out the mime type.
        if (!empty($size['mime'])) {
            $thumb_mime = $size['mime'];
        } else {
            $thumb_mime = 'image/' . $thumb_ext;
        }
        $thumb_filename = $filename . '_thumb';
        $thumb_hash = getAttachmentFilename($thumb_filename, 0, null, true);
        $db = database();
        // Add this beauty to the database.
        $db->insert('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'attachment_type' => 'int', 'filename' => 'string', 'file_hash' => 'string', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'fileext' => 'string', 'mime_type' => 'string'), array($id_folder_thumb, $id_msg, 3, $thumb_filename, $thumb_hash, (int) $thumb_size, (int) $attachment['thumb_width'], (int) $attachment['thumb_height'], $thumb_ext, $thumb_mime), array('id_attach'));
        $attachment['id_thumb'] = $db->insert_id('{db_prefix}attachments', 'id_attach');
        if (!empty($attachment['id_thumb'])) {
            $db->query('', '
				UPDATE {db_prefix}attachments
				SET id_thumb = {int:id_thumb}
				WHERE id_attach = {int:id_attach}', array('id_thumb' => $attachment['id_thumb'], 'id_attach' => $attachment['id_attach']));
            $thumb_realname = getAttachmentFilename($thumb_filename, $attachment['id_thumb'], $id_folder_thumb, false, $thumb_hash);
            rename($filename . '_thumb', $thumb_realname);
            // Do we need to remove an old thumbnail?
            if (!empty($old_id_thumb)) {
                require_once SUBSDIR . '/ManageAttachments.subs.php';
                removeAttachments(array('id_attach' => $old_id_thumb), '', false, false);
            }
        }
    }
    return $attachment;
}
Beispiel #11
0
/**
 * View all unapproved attachments.
 */
function UnapprovedAttachments()
{
    global $txt, $scripturl, $context, $user_info, $sourcedir, $smcFunc, $modSettings;
    $context['page_title'] = $txt['mc_unapproved_attachments'];
    // Once again, permissions are king!
    $approve_boards = boardsAllowedTo('approve_posts');
    if ($approve_boards == array(0)) {
        $approve_query = '';
    } elseif (!empty($approve_boards)) {
        $approve_query = ' AND m.id_board IN (' . implode(',', $approve_boards) . ')';
    } else {
        $approve_query = ' AND 0';
    }
    // Get together the array of things to act on, if any.
    $attachments = array();
    if (isset($_GET['approve'])) {
        $attachments[] = (int) $_GET['approve'];
    } elseif (isset($_GET['delete'])) {
        $attachments[] = (int) $_GET['delete'];
    } elseif (isset($_POST['item'])) {
        foreach ($_POST['item'] as $item) {
            $attachments[] = (int) $item;
        }
    }
    // Are we approving or deleting?
    if (isset($_GET['approve']) || isset($_POST['do']) && $_POST['do'] == 'approve') {
        $curAction = 'approve';
    } elseif (isset($_GET['delete']) || isset($_POST['do']) && $_POST['do'] == 'delete') {
        $curAction = 'delete';
    }
    // Something to do, let's do it!
    if (!empty($attachments) && isset($curAction)) {
        checkSession('request');
        // This will be handy.
        require_once $sourcedir . '/ManageAttachments.php';
        // Confirm the attachments are eligible for changing!
        $request = $smcFunc['db_query']('', '
			SELECT a.id_attach
			FROM {db_prefix}attachments AS a
				INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)
				LEFT JOIN {db_prefix}boards AS b ON (m.id_board = b.id_board)
			WHERE a.id_attach IN ({array_int:attachments})
				AND a.approved = {int:not_approved}
				AND a.attachment_type = {int:attachment_type}
				AND {query_see_board}
				' . $approve_query, array('attachments' => $attachments, 'not_approved' => 0, 'attachment_type' => 0));
        $attachments = array();
        while ($row = $smcFunc['db_fetch_assoc']($request)) {
            $attachments[] = $row['id_attach'];
        }
        $smcFunc['db_free_result']($request);
        // Assuming it wasn't all like, proper illegal, we can do the approving.
        if (!empty($attachments)) {
            if ($curAction == 'approve') {
                ApproveAttachments($attachments);
            } else {
                removeAttachments(array('id_attach' => $attachments, 'do_logging' => true));
            }
        }
    }
    require_once $sourcedir . '/Subs-List.php';
    $listOptions = array('id' => 'mc_unapproved_attach', 'width' => '100%', 'items_per_page' => $modSettings['defaultMaxMessages'], 'no_items_label' => $txt['mc_unapproved_attachments_none_found'], 'base_href' => $scripturl . '?action=moderate;area=attachmod;sa=attachments', 'default_sort_col' => 'attach_name', 'get_items' => array('function' => 'list_getUnapprovedAttachments', 'params' => array($approve_query)), 'get_count' => array('function' => 'list_getNumUnapprovedAttachments', 'params' => array($approve_query)), 'columns' => array('attach_name' => array('header' => array('value' => $txt['mc_unapproved_attach_name']), 'data' => array('db' => 'filename'), 'sort' => array('default' => 'a.filename', 'reverse' => 'a.filename DESC')), 'attach_size' => array('header' => array('value' => $txt['mc_unapproved_attach_size']), 'data' => array('db' => 'size'), 'sort' => array('default' => 'a.size', 'reverse' => 'a.size DESC')), 'attach_poster' => array('header' => array('value' => $txt['mc_unapproved_attach_poster']), 'data' => array('function' => create_function('$data', '
						return $data[\'poster\'][\'link\'];')), 'sort' => array('default' => 'm.id_member', 'reverse' => 'm.id_member DESC')), 'date' => array('header' => array('value' => $txt['date'], 'style' => 'width: 18%;'), 'data' => array('db' => 'time', 'class' => 'smalltext', 'style' => 'white-space:nowrap;'), 'sort' => array('default' => 'm.poster_time', 'reverse' => 'm.poster_time DESC')), 'message' => array('header' => array('value' => $txt['post']), 'data' => array('function' => create_function('$data', '
						return \'<a href="\' . $data[\'message\'][\'href\'] . \'">\' . shorten_subject($data[\'message\'][\'subject\'], 20) . \'</a>\';'), 'class' => 'smalltext', 'style' => 'width:15em;'), 'sort' => array('default' => 'm.subject', 'reverse' => 'm.subject DESC')), 'action' => array('header' => array('value' => '<input type="checkbox" class="input_check" onclick="invertAll(this, this.form);" checked="checked" />', 'style' => 'width: 4%;'), 'data' => array('sprintf' => array('format' => '<input type="checkbox" name="item[]" value="%1$d" checked="checked" class="input_check" />', 'params' => array('id' => false)), 'style' => 'text-align: center;'))), 'form' => array('href' => $scripturl . '?action=moderate;area=attachmod;sa=attachments', 'include_sort' => true, 'include_start' => true, 'hidden_fields' => array($context['session_var'] => $context['session_id']), 'token' => 'mod-ap'), 'additional_rows' => array(array('position' => 'bottom_of_list', 'value' => '
					<select name="do" onchange="if (this.value != 0 &amp;&amp; confirm(\'' . $txt['mc_unapproved_sure'] . '\')) submit();">
						<option value="0">' . $txt['with_selected'] . ':</option>
						<option value="0">-------------------</option>
						<option value="approve">&nbsp;--&nbsp;' . $txt['approve'] . '</option>
						<option value="delete">&nbsp;--&nbsp;' . $txt['delete'] . '</option>
					</select>
					<noscript><input type="submit" name="ml_go" value="' . $txt['go'] . '" class="button_submit" /></noscript>', 'align' => 'right')));
    // Create the request list.
    createToken('mod-ap');
    createList($listOptions);
    $context['sub_template'] = 'unapproved_attachments';
}
Beispiel #12
0
function shd_attach_delete()
{
    global $smcFunc, $user_info, $context, $sourcedir;
    if (empty($context['ticket_id']) || empty($_GET['attach']) || (int) $_GET['attach'] == 0) {
        fatal_lang_error('no_access', false);
    }
    $_GET['attach'] = (int) $_GET['attach'];
    // Well, we have a ticket id. Let's figure out what department we're in so we can check permissions.
    $query = shd_db_query('', '
		SELECT hdt.id_dept, a.filename, hda.id_msg, hdt.subject
		FROM {db_prefix}attachments AS a
			INNER JOIN {db_prefix}helpdesk_attachments AS hda ON (hda.id_attach = a.id_attach)
			INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hda.id_ticket = hdt.id_ticket)
		WHERE {query_see_ticket}
			AND hda.id_ticket = {int:ticket}
			AND hda.id_attach = {int:attach}
			AND a.attachment_type = 0', array('attach' => $_GET['attach'], 'ticket' => $context['ticket_id']));
    if ($smcFunc['db_num_rows']($query) == 0) {
        $smcFunc['db_free_result']($query);
        fatal_lang_error('no_access');
    }
    list($dept, $filename, $id_msg, $subject) = $smcFunc['db_fetch_row']($query);
    $smcFunc['db_free_result']($query);
    shd_is_allowed_to('shd_delete_attachment', $dept);
    // So, we can delete the attachment. We already know it exists, we know we have permission.
    $log_params = array('subject' => $subject, 'ticket' => $context['ticket_id'], 'msg' => $id_msg, 'att_removed' => array(htmlspecialchars($filename)));
    shd_log_action('editticket', $log_params);
    // Now you can delete
    require_once $sourcedir . '/ManageAttachments.php';
    $attachmentQuery = array('attachment_type' => 0, 'id_msg' => 0, 'id_attach' => array($_GET['attach']));
    removeAttachments($attachmentQuery);
    redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']);
}
Beispiel #13
0
    /**
     * Posts or saves the message composed with Post().
     *
     * requires various permissions depending on the action.
     * handles attachment, post, and calendar saving.
     * sends off notifications, and allows for announcements and moderation.
     * accessed from ?action=post2.
     */
    public function action_post2()
    {
        global $board, $topic, $txt, $modSettings, $context, $user_settings;
        global $user_info, $board_info, $options, $ignore_temp;
        // Sneaking off, are we?
        if (empty($_POST) && empty($topic)) {
            if (empty($_SERVER['CONTENT_LENGTH'])) {
                redirectexit('action=post;board=' . $board . '.0');
            } else {
                fatal_lang_error('post_upload_error', false);
            }
        } elseif (empty($_POST) && !empty($topic)) {
            redirectexit('action=post;topic=' . $topic . '.0');
        }
        // No need!
        $context['robot_no_index'] = true;
        // We are now in post2 action
        $context['current_action'] = 'post2';
        require_once SOURCEDIR . '/AttachmentErrorContext.class.php';
        // No errors as yet.
        $post_errors = Error_Context::context('post', 1);
        $attach_errors = Attachment_Error_Context::context();
        // If the session has timed out, let the user re-submit their form.
        if (checkSession('post', '', false) != '') {
            $post_errors->addError('session_timeout');
            // Disable the preview so that any potentially malicious code is not executed
            $_REQUEST['preview'] = false;
            return $this->action_post();
        }
        // Wrong verification code?
        if (!$user_info['is_admin'] && !$user_info['is_mod'] && !empty($modSettings['posts_require_captcha']) && ($user_info['posts'] < $modSettings['posts_require_captcha'] || $user_info['is_guest'] && $modSettings['posts_require_captcha'] == -1)) {
            require_once SUBSDIR . '/VerificationControls.class.php';
            $verificationOptions = array('id' => 'post');
            $context['require_verification'] = create_control_verification($verificationOptions, true);
            if (is_array($context['require_verification'])) {
                foreach ($context['require_verification'] as $verification_error) {
                    $post_errors->addError($verification_error);
                }
            }
        }
        require_once SUBSDIR . '/Boards.subs.php';
        require_once SUBSDIR . '/Post.subs.php';
        loadLanguage('Post');
        // Drafts enabled and needed?
        if (!empty($modSettings['drafts_enabled']) && (isset($_POST['save_draft']) || isset($_POST['id_draft']))) {
            require_once SUBSDIR . '/Drafts.subs.php';
        }
        // First check to see if they are trying to delete any current attachments.
        if (isset($_POST['attach_del'])) {
            $keep_temp = array();
            $keep_ids = array();
            foreach ($_POST['attach_del'] as $dummy) {
                if (strpos($dummy, 'post_tmp_' . $user_info['id']) !== false) {
                    $keep_temp[] = $dummy;
                } else {
                    $keep_ids[] = (int) $dummy;
                }
            }
            if (isset($_SESSION['temp_attachments'])) {
                foreach ($_SESSION['temp_attachments'] as $attachID => $attachment) {
                    if (isset($_SESSION['temp_attachments']['post']['files'], $attachment['name']) && in_array($attachment['name'], $_SESSION['temp_attachments']['post']['files']) || in_array($attachID, $keep_temp) || strpos($attachID, 'post_tmp_' . $user_info['id']) === false) {
                        continue;
                    }
                    unset($_SESSION['temp_attachments'][$attachID]);
                    @unlink($attachment['tmp_name']);
                }
            }
            if (!empty($_REQUEST['msg'])) {
                require_once SUBSDIR . '/ManageAttachments.subs.php';
                $attachmentQuery = array('attachment_type' => 0, 'id_msg' => (int) $_REQUEST['msg'], 'not_id_attach' => $keep_ids);
                removeAttachments($attachmentQuery);
            }
        }
        // Then try to upload any attachments.
        $context['attachments']['can']['post'] = !empty($modSettings['attachmentEnable']) && $modSettings['attachmentEnable'] == 1 && (allowedTo('post_attachment') || $modSettings['postmod_active'] && allowedTo('post_unapproved_attachments'));
        if ($context['attachments']['can']['post'] && empty($_POST['from_qr'])) {
            require_once SUBSDIR . '/Attachments.subs.php';
            if (isset($_REQUEST['msg'])) {
                processAttachments((int) $_REQUEST['msg']);
            } else {
                processAttachments();
            }
        }
        // Previewing? Go back to start.
        if (isset($_REQUEST['preview'])) {
            return $this->action_post();
        }
        // Prevent double submission of this form.
        checkSubmitOnce('check');
        // If this isn't a new topic load the topic info that we need.
        if (!empty($topic)) {
            require_once SUBSDIR . '/Topic.subs.php';
            $topic_info = getTopicInfo($topic);
            // Though the topic should be there, it might have vanished.
            if (empty($topic_info)) {
                fatal_lang_error('topic_doesnt_exist');
            }
            // Did this topic suddenly move? Just checking...
            if ($topic_info['id_board'] != $board) {
                fatal_lang_error('not_a_topic');
            }
        }
        // Replying to a topic?
        if (!empty($topic) && !isset($_REQUEST['msg'])) {
            // Don't allow a post if it's locked.
            if ($topic_info['locked'] != 0 && !allowedTo('moderate_board')) {
                fatal_lang_error('topic_locked', false);
            }
            // Sorry, multiple polls aren't allowed... yet.  You should stop giving me ideas :P.
            if (isset($_REQUEST['poll']) && $topic_info['id_poll'] > 0) {
                unset($_REQUEST['poll']);
            }
            // Do the permissions and approval stuff...
            $becomesApproved = true;
            if ($topic_info['id_member_started'] != $user_info['id']) {
                if ($modSettings['postmod_active'] && allowedTo('post_unapproved_replies_any') && !allowedTo('post_reply_any')) {
                    $becomesApproved = false;
                } else {
                    isAllowedTo('post_reply_any');
                }
            } elseif (!allowedTo('post_reply_any')) {
                if ($modSettings['postmod_active']) {
                    if (allowedTo('post_unapproved_replies_own') && !allowedTo('post_reply_own')) {
                        $becomesApproved = false;
                    } elseif ($user_info['is_guest'] && allowedTo('post_unapproved_replies_any')) {
                        $becomesApproved = false;
                    } else {
                        isAllowedTo('post_reply_own');
                    }
                }
            }
            if (isset($_POST['lock'])) {
                // Nothing is changed to the lock.
                if (empty($topic_info['locked']) && empty($_POST['lock']) || !empty($_POST['lock']) && !empty($topic_info['locked'])) {
                    unset($_POST['lock']);
                } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $topic_info['id_member_started']) {
                    unset($_POST['lock']);
                } elseif (!allowedTo('lock_any')) {
                    // You cannot override a moderator lock.
                    if ($topic_info['locked'] == 1) {
                        unset($_POST['lock']);
                    } else {
                        $_POST['lock'] = empty($_POST['lock']) ? 0 : 2;
                    }
                } else {
                    $_POST['lock'] = empty($_POST['lock']) ? 0 : 1;
                }
            }
            // So you wanna (un)sticky this...let's see.
            if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || $_POST['sticky'] == $topic_info['is_sticky'] || !allowedTo('make_sticky'))) {
                unset($_POST['sticky']);
            }
            // If drafts are enabled, then pass this off
            if (!empty($modSettings['drafts_enabled']) && isset($_POST['save_draft'])) {
                saveDraft();
                return $this->action_post();
            }
            // If the number of replies has changed, if the setting is enabled, go back to action_post() - which handles the error.
            if (empty($options['no_new_reply_warning']) && isset($_POST['last_msg']) && $topic_info['id_last_msg'] > $_POST['last_msg']) {
                addInlineJavascript('
					$(document).ready(function () {
						$("html,body").scrollTop($(\'.category_header:visible:first\').offset().top);
					});');
                return $this->action_post();
            }
            $posterIsGuest = $user_info['is_guest'];
        } elseif (empty($topic)) {
            // Now don't be silly, new topics will get their own id_msg soon enough.
            unset($_REQUEST['msg'], $_POST['msg'], $_GET['msg']);
            // Do like, the permissions, for safety and stuff...
            $becomesApproved = true;
            if ($modSettings['postmod_active'] && !allowedTo('post_new') && allowedTo('post_unapproved_topics')) {
                $becomesApproved = false;
            } else {
                isAllowedTo('post_new');
            }
            if (isset($_POST['lock'])) {
                // New topics are by default not locked.
                if (empty($_POST['lock'])) {
                    unset($_POST['lock']);
                } elseif (!allowedTo(array('lock_any', 'lock_own'))) {
                    unset($_POST['lock']);
                } else {
                    $_POST['lock'] = allowedTo('lock_any') ? 1 : 2;
                }
            }
            if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || empty($_POST['sticky']) || !allowedTo('make_sticky'))) {
                unset($_POST['sticky']);
            }
            // Saving your new topic as a draft first?
            if (!empty($modSettings['drafts_enabled']) && isset($_POST['save_draft'])) {
                saveDraft();
                return $this->action_post();
            }
            $posterIsGuest = $user_info['is_guest'];
        } elseif (isset($_REQUEST['msg']) && !empty($topic)) {
            $_REQUEST['msg'] = (int) $_REQUEST['msg'];
            require_once SUBSDIR . '/Messages.subs.php';
            $msgInfo = basicMessageInfo($_REQUEST['msg'], true);
            if (empty($msgInfo)) {
                fatal_lang_error('cant_find_messages', false);
            }
            if (!empty($topic_info['locked']) && !allowedTo('moderate_board')) {
                fatal_lang_error('topic_locked', false);
            }
            if (isset($_POST['lock'])) {
                // Nothing changes to the lock status.
                if (empty($_POST['lock']) && empty($topic_info['locked']) || !empty($_POST['lock']) && !empty($topic_info['locked'])) {
                    unset($_POST['lock']);
                } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $user_info['id'] != $topic_info['id_member_started']) {
                    unset($_POST['lock']);
                } elseif (!allowedTo('lock_any')) {
                    // You're not allowed to break a moderator's lock.
                    if ($topic_info['locked'] == 1) {
                        unset($_POST['lock']);
                    } else {
                        $_POST['lock'] = empty($_POST['lock']) ? 0 : 2;
                    }
                } else {
                    $_POST['lock'] = empty($_POST['lock']) ? 0 : 1;
                }
            }
            // Change the sticky status of this topic?
            if (isset($_POST['sticky']) && (!allowedTo('make_sticky') || $_POST['sticky'] == $topic_info['is_sticky'])) {
                unset($_POST['sticky']);
            }
            if ($msgInfo['id_member'] == $user_info['id'] && !allowedTo('modify_any')) {
                if ((!$modSettings['postmod_active'] || $msgInfo['approved']) && !empty($modSettings['edit_disable_time']) && $msgInfo['poster_time'] + ($modSettings['edit_disable_time'] + 5) * 60 < time()) {
                    fatal_lang_error('modify_post_time_passed', false);
                } elseif ($topic_info['id_member_started'] == $user_info['id'] && !allowedTo('modify_own')) {
                    isAllowedTo('modify_replies');
                } else {
                    isAllowedTo('modify_own');
                }
            } elseif ($topic_info['id_member_started'] == $user_info['id'] && !allowedTo('modify_any')) {
                isAllowedTo('modify_replies');
                // If you're modifying a reply, I say it better be logged...
                $moderationAction = true;
            } else {
                isAllowedTo('modify_any');
                // Log it, assuming you're not modifying your own post.
                if ($msgInfo['id_member'] != $user_info['id']) {
                    $moderationAction = true;
                }
            }
            // If drafts are enabled, then lets send this off to save
            if (!empty($modSettings['drafts_enabled']) && isset($_POST['save_draft'])) {
                saveDraft();
                return $this->action_post();
            }
            $posterIsGuest = empty($msgInfo['id_member']);
            // Can they approve it?
            $can_approve = allowedTo('approve_posts');
            $becomesApproved = $modSettings['postmod_active'] ? $can_approve && !$msgInfo['approved'] ? !empty($_REQUEST['approve']) ? 1 : 0 : $msgInfo['approved'] : 1;
            $approve_has_changed = $msgInfo['approved'] != $becomesApproved;
            if (!allowedTo('moderate_forum') || !$posterIsGuest) {
                $_POST['guestname'] = $msgInfo['poster_name'];
                $_POST['email'] = $msgInfo['poster_email'];
            }
        }
        // In case we want to override
        if (allowedTo('approve_posts')) {
            $becomesApproved = !isset($_REQUEST['approve']) || !empty($_REQUEST['approve']) ? 1 : 0;
            $approve_has_changed = isset($msgInfo['approved']) ? $msgInfo['approved'] != $becomesApproved : false;
        }
        // If the poster is a guest evaluate the legality of name and email.
        if ($posterIsGuest) {
            $_POST['guestname'] = !isset($_POST['guestname']) ? '' : Util::htmlspecialchars(trim($_POST['guestname']));
            $_POST['email'] = !isset($_POST['email']) ? '' : Util::htmlspecialchars(trim($_POST['email']));
            if ($_POST['guestname'] == '' || $_POST['guestname'] == '_') {
                $post_errors->addError('no_name');
            }
            if (Util::strlen($_POST['guestname']) > 25) {
                $post_errors->addError('long_name');
            }
            if (empty($modSettings['guest_post_no_email'])) {
                // Only check if they changed it!
                if (!isset($msgInfo) || $msgInfo['poster_email'] != $_POST['email']) {
                    require_once SUBSDIR . '/DataValidator.class.php';
                    if (!allowedTo('moderate_forum') && !Data_Validator::is_valid($_POST, array('email' => 'valid_email|required'), array('email' => 'trim'))) {
                        empty($_POST['email']) ? $post_errors->addError('no_email') : $post_errors->addError('bad_email');
                    }
                }
                // Now make sure this email address is not banned from posting.
                isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt['guest_title']));
            }
            // In case they are making multiple posts this visit, help them along by storing their name.
            if (!$post_errors->hasErrors()) {
                $_SESSION['guest_name'] = $_POST['guestname'];
                $_SESSION['guest_email'] = $_POST['email'];
            }
        }
        // Check the subject and message.
        if (!isset($_POST['subject']) || Util::htmltrim(Util::htmlspecialchars($_POST['subject'])) === '') {
            $post_errors->addError('no_subject');
        }
        if (!isset($_POST['message']) || Util::htmltrim(Util::htmlspecialchars($_POST['message'], ENT_QUOTES)) === '') {
            $post_errors->addError('no_message');
        } elseif (!empty($modSettings['max_messageLength']) && Util::strlen($_POST['message']) > $modSettings['max_messageLength']) {
            $post_errors->addError(array('long_message', array($modSettings['max_messageLength'])));
        } else {
            // Prepare the message a bit for some additional testing.
            $_POST['message'] = Util::htmlspecialchars($_POST['message'], ENT_QUOTES);
            // Preparse code. (Zef)
            if ($user_info['is_guest']) {
                $user_info['name'] = $_POST['guestname'];
            }
            preparsecode($_POST['message']);
            // Let's see if there's still some content left without the tags.
            if (Util::htmltrim(strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['message'], '[html]') === false)) {
                $post_errors->addError('no_message');
            }
        }
        if (isset($_POST['calendar']) && !isset($_REQUEST['deleteevent']) && Util::htmltrim($_POST['evtitle']) === '') {
            $post_errors->addError('no_event');
        }
        // Validate the poll...
        if (isset($_REQUEST['poll']) && !empty($modSettings['pollMode'])) {
            if (!empty($topic) && !isset($_REQUEST['msg'])) {
                fatal_lang_error('no_access', false);
            }
            // This is a new topic... so it's a new poll.
            if (empty($topic)) {
                isAllowedTo('poll_post');
            } elseif ($user_info['id'] == $topic_info['id_member_started'] && !allowedTo('poll_add_any')) {
                isAllowedTo('poll_add_own');
            } else {
                isAllowedTo('poll_add_any');
            }
            if (!isset($_POST['question']) || trim($_POST['question']) == '') {
                $post_errors->addError('no_question');
            }
            $_POST['options'] = empty($_POST['options']) ? array() : htmltrim__recursive($_POST['options']);
            // Get rid of empty ones.
            foreach ($_POST['options'] as $k => $option) {
                if ($option == '') {
                    unset($_POST['options'][$k], $_POST['options'][$k]);
                }
            }
            // What are you going to vote between with one choice?!?
            if (count($_POST['options']) < 2) {
                $post_errors->addError('poll_few');
            } elseif (count($_POST['options']) > 256) {
                $post_errors->addError('poll_many');
            }
        }
        if ($posterIsGuest) {
            // If user is a guest, make sure the chosen name isn't taken.
            require_once SUBSDIR . '/Members.subs.php';
            if (isReservedName($_POST['guestname'], 0, true, false) && (!isset($msgInfo['poster_name']) || $_POST['guestname'] != $msgInfo['poster_name'])) {
                $post_errors->addError('bad_name');
            }
        } elseif (!isset($_REQUEST['msg'])) {
            $_POST['guestname'] = $user_info['username'];
            $_POST['email'] = $user_info['email'];
        }
        // Posting somewhere else? Are we sure you can?
        if (!empty($_REQUEST['post_in_board'])) {
            $new_board = (int) $_REQUEST['post_in_board'];
            if (!allowedTo('post_new', $new_board)) {
                $post_in_board = boardInfo($new_board);
                if (!empty($post_in_board)) {
                    $post_errors->addError(array('post_new_board', array($post_in_board['name'])));
                } else {
                    $post_errors->addError('post_new');
                }
            }
        }
        // Any mistakes?
        if ($post_errors->hasErrors() || $attach_errors->hasErrors()) {
            addInlineJavascript('
				$(document).ready(function () {
					$("html,body").scrollTop($(\'.category_header:visible:first\').offset().top);
				});');
            return $this->action_post();
        }
        // Make sure the user isn't spamming the board.
        if (!isset($_REQUEST['msg'])) {
            spamProtection('post');
        }
        // At about this point, we're posting and that's that.
        ignore_user_abort(true);
        @set_time_limit(300);
        // Add special html entities to the subject, name, and email.
        $_POST['subject'] = strtr(Util::htmlspecialchars($_POST['subject']), array("\r" => '', "\n" => '', "\t" => ''));
        $_POST['guestname'] = htmlspecialchars($_POST['guestname'], ENT_COMPAT, 'UTF-8');
        $_POST['email'] = htmlspecialchars($_POST['email'], ENT_COMPAT, 'UTF-8');
        // At this point, we want to make sure the subject isn't too long.
        if (Util::strlen($_POST['subject']) > 100) {
            $_POST['subject'] = Util::substr($_POST['subject'], 0, 100);
        }
        if (!empty($modSettings['mentions_enabled']) && !empty($_REQUEST['uid'])) {
            $query_params = array();
            $query_params['member_ids'] = array_unique(array_map('intval', $_REQUEST['uid']));
            require_once SUBSDIR . '/Members.subs.php';
            $mentioned_members = membersBy('member_ids', $query_params, true);
            $replacements = 0;
            $actually_mentioned = array();
            foreach ($mentioned_members as $member) {
                $_POST['message'] = str_replace('@' . $member['real_name'], '[member=' . $member['id_member'] . ']' . $member['real_name'] . '[/member]', $_POST['message'], $replacements);
                if ($replacements > 0) {
                    $actually_mentioned[] = $member['id_member'];
                }
            }
        }
        // Make the poll...
        if (isset($_REQUEST['poll'])) {
            // Make sure that the user has not entered a ridiculous number of options..
            if (empty($_POST['poll_max_votes']) || $_POST['poll_max_votes'] <= 0) {
                $_POST['poll_max_votes'] = 1;
            } elseif ($_POST['poll_max_votes'] > count($_POST['options'])) {
                $_POST['poll_max_votes'] = count($_POST['options']);
            } else {
                $_POST['poll_max_votes'] = (int) $_POST['poll_max_votes'];
            }
            $_POST['poll_expire'] = (int) $_POST['poll_expire'];
            $_POST['poll_expire'] = $_POST['poll_expire'] > 9999 ? 9999 : ($_POST['poll_expire'] < 0 ? 0 : $_POST['poll_expire']);
            // Just set it to zero if it's not there..
            if (!isset($_POST['poll_hide'])) {
                $_POST['poll_hide'] = 0;
            } else {
                $_POST['poll_hide'] = (int) $_POST['poll_hide'];
            }
            $_POST['poll_change_vote'] = isset($_POST['poll_change_vote']) ? 1 : 0;
            $_POST['poll_guest_vote'] = isset($_POST['poll_guest_vote']) ? 1 : 0;
            // Make sure guests are actually allowed to vote generally.
            if ($_POST['poll_guest_vote']) {
                require_once SUBSDIR . '/Members.subs.php';
                $allowedVoteGroups = groupsAllowedTo('poll_vote', $board);
                if (!in_array(-1, $allowedVoteGroups['allowed'])) {
                    $_POST['poll_guest_vote'] = 0;
                }
            }
            // If the user tries to set the poll too far in advance, don't let them.
            if (!empty($_POST['poll_expire']) && $_POST['poll_expire'] < 1) {
                fatal_lang_error('poll_range_error', false);
            } elseif (empty($_POST['poll_expire']) && $_POST['poll_hide'] == 2) {
                $_POST['poll_hide'] = 1;
            }
            // Clean up the question and answers.
            $_POST['question'] = htmlspecialchars($_POST['question'], ENT_COMPAT, 'UTF-8');
            $_POST['question'] = Util::substr($_POST['question'], 0, 255);
            $_POST['question'] = preg_replace('~&amp;#(\\d{4,5}|[2-9]\\d{2,4}|1[2-9]\\d);~', '&#$1;', $_POST['question']);
            $_POST['options'] = htmlspecialchars__recursive($_POST['options']);
            // Finally, make the poll.
            require_once SUBSDIR . '/Poll.subs.php';
            $id_poll = createPoll($_POST['question'], $user_info['id'], $_POST['guestname'], $_POST['poll_max_votes'], $_POST['poll_hide'], $_POST['poll_expire'], $_POST['poll_change_vote'], $_POST['poll_guest_vote'], $_POST['options']);
        } else {
            $id_poll = 0;
        }
        // ...or attach a new file...
        if (empty($ignore_temp) && $context['attachments']['can']['post'] && !empty($_SESSION['temp_attachments']) && empty($_POST['from_qr'])) {
            $attachIDs = array();
            foreach ($_SESSION['temp_attachments'] as $attachID => $attachment) {
                if ($attachID != 'initial_error' && strpos($attachID, 'post_tmp_' . $user_info['id']) === false) {
                    continue;
                }
                // If there was an initial error just show that message.
                if ($attachID == 'initial_error') {
                    unset($_SESSION['temp_attachments']);
                    break;
                }
                // No errors, then try to create the attachment
                if (empty($attachment['errors'])) {
                    // Load the attachmentOptions array with the data needed to create an attachment
                    $attachmentOptions = array('post' => isset($_REQUEST['msg']) ? $_REQUEST['msg'] : 0, 'poster' => $user_info['id'], 'name' => $attachment['name'], 'tmp_name' => $attachment['tmp_name'], 'size' => isset($attachment['size']) ? $attachment['size'] : 0, 'mime_type' => isset($attachment['type']) ? $attachment['type'] : '', 'id_folder' => isset($attachment['id_folder']) ? $attachment['id_folder'] : 0, 'approved' => !$modSettings['postmod_active'] || allowedTo('post_attachment'), 'errors' => array());
                    if (createAttachment($attachmentOptions)) {
                        $attachIDs[] = $attachmentOptions['id'];
                        if (!empty($attachmentOptions['thumb'])) {
                            $attachIDs[] = $attachmentOptions['thumb'];
                        }
                    }
                } else {
                    @unlink($attachment['tmp_name']);
                }
            }
            unset($_SESSION['temp_attachments']);
        }
        // Creating a new topic?
        $newTopic = empty($_REQUEST['msg']) && empty($topic);
        $_POST['icon'] = !empty($attachIDs) && $_POST['icon'] == 'xx' ? 'clip' : $_POST['icon'];
        // Collect all parameters for the creation or modification of a post.
        $msgOptions = array('id' => empty($_REQUEST['msg']) ? 0 : (int) $_REQUEST['msg'], 'subject' => $_POST['subject'], 'body' => $_POST['message'], 'icon' => preg_replace('~[\\./\\\\*:"\'<>]~', '', $_POST['icon']), 'smileys_enabled' => !isset($_POST['ns']), 'attachments' => empty($attachIDs) ? array() : $attachIDs, 'approved' => $becomesApproved);
        $topicOptions = array('id' => empty($topic) ? 0 : $topic, 'board' => $board, 'poll' => isset($_REQUEST['poll']) ? $id_poll : null, 'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null, 'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null, 'mark_as_read' => true, 'is_approved' => !$modSettings['postmod_active'] || empty($topic) || !empty($board_info['cur_topic_approved']));
        $posterOptions = array('id' => $user_info['id'], 'name' => $_POST['guestname'], 'email' => $_POST['email'], 'update_post_count' => !$user_info['is_guest'] && !isset($_REQUEST['msg']) && $board_info['posts_count']);
        // This is an already existing message. Edit it.
        if (!empty($_REQUEST['msg'])) {
            // Have admins allowed people to hide their screwups?
            if (time() - $msgInfo['poster_time'] > $modSettings['edit_wait_time'] || $user_info['id'] != $msgInfo['id_member']) {
                $msgOptions['modify_time'] = time();
                $msgOptions['modify_name'] = $user_info['name'];
            }
            // This will save some time...
            if (empty($approve_has_changed)) {
                unset($msgOptions['approved']);
            }
            modifyPost($msgOptions, $topicOptions, $posterOptions);
        } else {
            if (!empty($modSettings['enableFollowup']) && !empty($_REQUEST['followup'])) {
                $original_post = (int) $_REQUEST['followup'];
            }
            // We also have to fake the board:
            // if it's valid and it's not the current, let's forget about the "current" and load the new one
            if (!empty($new_board) && $board !== $new_board) {
                $board = $new_board;
                loadBoard();
                // Some details changed
                $topicOptions['board'] = $board;
                $topicOptions['is_approved'] = !$modSettings['postmod_active'] || empty($topic) || !empty($board_info['cur_topic_approved']);
                $posterOptions['update_post_count'] = !$user_info['is_guest'] && !isset($_REQUEST['msg']) && $board_info['posts_count'];
            }
            createPost($msgOptions, $topicOptions, $posterOptions);
            if (isset($topicOptions['id'])) {
                $topic = $topicOptions['id'];
            }
            if (!empty($modSettings['enableFollowup'])) {
                require_once SUBSDIR . '/FollowUps.subs.php';
                require_once SUBSDIR . '/Messages.subs.php';
                // Time to update the original message with a pointer to the new one
                if (!empty($original_post) && canAccessMessage($original_post)) {
                    linkMessages($original_post, $topic);
                }
            }
        }
        // If we had a draft for this, its time to remove it since it was just posted
        if (!empty($modSettings['drafts_enabled']) && !empty($_POST['id_draft'])) {
            deleteDrafts($_POST['id_draft'], $user_info['id']);
        }
        // Editing or posting an event?
        if (isset($_POST['calendar']) && (!isset($_REQUEST['eventid']) || $_REQUEST['eventid'] == -1)) {
            require_once SUBSDIR . '/Calendar.subs.php';
            // Make sure they can link an event to this post.
            canLinkEvent();
            // Insert the event.
            $eventOptions = array('id_board' => $board, 'id_topic' => $topic, 'title' => $_POST['evtitle'], 'member' => $user_info['id'], 'start_date' => sprintf('%04d-%02d-%02d', $_POST['year'], $_POST['month'], $_POST['day']), 'span' => isset($_POST['span']) && $_POST['span'] > 0 ? min((int) $modSettings['cal_maxspan'], (int) $_POST['span'] - 1) : 0);
            insertEvent($eventOptions);
        } elseif (isset($_POST['calendar'])) {
            $_REQUEST['eventid'] = (int) $_REQUEST['eventid'];
            // Validate the post...
            require_once SUBSDIR . '/Calendar.subs.php';
            validateEventPost();
            // If you're not allowed to edit any events, you have to be the poster.
            if (!allowedTo('calendar_edit_any')) {
                $event_poster = getEventPoster($_REQUEST['eventid']);
                // Silly hacker, Trix are for kids. ...probably trademarked somewhere, this is FAIR USE! (parody...)
                isAllowedTo('calendar_edit_' . ($event_poster == $user_info['id'] ? 'own' : 'any'));
            }
            // Delete it?
            if (isset($_REQUEST['deleteevent'])) {
                removeEvent($_REQUEST['eventid']);
            } else {
                $span = !empty($modSettings['cal_allowspan']) && !empty($_REQUEST['span']) ? min((int) $modSettings['cal_maxspan'], (int) $_REQUEST['span'] - 1) : 0;
                $start_time = mktime(0, 0, 0, (int) $_REQUEST['month'], (int) $_REQUEST['day'], (int) $_REQUEST['year']);
                $eventOptions = array('start_date' => strftime('%Y-%m-%d', $start_time), 'end_date' => strftime('%Y-%m-%d', $start_time + $span * 86400), 'title' => $_REQUEST['evtitle']);
                modifyEvent($_REQUEST['eventid'], $eventOptions);
            }
        }
        // Marking boards as read.
        // (You just posted and they will be unread.)
        if (!$user_info['is_guest']) {
            $board_list = !empty($board_info['parent_boards']) ? array_keys($board_info['parent_boards']) : array();
            // Returning to the topic?
            if (!empty($_REQUEST['goback'])) {
                $board_list[] = $board;
            }
            if (!empty($board_list)) {
                markBoardsRead($board_list, false, false);
            }
        }
        // Turn notification on or off.
        if (!empty($_POST['notify']) && allowedTo('mark_any_notify')) {
            setTopicNotification($user_info['id'], $topic, true);
        } elseif (!$newTopic) {
            setTopicNotification($user_info['id'], $topic, false);
        }
        // Log an act of moderation - modifying.
        if (!empty($moderationAction)) {
            logAction('modify', array('topic' => $topic, 'message' => (int) $_REQUEST['msg'], 'member' => $msgInfo['id_member'], 'board' => $board));
        }
        if (isset($_POST['lock']) && $_POST['lock'] != 2) {
            logAction(empty($_POST['lock']) ? 'unlock' : 'lock', array('topic' => $topicOptions['id'], 'board' => $topicOptions['board']));
        }
        if (isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics'])) {
            logAction(empty($_POST['sticky']) ? 'unsticky' : 'sticky', array('topic' => $topicOptions['id'], 'board' => $topicOptions['board']));
        }
        // Notify any members who have notification turned on for this topic/board - only do this if it's going to be approved(!)
        if ($becomesApproved) {
            require_once SUBSDIR . '/Notification.subs.php';
            if ($newTopic) {
                $notifyData = array('body' => $_POST['message'], 'subject' => $_POST['subject'], 'name' => $user_info['name'], 'poster' => $user_info['id'], 'msg' => $msgOptions['id'], 'board' => $board, 'topic' => $topic, 'signature' => isset($user_settings['signature']) ? $user_settings['signature'] : '');
                sendBoardNotifications($notifyData);
            } elseif (empty($_REQUEST['msg'])) {
                // Only send it to everyone if the topic is approved, otherwise just to the topic starter if they want it.
                if ($topic_info['approved']) {
                    sendNotifications($topic, 'reply');
                } else {
                    sendNotifications($topic, 'reply', array(), $topic_info['id_member_started']);
                }
            }
        }
        if (!empty($modSettings['mentions_enabled']) && !empty($actually_mentioned)) {
            require_once CONTROLLERDIR . '/Mentions.controller.php';
            $mentions = new Mentions_Controller();
            $mentions->setData(array('id_member' => $actually_mentioned, 'type' => 'men', 'id_msg' => $msgOptions['id'], 'status' => $becomesApproved ? 'new' : 'unapproved'));
            $mentions->action_add();
        }
        if ($board_info['num_topics'] == 0) {
            cache_put_data('board-' . $board, null, 120);
        }
        if (!empty($_POST['announce_topic'])) {
            redirectexit('action=announce;sa=selectgroup;topic=' . $topic . (!empty($_POST['move']) && allowedTo('move_any') ? ';move' : '') . (empty($_REQUEST['goback']) ? '' : ';goback'));
        }
        if (!empty($_POST['move']) && allowedTo('move_any')) {
            redirectexit('action=movetopic;topic=' . $topic . '.0' . (empty($_REQUEST['goback']) ? '' : ';goback'));
        }
        // Return to post if the mod is on.
        if (isset($_REQUEST['msg']) && !empty($_REQUEST['goback'])) {
            redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg'], isBrowser('ie'));
        } elseif (!empty($_REQUEST['goback'])) {
            redirectexit('topic=' . $topic . '.new#new', isBrowser('ie'));
        } else {
            redirectexit('board=' . $board . '.0');
        }
    }
/**
 *	If we are deleting an attachment, check if we should handle this.
 *
 *	@since 2.1
 *	@param array &$listOptions The listOptions of attachments page.
 *	@param array &$titles All the sections we have.
 *	@param array &$list_title List title.
*/
function shd_attachment_remove(&$filesRemoved, $attachments)
{
    if (in_array($_REQUEST['type'], array('shd_attach', 'shd_thumb')) && !empty($attachments)) {
        $messages = removeAttachments(array('id_attach' => $attachments), '', true);
    }
}
Beispiel #15
0
function deleteMembers($users)
{
    global $db_prefix, $sourcedir, $modSettings, $ID_MEMBER;
    // If it's not an array, make it so!
    if (!is_array($users)) {
        $users = array($users);
    } else {
        $users = array_unique($users);
    }
    // Make sure there's no void user in here.
    $users = array_diff($users, array(0));
    // How many are they deleting?
    if (empty($users)) {
        return;
    } elseif (count($users) == 1) {
        list($user) = $users;
        $condition = '= ' . $user;
        if ($user == $ID_MEMBER) {
            isAllowedTo('profile_remove_own');
        } else {
            isAllowedTo('profile_remove_any');
        }
    } else {
        foreach ($users as $k => $v) {
            $users[$k] = (int) $v;
        }
        $condition = 'IN (' . implode(', ', $users) . ')';
        // Deleting more than one?  You can't have more than one account...
        isAllowedTo('profile_remove_any');
    }
    // Make sure they aren't trying to delete administrators if they aren't one.  But don't bother checking if it's just themself.
    if (!allowedTo('admin_forum') && (count($users) != 1 || $users[0] != $ID_MEMBER)) {
        $request = db_query("\n\t\t\tSELECT ID_MEMBER\n\t\t\tFROM {$db_prefix}members\n\t\t\tWHERE ID_MEMBER IN (" . implode(', ', $users) . ")\n\t\t\t\tAND (ID_GROUP = 1 OR FIND_IN_SET(1, additionalGroups) != 0)\n\t\t\tLIMIT " . count($users), __FILE__, __LINE__);
        $admins = array();
        while ($row = mysql_fetch_assoc($request)) {
            $admins[] = $row['ID_MEMBER'];
        }
        mysql_free_result($request);
        if (!empty($admins)) {
            $users = array_diff($users, $admins);
        }
    }
    if (empty($users)) {
        return;
    }
    // Log the action - regardless of who is deleting it.
    foreach ($users as $user) {
        // Integration rocks!
        if (isset($modSettings['integrate_delete_member']) && function_exists($modSettings['integrate_delete_member'])) {
            call_user_func($modSettings['integrate_delete_member'], $user);
        }
        logAction('delete_member', array('member' => $user));
    }
    // Make these peoples' posts guest posts.
    db_query("\n\t\tUPDATE {$db_prefix}messages\n\t\tSET ID_MEMBER = 0" . (!empty($modSettings['allow_hideEmail']) ? ", posterEmail = ''" : '') . "\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    db_query("\n\t\tUPDATE {$db_prefix}polls\n\t\tSET ID_MEMBER = 0\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    // Make these peoples' posts guest first posts and last posts.
    db_query("\n\t\tUPDATE {$db_prefix}topics\n\t\tSET ID_MEMBER_STARTED = 0\n\t\tWHERE ID_MEMBER_STARTED {$condition}", __FILE__, __LINE__);
    db_query("\n\t\tUPDATE {$db_prefix}topics\n\t\tSET ID_MEMBER_UPDATED = 0\n\t\tWHERE ID_MEMBER_UPDATED {$condition}", __FILE__, __LINE__);
    db_query("\n\t\tUPDATE {$db_prefix}log_actions\n\t\tSET ID_MEMBER = 0\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    db_query("\n\t\tUPDATE {$db_prefix}log_banned\n\t\tSET ID_MEMBER = 0\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    db_query("\n\t\tUPDATE {$db_prefix}log_errors\n\t\tSET ID_MEMBER = 0\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    // Delete the member.
    db_query("\n\t\tDELETE FROM {$db_prefix}members\n\t\tWHERE ID_MEMBER {$condition}\n\t\tLIMIT " . count($users), __FILE__, __LINE__);
    // Delete the logs...
    db_query("\n\t\tDELETE FROM {$db_prefix}log_boards\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    db_query("\n\t\tDELETE FROM {$db_prefix}log_karma\n\t\tWHERE ID_TARGET {$condition}\n\t\t\tOR ID_EXECUTOR {$condition}", __FILE__, __LINE__);
    db_query("\n\t\tDELETE FROM {$db_prefix}log_mark_read\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    db_query("\n\t\tDELETE FROM {$db_prefix}log_notify\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    db_query("\n\t\tDELETE FROM {$db_prefix}log_online\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    db_query("\n\t\tDELETE FROM {$db_prefix}log_polls\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    db_query("\n\t\tDELETE FROM {$db_prefix}log_topics\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    db_query("\n\t\tDELETE FROM {$db_prefix}collapsed_categories\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    // Delete personal messages.
    require_once $sourcedir . '/PersonalMessage.php';
    deleteMessages(null, null, $users);
    db_query("\n\t\tUPDATE {$db_prefix}personal_messages\n\t\tSET ID_MEMBER_FROM = 0\n\t\tWHERE ID_MEMBER_FROM {$condition}", __FILE__, __LINE__);
    // Delete avatar.
    require_once $sourcedir . '/ManageAttachments.php';
    removeAttachments('a.ID_MEMBER ' . $condition);
    // It's over, no more moderation for you.
    db_query("\n\t\tDELETE FROM {$db_prefix}moderators\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    // If you don't exist we can't ban you.
    db_query("\n\t\tDELETE FROM {$db_prefix}ban_items\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    // Remove individual theme settings.
    db_query("\n\t\tDELETE FROM {$db_prefix}themes\n\t\tWHERE ID_MEMBER {$condition}", __FILE__, __LINE__);
    // These users are nobody's buddy nomore.
    $request = db_query("\n\t\tSELECT ID_MEMBER, pm_ignore_list, buddy_list\n\t\tFROM {$db_prefix}members\n\t\tWHERE FIND_IN_SET(" . implode(', pm_ignore_list) OR FIND_IN_SET(', $users) . ', pm_ignore_list) OR FIND_IN_SET(' . implode(', buddy_list) OR FIND_IN_SET(', $users) . ', buddy_list)', __FILE__, __LINE__);
    while ($row = mysql_fetch_assoc($request)) {
        db_query("\n\t\t\tUPDATE {$db_prefix}members\n\t\t\tSET\n\t\t\t\tpm_ignore_list = '" . implode(',', array_diff(explode(',', $row['pm_ignore_list']), $users)) . "',\n\t\t\t\tbuddy_list = '" . implode(',', array_diff(explode(',', $row['buddy_list']), $users)) . "'\n\t\t\tWHERE ID_MEMBER = {$row['ID_MEMBER']}\n\t\t\tLIMIT 1", __FILE__, __LINE__);
    }
    mysql_free_result($request);
    // Make sure no member's birthday is still sticking in the calendar...
    updateStats('calendar');
    updateStats('member');
}
Beispiel #16
0
function shd_handle_attachments()
{
    global $modSettings, $smcFunc, $context, $user_info, $sourcedir, $txt;
    if (!shd_allowed_to('shd_post_attachment', $context['ticket_form']['dept'])) {
        return;
    }
    $attachIDs = array();
    require_once $sourcedir . '/Subs-Attachments.php';
    // Check if they are trying to delete any current attachments....
    if (isset($_POST['attach_del'])) {
        shd_is_allowed_to('shd_delete_attachment', $context['ticket_form']['dept']);
        $del_temp = array();
        foreach ($_POST['attach_del'] as $i => $dummy) {
            $del_temp[$i] = (int) $dummy;
        }
        // First, get them from the other table
        $query = shd_db_query('', '
			SELECT a.id_attach
			FROM {db_prefix}attachments AS a
				INNER JOIN {db_prefix}helpdesk_attachments AS hda ON (hda.id_attach = a.id_attach)
			WHERE ' . ($modSettings['shd_attachments_mode'] == 'ticket' ? 'hda.id_ticket = {int:ticket}' : 'hda.id_msg = {int:msg}'), array('msg' => $context['ticket_form']['msg'], 'ticket' => $context['ticket_id']));
        $attachments = array();
        while ($row = $smcFunc['db_fetch_assoc']($query)) {
            $attachments[] = $row['id_attach'];
        }
        $smcFunc['db_free_result']($query);
        // OK, so attachments = full list of attachments on this post, del_temp is list of ones to keep, so look for the ones that aren't in both lists
        $del_temp = array_diff($attachments, $del_temp);
        if (!empty($del_temp)) {
            $filenames = array();
            // Before deleting, get the names for the log
            $query = $smcFunc['db_query']('', '
				SELECT filename, attachment_type
				FROM {db_prefix}attachments
				WHERE id_attach IN ({array_int:attach})
				ORDER BY id_attach', array('attach' => $del_temp));
            $removed = array();
            while ($row = $smcFunc['db_fetch_assoc']($query)) {
                $row['filename'] = htmlspecialchars($row['filename']);
                $filenames[] = $row['filename'];
                if ($row['attachment_type'] == 0) {
                    $removed[] = $row['filename'];
                }
            }
            if (!empty($removed)) {
                $context['log_params']['att_removed'] = $removed;
            }
            // Now you can delete
            require_once $sourcedir . '/ManageAttachments.php';
            $attachmentQuery = array('attachment_type' => 0, 'id_msg' => 0, 'id_attach' => $del_temp);
            removeAttachments($attachmentQuery);
        }
    }
    // ...or attach a new file...
    if (!empty($_FILES) || !empty($_SESSION['temp_attachments'])) {
        if (!empty($FILES)) {
            $_FILES = array_reverse($_FILES);
        }
        shd_is_allowed_to('shd_post_attachment');
        // Make sure we're uploading to the right place.
        if (!empty($modSettings['currentAttachmentUploadDir'])) {
            if (!is_array($modSettings['attachmentUploadDir'])) {
                $modSettings['attachmentUploadDir'] = json_decode($modSettings['attachmentUploadDir'], true);
            }
            // The current directory, of course!
            $current_attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
        } else {
            $current_attach_dir = $modSettings['attachmentUploadDir'];
        }
        // If this isn't a new post, check the current attachments.
        if (isset($_REQUEST['msg']) || !empty($context['ticket_id'])) {
            $request = shd_db_query('', '
				SELECT COUNT(*), SUM(size)
				FROM {db_prefix}attachments AS a
					INNER JOIN {db_prefix}helpdesk_attachments AS hda ON (a.id_attach = hda.id_attach)
				WHERE ' . ($modSettings['shd_attachments_mode'] == 'ticket' ? 'hda.id_ticket = {int:ticket}' : 'hda.id_msg = {int:msg}') . '
					AND attachment_type = {int:attachment_type}', array('msg' => $context['ticket_form']['msg'], 'ticket' => $context['ticket_id'], 'attachment_type' => 0));
            list($quantity, $total_size) = $smcFunc['db_fetch_row']($request);
            $smcFunc['db_free_result']($request);
        } else {
            $quantity = 0;
            $total_size = 0;
        }
        if (!empty($_SESSION['temp_attachments'])) {
            foreach ($_SESSION['temp_attachments'] as $attachID => $name) {
                if (preg_match('~^post_tmp_' . $user_info['id'] . '_\\d+$~', $attachID) == 0) {
                    continue;
                }
                if (!empty($_POST['attach_del']) && !in_array($attachID, $_POST['attach_del'])) {
                    unset($_SESSION['temp_attachments'][$attachID]);
                    @unlink($current_attach_dir . '/' . $attachID);
                    continue;
                }
                $_FILES['attachment' . $attachID]['tmp_name'] = $attachID;
                $_FILES['attachment' . $attachID]['name'] = $name;
                $_FILES['attachment' . $attachID]['size'] = filesize($current_attach_dir . '/' . $attachID);
                list($_FILES['attachment' . $attachID]['width'], $_FILES['attachment' . $attachID]['height']) = @getimagesize($current_attach_dir . '/' . $attachID);
                unset($_SESSION['temp_attachments'][$attachID]);
            }
        }
        foreach ($_FILES as $uplfile) {
            if ($uplfile['name'] == '') {
                continue;
            }
            // Have we reached the maximum number of files we are allowed?
            $quantity++;
            $file_limit = !empty($modSettings['attachmentNumPerPostLimit']) && $modSettings['shd_attachments_mode'] != 'ticket' ? $modSettings['attachmentNumPerPostLimit'] : $quantity + 1;
            if ($quantity > $file_limit) {
                checkSubmitOnce('free');
                fatal_lang_error('attachments_limit_per_post', false, array($modSettings['attachmentNumPerPostLimit']));
            }
            // Check the total upload size for this post...
            $total_size += $uplfile['size'];
            $size_limit = !empty($modSettings['attachmentPostLimit']) && $modSettings['shd_attachments_mode'] != 'ticket' ? $modSettings['attachmentPostLimit'] * 1024 : $total_size + 1024;
            if ($total_size > $size_limit) {
                checkSubmitOnce('free');
                fatal_lang_error('file_too_big', false, array($modSettings['attachmentPostLimit']));
            }
            $attachmentOptions = array('post' => 0, 'poster' => $user_info['id'], 'name' => $uplfile['name'], 'tmp_name' => $uplfile['tmp_name'], 'size' => $uplfile['size'], 'id_folder' => $modSettings['currentAttachmentUploadDir']);
            if (createAttachment($attachmentOptions)) {
                $attachIDs[] = $attachmentOptions['id'];
                if (!empty($attachmentOptions['thumb'])) {
                    $attachIDs[] = $attachmentOptions['thumb'];
                }
                $context['log_params']['att_added'][] = htmlspecialchars($attachmentOptions['name']);
            } else {
                if (in_array('could_not_upload', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_lang_error('attach_timeout', 'critical');
                }
                if (in_array('too_large', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_lang_error('file_too_big', false, array($modSettings['attachmentSizeLimit']));
                }
                if (in_array('bad_extension', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_error($attachmentOptions['name'] . '.<br />' . $txt['cant_upload_type'] . ' ' . strtr($modSettings['attachmentExtensions'], array(',' => ', ')) . '.', false);
                }
                if (in_array('directory_full', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_lang_error('ran_out_of_space', 'critical');
                }
                if (in_array('bad_filename', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_error(basename($attachmentOptions['name']) . '.<br />' . $txt['restricted_filename'] . '.', 'critical');
                }
                if (in_array('taken_filename', $attachmentOptions['errors'])) {
                    checkSubmitOnce('free');
                    fatal_lang_error('filename_exists');
                }
            }
        }
    }
    return $attachIDs;
}
Beispiel #17
0
/**
 * Delete one or more members.
 *
 * What it does:
 * - Requires profile_remove_own or profile_remove_any permission for
 * respectively removing your own account or any account.
 * - Non-admins cannot delete admins.
 *
 * The function:
 * - changes author of messages, topics and polls to guest authors.
 * - removes all log entries concerning the deleted members, except the
 * error logs, ban logs and moderation logs.
 * - removes these members' personal messages (only the inbox)
 * - rmoves avatars, ban entries, theme settings, moderator positions, poll votes,
 * drafts, likes, mentions, notifications
 * - removes custom field data associated with them
 * - updates member statistics afterwards.
 *
 * @package Members
 * @param int[]|int $users
 * @param bool $check_not_admin = false
 */
function deleteMembers($users, $check_not_admin = false)
{
    global $modSettings, $user_info;
    $db = database();
    // Try give us a while to sort this out...
    @set_time_limit(600);
    // Try to get some more memory.
    setMemoryLimit('128M');
    // If it's not an array, make it so!
    if (!is_array($users)) {
        $users = array($users);
    } else {
        $users = array_unique($users);
    }
    // Make sure there's no void user in here.
    $users = array_diff($users, array(0));
    // How many are they deleting?
    if (empty($users)) {
        return;
    } elseif (count($users) == 1) {
        list($user) = $users;
        if ($user == $user_info['id']) {
            isAllowedTo('profile_remove_own');
        } else {
            isAllowedTo('profile_remove_any');
        }
    } else {
        foreach ($users as $k => $v) {
            $users[$k] = (int) $v;
        }
        // Deleting more than one?  You can't have more than one account...
        isAllowedTo('profile_remove_any');
    }
    // Get their names for logging purposes.
    $request = $db->query('', '
		SELECT id_member, member_name, email_address, CASE WHEN id_group = {int:admin_group} OR FIND_IN_SET({int:admin_group}, additional_groups) != 0 THEN 1 ELSE 0 END AS is_admin
		FROM {db_prefix}members
		WHERE id_member IN ({array_int:user_list})
		LIMIT ' . count($users), array('user_list' => $users, 'admin_group' => 1));
    $admins = array();
    $emails = array();
    $user_log_details = array();
    while ($row = $db->fetch_assoc($request)) {
        if ($row['is_admin']) {
            $admins[] = $row['id_member'];
        }
        $user_log_details[$row['id_member']] = array($row['id_member'], $row['member_name']);
        $emails[] = $row['email_address'];
    }
    $db->free_result($request);
    if (empty($user_log_details)) {
        return;
    }
    // Make sure they aren't trying to delete administrators if they aren't one.  But don't bother checking if it's just themself.
    if (!empty($admins) && ($check_not_admin || !allowedTo('admin_forum') && (count($users) != 1 || $users[0] != $user_info['id']))) {
        $users = array_diff($users, $admins);
        foreach ($admins as $id) {
            unset($user_log_details[$id]);
        }
    }
    // No one left?
    if (empty($users)) {
        return;
    }
    // Log the action - regardless of who is deleting it.
    $log_changes = array();
    foreach ($user_log_details as $user) {
        $log_changes[] = array('action' => 'delete_member', 'log_type' => 'admin', 'extra' => array('member' => $user[0], 'name' => $user[1], 'member_acted' => $user_info['name']));
        // Remove any cached data if enabled.
        if (!empty($modSettings['cache_enable']) && $modSettings['cache_enable'] >= 2) {
            cache_put_data('user_settings-' . $user[0], null, 60);
        }
    }
    // Make these peoples' posts guest posts.
    $db->query('', '
		UPDATE {db_prefix}messages
		SET id_member = {int:guest_id}' . (!empty($modSettings['deleteMembersRemovesEmail']) ? ',
		poster_email = {string:blank_email}' : '') . '
		WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'blank_email' => '', 'users' => $users));
    $db->query('', '
		UPDATE {db_prefix}polls
		SET id_member = {int:guest_id}
		WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    // Make these peoples' posts guest first posts and last posts.
    $db->query('', '
		UPDATE {db_prefix}topics
		SET id_member_started = {int:guest_id}
		WHERE id_member_started IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    $db->query('', '
		UPDATE {db_prefix}topics
		SET id_member_updated = {int:guest_id}
		WHERE id_member_updated IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    $db->query('', '
		UPDATE {db_prefix}log_actions
		SET id_member = {int:guest_id}
		WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    $db->query('', '
		UPDATE {db_prefix}log_banned
		SET id_member = {int:guest_id}
		WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    $db->query('', '
		UPDATE {db_prefix}log_errors
		SET id_member = {int:guest_id}
		WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    // Delete the member.
    $db->query('', '
		DELETE FROM {db_prefix}members
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // Delete any drafts...
    $db->query('', '
		DELETE FROM {db_prefix}user_drafts
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // Delete any likes...
    $db->query('', '
		DELETE FROM {db_prefix}message_likes
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // Delete any custom field data...
    $db->query('', '
		DELETE FROM {db_prefix}custom_fields_data
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // Delete any post by email keys...
    $db->query('', '
		DELETE FROM {db_prefix}postby_emails
		WHERE email_to IN ({array_string:emails})', array('emails' => $emails));
    // Delete the logs...
    $db->query('', '
		DELETE FROM {db_prefix}log_actions
		WHERE id_log = {int:log_type}
			AND id_member IN ({array_int:users})', array('log_type' => 2, 'users' => $users));
    $db->query('', '
		DELETE FROM {db_prefix}log_boards
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    $db->query('', '
		DELETE FROM {db_prefix}log_comments
		WHERE id_recipient IN ({array_int:users})
			AND comment_type = {string:warntpl}', array('users' => $users, 'warntpl' => 'warntpl'));
    $db->query('', '
		DELETE FROM {db_prefix}log_group_requests
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    $db->query('', '
		DELETE FROM {db_prefix}log_karma
		WHERE id_target IN ({array_int:users})
			OR id_executor IN ({array_int:users})', array('users' => $users));
    $db->query('', '
		DELETE FROM {db_prefix}log_mark_read
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    $db->query('', '
		DELETE FROM {db_prefix}log_notify
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    $db->query('', '
		DELETE FROM {db_prefix}log_online
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    $db->query('', '
		DELETE FROM {db_prefix}log_subscribed
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    $db->query('', '
		DELETE FROM {db_prefix}log_topics
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    $db->query('', '
		DELETE FROM {db_prefix}collapsed_categories
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // Make their votes appear as guest votes - at least it keeps the totals right.
    // @todo Consider adding back in cookie protection.
    $db->query('', '
		UPDATE {db_prefix}log_polls
		SET id_member = {int:guest_id}
		WHERE id_member IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    // Remove the mentions
    $db->query('', '
		DELETE FROM {db_prefix}log_mentions
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // Delete personal messages.
    require_once SUBSDIR . '/PersonalMessage.subs.php';
    deleteMessages(null, null, $users);
    $db->query('', '
		UPDATE {db_prefix}personal_messages
		SET id_member_from = {int:guest_id}
		WHERE id_member_from IN ({array_int:users})', array('guest_id' => 0, 'users' => $users));
    // They no longer exist, so we don't know who it was sent to.
    $db->query('', '
		DELETE FROM {db_prefix}pm_recipients
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // Delete avatar.
    require_once SUBSDIR . '/ManageAttachments.subs.php';
    removeAttachments(array('id_member' => $users));
    // It's over, no more moderation for you.
    $db->query('', '
		DELETE FROM {db_prefix}moderators
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    $db->query('', '
		DELETE FROM {db_prefix}group_moderators
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // If you don't exist we can't ban you.
    $db->query('', '
		DELETE FROM {db_prefix}ban_items
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // Remove individual theme settings.
    $db->query('', '
		DELETE FROM {db_prefix}themes
		WHERE id_member IN ({array_int:users})', array('users' => $users));
    // These users are nobody's buddy nomore.
    $request = $db->query('', '
		SELECT id_member, pm_ignore_list, buddy_list
		FROM {db_prefix}members
		WHERE FIND_IN_SET({raw:pm_ignore_list}, pm_ignore_list) != 0 OR FIND_IN_SET({raw:buddy_list}, buddy_list) != 0', array('pm_ignore_list' => implode(', pm_ignore_list) != 0 OR FIND_IN_SET(', $users), 'buddy_list' => implode(', buddy_list) != 0 OR FIND_IN_SET(', $users)));
    while ($row = $db->fetch_assoc($request)) {
        updateMemberData($row['id_member'], array('pm_ignore_list' => implode(',', array_diff(explode(',', $row['pm_ignore_list']), $users)), 'buddy_list' => implode(',', array_diff(explode(',', $row['buddy_list']), $users))));
    }
    $db->free_result($request);
    // Make sure no member's birthday is still sticking in the calendar...
    updateSettings(array('calendar_updated' => time()));
    // Integration rocks!
    call_integration_hook('integrate_delete_members', array($users));
    updateMemberStats();
    logActions($log_changes);
}
Beispiel #18
0
function UnapprovedAttachments()
{
    global $txt, $scripturl, $context, $user_info, $sourcedir, $smcFunc;
    $context['page_title'] = $txt['mc_unapproved_attachments'];
    // Once again, permissions are king!
    $approve_boards = boardsAllowedTo('approve_posts');
    if ($approve_boards == array(0)) {
        $approve_query = '';
    } elseif (!empty($approve_boards)) {
        $approve_query = ' AND m.id_board IN (' . implode(',', $approve_boards) . ')';
    } else {
        $approve_query = ' AND 0';
    }
    // Get together the array of things to act on, if any.
    $attachments = array();
    if (isset($_GET['approve'])) {
        $attachments[] = (int) $_GET['approve'];
    } elseif (isset($_GET['delete'])) {
        $attachments[] = (int) $_GET['delete'];
    } elseif (isset($_POST['item'])) {
        foreach ($_POST['item'] as $item) {
            $attachments[] = (int) $item;
        }
    }
    // Are we approving or deleting?
    if (isset($_GET['approve']) || isset($_POST['do']) && $_POST['do'] == 'approve') {
        $curAction = 'approve';
    } elseif (isset($_GET['delete']) || isset($_POST['do']) && $_POST['do'] == 'delete') {
        $curAction = 'delete';
    }
    // Something to do, let's do it!
    if (!empty($attachments) && isset($curAction)) {
        checkSession('request');
        // This will be handy.
        require_once $sourcedir . '/ManageAttachments.php';
        // Confirm the attachments are eligible for changing!
        $request = $smcFunc['db_query']('', '
			SELECT a.id_attach
			FROM {db_prefix}attachments AS a
				INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)
				LEFT JOIN {db_prefix}boards AS b ON (m.id_board = b.id_board)
			WHERE a.id_attach IN ({array_int:attachments})
				AND a.approved = {int:not_approved}
				AND a.attachment_type = {int:attachment_type}
				AND {query_see_board}
				' . $approve_query, array('attachments' => $attachments, 'not_approved' => 0, 'attachment_type' => 0));
        $attachments = array();
        while ($row = $smcFunc['db_fetch_assoc']($request)) {
            $attachments[] = $row['id_attach'];
        }
        $smcFunc['db_free_result']($request);
        // Assuming it wasn't all like, proper illegal, we can do the approving.
        if (!empty($attachments)) {
            if ($curAction == 'approve') {
                ApproveAttachments($attachments);
            } else {
                removeAttachments(array('id_attach' => $attachments));
            }
        }
    }
    // How many unapproved attachments in total?
    $request = $smcFunc['db_query']('', '
		SELECT COUNT(*)
		FROM {db_prefix}attachments AS a
			INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
		WHERE a.approved = {int:not_approved}
			AND a.attachment_type = {int:attachment_type}
			AND {query_see_board}
			' . $approve_query, array('not_approved' => 0, 'attachment_type' => 0));
    list($context['total_unapproved_attachments']) = $smcFunc['db_fetch_row']($request);
    $smcFunc['db_free_result']($request);
    $context['page_index'] = constructPageIndex($scripturl . '?action=moderate;area=attachmod;sa=attachments', $_GET['start'], $context['total_unapproved_attachments'], 10);
    $context['start'] = $_GET['start'];
    // Get all unapproved attachments.
    $request = $smcFunc['db_query']('', '
		SELECT a.id_attach, a.filename, a.size, m.id_msg, m.id_topic, m.id_board, m.subject, m.body, m.id_member,
			IFNULL(mem.real_name, m.poster_name) AS poster_name, m.poster_time,
			t.id_member_started, t.id_first_msg, b.name AS board_name, c.id_cat, c.name AS cat_name
		FROM {db_prefix}attachments AS a
			INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg)
			INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic)
			INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
			LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = m.id_member)
			LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
		WHERE a.approved = {int:not_approved}
			AND a.attachment_type = {int:attachment_type}
			AND {query_see_board}
			' . $approve_query . '
		LIMIT ' . $context['start'] . ', 10', array('not_approved' => 0, 'attachment_type' => 0));
    $context['unapproved_items'] = array();
    while ($row = $smcFunc['db_fetch_assoc']($request)) {
        $context['unapproved_items'][] = array('id' => $row['id_attach'], 'filename' => $row['filename'], 'size' => round($row['size'] / 1024, 2), 'time' => timeformat($row['poster_time']), 'poster' => array('id' => $row['id_member'], 'name' => $row['poster_name'], 'link' => $row['id_member'] ? '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['poster_name'] . '</a>' : $row['poster_name'], 'href' => $scripturl . '?action=profile;u=' . $row['id_member']), 'message' => array('id' => $row['id_msg'], 'subject' => $row['subject'], 'body' => parse_bbc($row['body']), 'time' => timeformat($row['poster_time']), 'href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . '#msg' . $row['id_msg']), 'topic' => array('id' => $row['id_topic']), 'board' => array('id' => $row['id_board'], 'name' => $row['board_name']), 'category' => array('id' => $row['id_cat'], 'name' => $row['cat_name']));
    }
    $smcFunc['db_free_result']($request);
    $context['sub_template'] = 'unapproved_attachments';
}
Beispiel #19
0
 function avatar_save($memID, &$profile_vars, &$cur_profile)
 {
     // Remove any attached avatar...
     removeAttachments(array('id_member' => $memID));
     $profile_vars['avatar'] = $_POST['attachment'];
     //	if ($profile_vars['avatar'] == 'http://' || $profile_vars['avatar'] == 'http:///')
     //		$profile_vars['avatar'] = '';
     // Trying to make us do something we'll regret?
     //	var_dump($profile_vars['avatar']);die;
     if (!is_numeric($profile_vars['avatar'])) {
         return 'bad_avatar';
     }
     // Should we check dimensions?
     //	elseif (!empty($modSettings['avatar_max_height_external']) || !empty($modSettings['avatar_max_width_external']))
     //	{
     // Now let's validate the avatar.
     //		$sizes = url_image_size($profile_vars['avatar']);
     //		if (is_array($sizes) && (($sizes[0] > $modSettings['avatar_max_width_external'] && !empty($modSettings['avatar_max_width_external'])) || ($sizes[1] > $modSettings['avatar_max_height_external'] && !empty($modSettings['avatar_max_height_external']))))
     //		{
     // Houston, we have a problem. The avatar is too large!!
     //			if ($modSettings['avatar_action_too_large'] == 'option_refuse')
     //				return 'bad_avatar';
     //			elseif ($modSettings['avatar_action_too_large'] == 'option_download_and_resize')
     //			{
     require_once $this->sourcedir . '/Subs-Graphics.php';
     $tea_avatar_size = !empty($this->modSettings['tea_avatar_size']) ? $this->modSettings['tea_avatar_size'] : 64;
     if (downloadAvatar('http://image.eveonline.com/Character/' . $profile_vars['avatar'] . '_' . $tea_avatar_size . '.jpg', $memID, $tea_avatar_size, $tea_avatar_size)) {
         $profile_vars['avatar'] = '';
         $cur_profile['id_attach'] = $this->modSettings['new_avatar_data']['id'];
         $cur_profile['filename'] = $this->modSettings['new_avatar_data']['filename'];
         $cur_profile['attachment_type'] = $this->modSettings['new_avatar_data']['type'];
     }
     //			}
     //		}
     //	}
 }
Beispiel #20
0
/**
 * Removes the passed id_topic's.
 * Permissions are NOT checked here because the function is used in a scheduled task
 *
 * @param int[]|int $topics The topics to remove (can be an id or an array of ids).
 * @param bool $decreasePostCount if true users' post count will be reduced
 * @param bool $ignoreRecycling if true topics are not moved to the recycle board (if it exists).
 */
function removeTopics($topics, $decreasePostCount = true, $ignoreRecycling = false)
{
    global $modSettings;
    $db = database();
    // Nothing to do?
    if (empty($topics)) {
        return;
    }
    // Only a single topic.
    if (is_numeric($topics)) {
        $topics = array($topics);
    }
    // Decrease the post counts for members.
    if ($decreasePostCount) {
        $requestMembers = $db->query('', '
			SELECT m.id_member, COUNT(*) AS posts
			FROM {db_prefix}messages AS m
				INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
			WHERE m.id_topic IN ({array_int:topics})
				AND m.icon != {string:recycled}
				AND b.count_posts = {int:do_count_posts}
				AND m.approved = {int:is_approved}
			GROUP BY m.id_member', array('do_count_posts' => 0, 'recycled' => 'recycled', 'topics' => $topics, 'is_approved' => 1));
        if ($db->num_rows($requestMembers) > 0) {
            while ($rowMembers = $db->fetch_assoc($requestMembers)) {
                updateMemberData($rowMembers['id_member'], array('posts' => 'posts - ' . $rowMembers['posts']));
            }
        }
        $db->free_result($requestMembers);
    }
    // Recycle topics that aren't in the recycle board...
    if (!empty($modSettings['recycle_enable']) && $modSettings['recycle_board'] > 0 && !$ignoreRecycling) {
        $request = $db->query('', '
			SELECT id_topic, id_board, unapproved_posts, approved
			FROM {db_prefix}topics
			WHERE id_topic IN ({array_int:topics})
				AND id_board != {int:recycle_board}
			LIMIT ' . count($topics), array('recycle_board' => $modSettings['recycle_board'], 'topics' => $topics));
        if ($db->num_rows($request) > 0) {
            // Get topics that will be recycled.
            $recycleTopics = array();
            while ($row = $db->fetch_assoc($request)) {
                if (function_exists('apache_reset_timeout')) {
                    @apache_reset_timeout();
                }
                $recycleTopics[] = $row['id_topic'];
                // Set the id_previous_board for this topic - and make it not sticky.
                $db->query('', '
					UPDATE {db_prefix}topics
					SET id_previous_board = {int:id_previous_board}, is_sticky = {int:not_sticky}
					WHERE id_topic = {int:id_topic}', array('id_previous_board' => $row['id_board'], 'id_topic' => $row['id_topic'], 'not_sticky' => 0));
            }
            $db->free_result($request);
            // Mark recycled topics as recycled.
            $db->query('', '
				UPDATE {db_prefix}messages
				SET icon = {string:recycled}
				WHERE id_topic IN ({array_int:recycle_topics})', array('recycle_topics' => $recycleTopics, 'recycled' => 'recycled'));
            // Move the topics to the recycle board.
            require_once SUBSDIR . '/Topic.subs.php';
            moveTopics($recycleTopics, $modSettings['recycle_board']);
            // Close reports that are being recycled.
            require_once SUBSDIR . '/Moderation.subs.php';
            $db->query('', '
				UPDATE {db_prefix}log_reported
				SET closed = {int:is_closed}
				WHERE id_topic IN ({array_int:recycle_topics})', array('recycle_topics' => $recycleTopics, 'is_closed' => 1));
            updateSettings(array('last_mod_report_action' => time()));
            recountOpenReports();
            // Topics that were recycled don't need to be deleted, so subtract them.
            $topics = array_diff($topics, $recycleTopics);
        } else {
            $db->free_result($request);
        }
    }
    // Still topics left to delete?
    if (empty($topics)) {
        return;
    }
    $adjustBoards = array();
    // Find out how many posts we are deleting.
    $request = $db->query('', '
		SELECT id_board, approved, COUNT(*) AS num_topics, SUM(unapproved_posts) AS unapproved_posts,
			SUM(num_replies) AS num_replies
		FROM {db_prefix}topics
		WHERE id_topic IN ({array_int:topics})
		GROUP BY id_board, approved', array('topics' => $topics));
    while ($row = $db->fetch_assoc($request)) {
        if (!isset($adjustBoards[$row['id_board']]['num_posts'])) {
            cache_put_data('board-' . $row['id_board'], null, 120);
            $adjustBoards[$row['id_board']] = array('num_posts' => 0, 'num_topics' => 0, 'unapproved_posts' => 0, 'unapproved_topics' => 0, 'id_board' => $row['id_board']);
        }
        // Posts = (num_replies + 1) for each approved topic.
        $adjustBoards[$row['id_board']]['num_posts'] += $row['num_replies'] + ($row['approved'] ? $row['num_topics'] : 0);
        $adjustBoards[$row['id_board']]['unapproved_posts'] += $row['unapproved_posts'];
        // Add the topics to the right type.
        if ($row['approved']) {
            $adjustBoards[$row['id_board']]['num_topics'] += $row['num_topics'];
        } else {
            $adjustBoards[$row['id_board']]['unapproved_topics'] += $row['num_topics'];
        }
    }
    $db->free_result($request);
    // Decrease number of posts and topics for each board.
    foreach ($adjustBoards as $stats) {
        if (function_exists('apache_reset_timeout')) {
            @apache_reset_timeout();
        }
        $db->query('', '
			UPDATE {db_prefix}boards
			SET
				num_posts = CASE WHEN {int:num_posts} > num_posts THEN 0 ELSE num_posts - {int:num_posts} END,
				num_topics = CASE WHEN {int:num_topics} > num_topics THEN 0 ELSE num_topics - {int:num_topics} END,
				unapproved_posts = CASE WHEN {int:unapproved_posts} > unapproved_posts THEN 0 ELSE unapproved_posts - {int:unapproved_posts} END,
				unapproved_topics = CASE WHEN {int:unapproved_topics} > unapproved_topics THEN 0 ELSE unapproved_topics - {int:unapproved_topics} END
			WHERE id_board = {int:id_board}', array('id_board' => $stats['id_board'], 'num_posts' => $stats['num_posts'], 'num_topics' => $stats['num_topics'], 'unapproved_posts' => $stats['unapproved_posts'], 'unapproved_topics' => $stats['unapproved_topics']));
    }
    // Remove polls for these topics.
    $request = $db->query('', '
		SELECT id_poll
		FROM {db_prefix}topics
		WHERE id_topic IN ({array_int:topics})
			AND id_poll > {int:no_poll}
		LIMIT ' . count($topics), array('no_poll' => 0, 'topics' => $topics));
    $polls = array();
    while ($row = $db->fetch_assoc($request)) {
        $polls[] = $row['id_poll'];
    }
    $db->free_result($request);
    if (!empty($polls)) {
        $db->query('', '
			DELETE FROM {db_prefix}polls
			WHERE id_poll IN ({array_int:polls})', array('polls' => $polls));
        $db->query('', '
			DELETE FROM {db_prefix}poll_choices
			WHERE id_poll IN ({array_int:polls})', array('polls' => $polls));
        $db->query('', '
			DELETE FROM {db_prefix}log_polls
			WHERE id_poll IN ({array_int:polls})', array('polls' => $polls));
    }
    // Get rid of the attachment(s).
    require_once SUBSDIR . '/ManageAttachments.subs.php';
    $attachmentQuery = array('attachment_type' => 0, 'id_topic' => $topics);
    removeAttachments($attachmentQuery, 'messages');
    // Delete search index entries.
    if (!empty($modSettings['search_custom_index_config'])) {
        $customIndexSettings = unserialize($modSettings['search_custom_index_config']);
        $request = $db->query('', '
			SELECT id_msg, body
			FROM {db_prefix}messages
			WHERE id_topic IN ({array_int:topics})', array('topics' => $topics));
        $words = array();
        $messages = array();
        while ($row = $db->fetch_assoc($request)) {
            if (function_exists('apache_reset_timeout')) {
                @apache_reset_timeout();
            }
            $words = array_merge($words, text2words($row['body'], $customIndexSettings['bytes_per_word'], true));
            $messages[] = $row['id_msg'];
        }
        $db->free_result($request);
        $words = array_unique($words);
        if (!empty($words) && !empty($messages)) {
            $db->query('', '
				DELETE FROM {db_prefix}log_search_words
				WHERE id_word IN ({array_int:word_list})
					AND id_msg IN ({array_int:message_list})', array('word_list' => $words, 'message_list' => $messages));
        }
    }
    // Reuse the message array if available
    if (empty($messages)) {
        $messages = messagesInTopics($topics);
    }
    // If there are messages left in this topic
    if (!empty($messages)) {
        // Remove all likes now that the topic is gone
        $db->query('', '
			DELETE FROM {db_prefix}message_likes
			WHERE id_msg IN ({array_int:messages})', array('messages' => $messages));
        // Remove all mentions now that the topic is gone
        $db->query('', '
			DELETE FROM {db_prefix}log_mentions
			WHERE id_msg IN ({array_int:messages})', array('messages' => $messages));
    }
    // Delete messages in each topic.
    $db->query('', '
		DELETE FROM {db_prefix}messages
		WHERE id_topic IN ({array_int:topics})', array('topics' => $topics));
    // Remove linked calendar events.
    // @todo if unlinked events are enabled, wouldn't this be expected to keep them?
    $db->query('', '
		DELETE FROM {db_prefix}calendar
		WHERE id_topic IN ({array_int:topics})', array('topics' => $topics));
    // Delete log_topics data
    $db->query('', '
		DELETE FROM {db_prefix}log_topics
		WHERE id_topic IN ({array_int:topics})', array('topics' => $topics));
    // Delete notifications
    $db->query('', '
		DELETE FROM {db_prefix}log_notify
		WHERE id_topic IN ({array_int:topics})', array('topics' => $topics));
    // Delete the topics themselves
    $db->query('', '
		DELETE FROM {db_prefix}topics
		WHERE id_topic IN ({array_int:topics})', array('topics' => $topics));
    // Remove data from the subjects for search cache
    $db->query('', '
		DELETE FROM {db_prefix}log_search_subjects
		WHERE id_topic IN ({array_int:topics})', array('topics' => $topics));
    require_once SUBSDIR . '/FollowUps.subs.php';
    removeFollowUpsByTopic($topics);
    foreach ($topics as $topic_id) {
        cache_put_data('topic_board-' . $topic_id, null, 120);
    }
    // Maybe there's an addon that wants to delete topic related data of its own
    call_integration_hook('integrate_remove_topics', array($topics));
    // Update the totals...
    updateStats('message');
    updateTopicStats();
    updateSettings(array('calendar_updated' => time()));
    require_once SUBSDIR . '/Post.subs.php';
    $updates = array();
    foreach ($adjustBoards as $stats) {
        $updates[] = $stats['id_board'];
    }
    updateLastMessages($updates);
}
 /**
  * Removes all attachments in a single click
  *
  * - Called from the maintenance screen by ?action=admin;area=manageattachments;sa=removeall.
  */
 public function action_removeall()
 {
     global $txt;
     checkSession('get', 'admin');
     // lots of work to do
     require_once SUBSDIR . '/ManageAttachments.subs.php';
     $messages = removeAttachments(array('attachment_type' => 0), '', true);
     $notice = isset($_POST['notice']) ? $_POST['notice'] : $txt['attachment_delete_admin'];
     // Add the notice on the end of the changed messages.
     if (!empty($messages)) {
         setRemovalNotice($messages, $notice);
     }
     redirectexit('action=admin;area=manageattachments;sa=maintenance');
 }
Beispiel #22
0
function RemoveAllAttachments()
{
    global $db_prefix, $txt;
    checkSession('get', 'manageattachments');
    $messages = removeAttachments('a.attachmentType = 0', '', true);
    if (!isset($_POST['notice'])) {
        $_POST['notice'] = $txt['smf216'];
    }
    // Add the notice on the end of the changed messages.
    if (!empty($messages)) {
        db_query("\n\t\t\tUPDATE {$db_prefix}messages\n\t\t\tSET body = CONCAT(body, '<br /><br />{$_POST['notice']}')\n\t\t\tWHERE ID_MSG IN (" . implode(',', $messages) . ")\n\t\t\tLIMIT " . count($messages), __FILE__, __LINE__);
    }
    redirectexit('action=manageattachments;sa=maintenance');
}
Beispiel #23
0
function downloadAvatar($url, $memID, $max_width, $max_height)
{
    global $modSettings, $db_prefix, $sourcedir, $gd2;
    $destName = 'avatar_' . $memID . '.' . (!empty($modSettings['avatar_download_png']) ? 'png' : 'jpeg');
    $default_formats = array('1' => 'gif', '2' => 'jpeg', '3' => 'png', '6' => 'bmp', '15' => 'wbmp');
    // Check to see if GD is installed and what version.
    $testGD = get_extension_funcs('gd');
    // If GD is not installed, this function is pointless.
    if (empty($testGD)) {
        return false;
    }
    // Just making sure there is a non-zero member.
    if (empty($memID)) {
        return false;
    }
    // GD 2 maybe?
    $gd2 = in_array('imagecreatetruecolor', $testGD) && function_exists('imagecreatetruecolor');
    unset($testGD);
    require_once $sourcedir . '/ManageAttachments.php';
    removeAttachments('a.ID_MEMBER = ' . $memID);
    $avatar_hash = empty($modSettings['custom_avatar_enabled']) ? getAttachmentFilename($destName, false, true) : '';
    db_query("\n\t\tINSERT INTO {$db_prefix}attachments\n\t\t\t(ID_MEMBER, attachmentType, filename, file_hash, size)\n\t\tVALUES ({$memID}, " . (empty($modSettings['custom_avatar_enabled']) ? '0' : '1') . ", '{$destName}', '" . (empty($avatar_hash) ? "" : "{$avatar_hash}") . "', 1)", __FILE__, __LINE__);
    $attachID = db_insert_id();
    $destName = (empty($modSettings['custom_avatar_enabled']) ? $modSettings['attachmentUploadDir'] : $modSettings['custom_avatar_dir']) . '/' . $destName . '.tmp';
    $success = false;
    $sizes = url_image_size($url);
    require_once $sourcedir . '/Subs-Package.php';
    $fp = fopen($destName, 'wb');
    if ($fp && substr($url, 0, 7) == 'http://') {
        $fileContents = fetch_web_data($url);
        // Though not an exhaustive list, better safe than sorry.
        if (preg_match('~(iframe|\\<\\?php|\\<\\?[\\s=]|\\<%[\\s=]|html|eval|body|script\\W)~', $fileContents) === 1) {
            fclose($fp);
            return false;
        }
        fwrite($fp, $fileContents);
        fclose($fp);
    } elseif ($fp) {
        $fp2 = fopen($url, 'rb');
        $prev_chunk = '';
        while (!feof($fp2)) {
            $cur_chunk = fread($fp2, 8192);
            // Make sure nothing odd came through.
            if (preg_match('~(iframe|\\<\\?php|\\<\\?[\\s=]|\\<%[\\s=]|html|eval|body|script\\W)~', $prev_chunk . $cur_chunk) === 1) {
                fclose($fp2);
                fclose($fp);
                unlink($destName);
                return false;
            }
            fwrite($fp, $cur_chunk);
            $prev_chunk = $cur_chunk;
        }
        fclose($fp2);
        fclose($fp);
    } else {
        $sizes = array(-1, -1, -1);
    }
    // Gif? That might mean trouble if gif support is not available.
    if ($sizes[2] == 1 && !function_exists('imagecreatefromgif') && function_exists('imagecreatefrompng')) {
        // Download it to the temporary file... use the special gif library... and save as png.
        if ($img = @gif_loadFile($destName) && gif_outputAsPng($img, $destName)) {
            $sizes[2] = 3;
        }
    }
    // A known and supported format?
    if (isset($default_formats[$sizes[2]]) && function_exists('imagecreatefrom' . $default_formats[$sizes[2]])) {
        $imagecreatefrom = 'imagecreatefrom' . $default_formats[$sizes[2]];
        if ($src_img = @$imagecreatefrom($destName)) {
            resizeImage($src_img, $destName, imagesx($src_img), imagesy($src_img), $max_width, $max_height);
            $success = true;
        }
    }
    // Remove the .tmp extension.
    $destName = substr($destName, 0, -4);
    if ($success) {
        // Remove the .tmp extension from the attachment.
        if (rename($destName . '.tmp', empty($avatar_hash) ? $destName : $modSettings['attachmentUploadDir'] . '/' . $attachID . '_' . $avatar_hash)) {
            $destName = empty($avatar_hash) ? $destName : $modSettings['attachmentUploadDir'] . '/' . $attachID . '_' . $avatar_hash;
            list($width, $height) = getimagesize($destName);
            // Write filesize in the database.
            db_query("\n\t\t\t\tUPDATE {$db_prefix}attachments\n\t\t\t\tSET size = " . filesize($destName) . ", width = " . (int) $width . ", height = " . (int) $height . "\n\t\t\t\tWHERE ID_ATTACH = {$attachID}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__);
            return true;
        } else {
            return false;
        }
    } else {
        db_query("\n\t\t\tDELETE FROM {$db_prefix}attachments\n\t\t\tWHERE ID_ATTACH = {$attachID}\n\t\t\tLIMIT 1", __FILE__, __LINE__);
        @unlink($destName . '.tmp');
        return false;
    }
}
Beispiel #24
0
function Post2()
{
    global $board, $topic, $txt, $db_prefix, $modSettings, $sourcedir, $context;
    global $ID_MEMBER, $user_info, $board_info, $options, $func;
    // Previewing? Go back to start.
    if (isset($_REQUEST['preview'])) {
        return Post();
    }
    // Prevent double submission of this form.
    checkSubmitOnce('check');
    // No errors as yet.
    $post_errors = array();
    // If the session has timed out, let the user re-submit their form.
    if (checkSession('post', '', false) != '') {
        $post_errors[] = 'session_timeout';
    }
    require_once $sourcedir . '/Subs-Post.php';
    loadLanguage('Post');
    // Replying to a topic?
    if (!empty($topic) && !isset($_REQUEST['msg'])) {
        $request = db_query("\n\t\t\tSELECT t.locked, t.isSticky, t.ID_POLL, t.numReplies, m.ID_MEMBER\n\t\t\tFROM ({$db_prefix}topics AS t, {$db_prefix}messages AS m)\n\t\t\tWHERE t.ID_TOPIC = {$topic}\n\t\t\t\tAND m.ID_MSG = t.ID_FIRST_MSG\n\t\t\tLIMIT 1", __FILE__, __LINE__);
        list($tmplocked, $tmpstickied, $pollID, $numReplies, $ID_MEMBER_POSTER) = mysql_fetch_row($request);
        mysql_free_result($request);
        // Don't allow a post if it's locked.
        if ($tmplocked != 0 && !allowedTo('moderate_board')) {
            fatal_lang_error(90, false);
        }
        // Sorry, multiple polls aren't allowed... yet.  You should stop giving me ideas :P.
        if (isset($_REQUEST['poll']) && $pollID > 0) {
            unset($_REQUEST['poll']);
        }
        if ($ID_MEMBER_POSTER != $ID_MEMBER) {
            isAllowedTo('post_reply_any');
        } elseif (!allowedTo('post_reply_any')) {
            isAllowedTo('post_reply_own');
        }
        if (isset($_POST['lock'])) {
            // Nothing is changed to the lock.
            if (empty($tmplocked) && empty($_POST['lock']) || !empty($_POST['lock']) && !empty($tmplocked)) {
                unset($_POST['lock']);
            } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $ID_MEMBER != $ID_MEMBER_POSTER) {
                unset($_POST['lock']);
            } elseif (!allowedTo('lock_any')) {
                // You cannot override a moderator lock.
                if ($tmplocked == 1) {
                    unset($_POST['lock']);
                } else {
                    $_POST['lock'] = empty($_POST['lock']) ? 0 : 2;
                }
            } else {
                $_POST['lock'] = empty($_POST['lock']) ? 0 : 1;
            }
        }
        // So you wanna (un)sticky this...let's see.
        if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || $_POST['sticky'] == $tmpstickied || !allowedTo('make_sticky'))) {
            unset($_POST['sticky']);
        }
        // If the number of replies has changed, if the setting is enabled, go back to Post() - which handles the error.
        $newReplies = isset($_POST['num_replies']) && $numReplies > $_POST['num_replies'] ? $numReplies - $_POST['num_replies'] : 0;
        if (empty($options['no_new_reply_warning']) && !empty($newReplies)) {
            $_REQUEST['preview'] = true;
            return Post();
        }
        $posterIsGuest = $user_info['is_guest'];
    } elseif (empty($topic)) {
        if (!isset($_REQUEST['poll']) || $modSettings['pollMode'] != '1') {
            isAllowedTo('post_new');
        }
        if (isset($_POST['lock'])) {
            // New topics are by default not locked.
            if (empty($_POST['lock'])) {
                unset($_POST['lock']);
            } elseif (!allowedTo(array('lock_any', 'lock_own'))) {
                unset($_POST['lock']);
            } else {
                $_POST['lock'] = allowedTo('lock_any') ? 1 : 2;
            }
        }
        if (isset($_POST['sticky']) && (empty($modSettings['enableStickyTopics']) || empty($_POST['sticky']) || !allowedTo('make_sticky'))) {
            unset($_POST['sticky']);
        }
        $posterIsGuest = $user_info['is_guest'];
    } elseif (isset($_REQUEST['msg']) && !empty($topic)) {
        $_REQUEST['msg'] = (int) $_REQUEST['msg'];
        $request = db_query("\n\t\t\tSELECT\n\t\t\t\tm.ID_MEMBER, m.posterName, m.posterEmail, m.posterTime, \n\t\t\t\tt.ID_FIRST_MSG, t.locked, t.isSticky, t.ID_MEMBER_STARTED AS ID_MEMBER_POSTER\n\t\t\tFROM ({$db_prefix}messages AS m, {$db_prefix}topics AS t)\n\t\t\tWHERE m.ID_MSG = {$_REQUEST['msg']}\n\t\t\t\tAND t.ID_TOPIC = {$topic}\n\t\t\tLIMIT 1", __FILE__, __LINE__);
        if (mysql_num_rows($request) == 0) {
            fatal_lang_error('smf272', false);
        }
        $row = mysql_fetch_assoc($request);
        mysql_free_result($request);
        if (!empty($row['locked']) && !allowedTo('moderate_board')) {
            fatal_lang_error(90, false);
        }
        if (isset($_POST['lock'])) {
            // Nothing changes to the lock status.
            if (empty($_POST['lock']) && empty($row['locked']) || !empty($_POST['lock']) && !empty($row['locked'])) {
                unset($_POST['lock']);
            } elseif (!allowedTo(array('lock_any', 'lock_own')) || !allowedTo('lock_any') && $ID_MEMBER != $row['ID_MEMBER_POSTER']) {
                unset($_POST['lock']);
            } elseif (!allowedTo('lock_any')) {
                // You're not allowed to break a moderator's lock.
                if ($row['locked'] == 1) {
                    unset($_POST['lock']);
                } else {
                    $_POST['lock'] = empty($_POST['lock']) ? 0 : 2;
                }
            } else {
                $_POST['lock'] = empty($_POST['lock']) ? 0 : 1;
            }
        }
        // Change the sticky status of this topic?
        if (isset($_POST['sticky']) && (!allowedTo('make_sticky') || $_POST['sticky'] == $row['isSticky'])) {
            unset($_POST['sticky']);
        }
        if ($row['ID_MEMBER'] == $ID_MEMBER && !allowedTo('modify_any')) {
            if (!empty($modSettings['edit_disable_time']) && $row['posterTime'] + ($modSettings['edit_disable_time'] + 5) * 60 < time()) {
                fatal_lang_error('modify_post_time_passed', false);
            } elseif ($row['ID_MEMBER_POSTER'] == $ID_MEMBER && !allowedTo('modify_own')) {
                isAllowedTo('modify_replies');
            } else {
                isAllowedTo('modify_own');
            }
        } elseif ($row['ID_MEMBER_POSTER'] == $ID_MEMBER && !allowedTo('modify_any')) {
            isAllowedTo('modify_replies');
            // If you're modifying a reply, I say it better be logged...
            $moderationAction = true;
        } else {
            isAllowedTo('modify_any');
            // Log it, assuming you're not modifying your own post.
            if ($row['ID_MEMBER'] != $ID_MEMBER) {
                $moderationAction = true;
            }
        }
        $posterIsGuest = empty($row['ID_MEMBER']);
        if (!allowedTo('moderate_forum') || !$posterIsGuest) {
            $_POST['guestname'] = addslashes($row['posterName']);
            $_POST['email'] = addslashes($row['posterEmail']);
        }
    }
    // If the poster is a guest evaluate the legality of name and email.
    if ($posterIsGuest) {
        $_POST['guestname'] = !isset($_POST['guestname']) ? '' : trim($_POST['guestname']);
        $_POST['email'] = !isset($_POST['email']) ? '' : trim($_POST['email']);
        if ($_POST['guestname'] == '' || $_POST['guestname'] == '_') {
            $post_errors[] = 'no_name';
        }
        if ($func['strlen']($_POST['guestname']) > 25) {
            $post_errors[] = 'long_name';
        }
        if (empty($modSettings['guest_post_no_email'])) {
            // Only check if they changed it!
            if (!isset($row) || $row['posterEmail'] != $_POST['email']) {
                if (!allowedTo('moderate_forum') && (!isset($_POST['email']) || $_POST['email'] == '')) {
                    $post_errors[] = 'no_email';
                }
                if (!allowedTo('moderate_forum') && preg_match('~^[0-9A-Za-z=_+\\-/][0-9A-Za-z=_\'+\\-/\\.]*@[\\w\\-]+(\\.[\\w\\-]+)*(\\.[\\w]{2,6})$~', stripslashes($_POST['email'])) == 0) {
                    $post_errors[] = 'bad_email';
                }
            }
            // Now make sure this email address is not banned from posting.
            isBannedEmail($_POST['email'], 'cannot_post', sprintf($txt['you_are_post_banned'], $txt[28]));
        }
    }
    // Check the subject and message.
    if (!isset($_POST['subject']) || $func['htmltrim']($_POST['subject']) === '') {
        $post_errors[] = 'no_subject';
    }
    if (!isset($_POST['message']) || $func['htmltrim']($_POST['message']) === '') {
        $post_errors[] = 'no_message';
    } elseif (!empty($modSettings['max_messageLength']) && $func['strlen']($_POST['message']) > $modSettings['max_messageLength']) {
        $post_errors[] = 'long_message';
    } else {
        // Prepare the message a bit for some additional testing.
        $_POST['message'] = $func['htmlspecialchars']($_POST['message'], ENT_QUOTES);
        // Preparse code. (Zef)
        if ($user_info['is_guest']) {
            $user_info['name'] = $_POST['guestname'];
        }
        preparsecode($_POST['message']);
        // Let's see if there's still some content left without the tags.
        if ($func['htmltrim'](strip_tags(parse_bbc($_POST['message'], false), '<img>')) === '') {
            $post_errors[] = 'no_message';
        }
    }
    if (isset($_POST['calendar']) && !isset($_REQUEST['deleteevent']) && $func['htmltrim']($_POST['evtitle']) === '') {
        $post_errors[] = 'no_event';
    }
    // You are not!
    if (isset($_POST['message']) && strtolower($_POST['message']) == 'i am the administrator.' && !$user_info['is_admin']) {
        fatal_error('Knave! Masquerader! Charlatan!', false);
    }
    // Validate the poll...
    if (isset($_REQUEST['poll']) && $modSettings['pollMode'] == '1') {
        if (!empty($topic) && !isset($_REQUEST['msg'])) {
            fatal_lang_error(1, false);
        }
        // This is a new topic... so it's a new poll.
        if (empty($topic)) {
            isAllowedTo('poll_post');
        } elseif ($ID_MEMBER == $row['ID_MEMBER_POSTER'] && !allowedTo('poll_add_any')) {
            isAllowedTo('poll_add_own');
        } else {
            isAllowedTo('poll_add_any');
        }
        if (!isset($_POST['question']) || trim($_POST['question']) == '') {
            $post_errors[] = 'no_question';
        }
        $_POST['options'] = empty($_POST['options']) ? array() : htmltrim__recursive($_POST['options']);
        // Get rid of empty ones.
        foreach ($_POST['options'] as $k => $option) {
            if ($option == '') {
                unset($_POST['options'][$k], $_POST['options'][$k]);
            }
        }
        // What are you going to vote between with one choice?!?
        if (count($_POST['options']) < 2) {
            $post_errors[] = 'poll_few';
        }
    }
    if ($posterIsGuest) {
        // If user is a guest, make sure the chosen name isn't taken.
        require_once $sourcedir . '/Subs-Members.php';
        if (isReservedName($_POST['guestname'], 0, true, false) && (!isset($row['posterName']) || $_POST['guestname'] != $row['posterName'])) {
            $post_errors[] = 'bad_name';
        }
    } elseif (!isset($_REQUEST['msg'])) {
        $_POST['guestname'] = addslashes($user_info['username']);
        $_POST['email'] = addslashes($user_info['email']);
    }
    // Any mistakes?
    if (!empty($post_errors)) {
        loadLanguage('Errors');
        // Previewing.
        $_REQUEST['preview'] = true;
        $context['post_error'] = array('messages' => array());
        foreach ($post_errors as $post_error) {
            $context['post_error'][$post_error] = true;
            $context['post_error']['messages'][] = $txt['error_' . $post_error];
        }
        return Post();
    }
    // Make sure the user isn't spamming the board.
    if (!isset($_REQUEST['msg'])) {
        spamProtection('spam');
    }
    // At about this point, we're posting and that's that.
    ignore_user_abort(true);
    @set_time_limit(300);
    // Add special html entities to the subject, name, and email.
    $_POST['subject'] = strtr($func['htmlspecialchars']($_POST['subject']), array("\r" => '', "\n" => '', "\t" => ''));
    $_POST['guestname'] = htmlspecialchars($_POST['guestname']);
    $_POST['email'] = htmlspecialchars($_POST['email']);
    // At this point, we want to make sure the subject isn't too long.
    if ($func['strlen']($_POST['subject']) > 100) {
        $_POST['subject'] = addslashes($func['substr'](stripslashes($_POST['subject']), 0, 100));
    }
    // Make the poll...
    if (isset($_REQUEST['poll'])) {
        // Make sure that the user has not entered a ridiculous number of options..
        if (empty($_POST['poll_max_votes']) || $_POST['poll_max_votes'] <= 0) {
            $_POST['poll_max_votes'] = 1;
        } elseif ($_POST['poll_max_votes'] > count($_POST['options'])) {
            $_POST['poll_max_votes'] = count($_POST['options']);
        } else {
            $_POST['poll_max_votes'] = (int) $_POST['poll_max_votes'];
        }
        // Just set it to zero if it's not there..
        if (!isset($_POST['poll_hide'])) {
            $_POST['poll_hide'] = 0;
        } else {
            $_POST['poll_hide'] = (int) $_POST['poll_hide'];
        }
        $_POST['poll_change_vote'] = isset($_POST['poll_change_vote']) ? 1 : 0;
        // If the user tries to set the poll too far in advance, don't let them.
        if (!empty($_POST['poll_expire']) && $_POST['poll_expire'] < 1) {
            fatal_lang_error('poll_range_error', false);
        } elseif (empty($_POST['poll_expire']) && $_POST['poll_hide'] == 2) {
            $_POST['poll_hide'] = 1;
        }
        // Clean up the question and answers.
        $_POST['question'] = $func['htmlspecialchars']($_POST['question']);
        $_POST['options'] = htmlspecialchars__recursive($_POST['options']);
    }
    // Check if they are trying to delete any current attachments....
    if (isset($_REQUEST['msg'], $_POST['attach_del']) && allowedTo('post_attachment')) {
        $del_temp = array();
        foreach ($_POST['attach_del'] as $i => $dummy) {
            $del_temp[$i] = (int) $dummy;
        }
        require_once $sourcedir . '/ManageAttachments.php';
        removeAttachments('a.attachmentType = 0 AND a.ID_MSG = ' . (int) $_REQUEST['msg'] . ' AND a.ID_ATTACH NOT IN (' . implode(', ', $del_temp) . ')');
    }
    // ...or attach a new file...
    if (isset($_FILES['attachment']['name']) || !empty($_SESSION['temp_attachments'])) {
        isAllowedTo('post_attachment');
        // If this isn't a new post, check the current attachments.
        if (isset($_REQUEST['msg'])) {
            $request = db_query("\n\t\t\t\tSELECT COUNT(*), SUM(size)\n\t\t\t\tFROM {$db_prefix}attachments\n\t\t\t\tWHERE ID_MSG = " . (int) $_REQUEST['msg'] . "\n\t\t\t\t\tAND attachmentType = 0", __FILE__, __LINE__);
            list($quantity, $total_size) = mysql_fetch_row($request);
            mysql_free_result($request);
        } else {
            $quantity = 0;
            $total_size = 0;
        }
        if (!empty($_SESSION['temp_attachments'])) {
            foreach ($_SESSION['temp_attachments'] as $attachID => $name) {
                if (preg_match('~^post_tmp_' . $ID_MEMBER . '_\\d+$~', $attachID) == 0) {
                    continue;
                }
                if (!empty($_POST['attach_del']) && !in_array($attachID, $_POST['attach_del'])) {
                    unset($_SESSION['temp_attachments'][$attachID]);
                    @unlink($modSettings['attachmentUploadDir'] . '/' . $attachID);
                    continue;
                }
                $_FILES['attachment']['tmp_name'][] = $attachID;
                $_FILES['attachment']['name'][] = addslashes($name);
                $_FILES['attachment']['size'][] = filesize($modSettings['attachmentUploadDir'] . '/' . $attachID);
                list($_FILES['attachment']['width'][], $_FILES['attachment']['height'][]) = @getimagesize($modSettings['attachmentUploadDir'] . '/' . $attachID);
                unset($_SESSION['temp_attachments'][$attachID]);
            }
        }
        if (!isset($_FILES['attachment']['name'])) {
            $_FILES['attachment']['tmp_name'] = array();
        }
        $attachIDs = array();
        foreach ($_FILES['attachment']['tmp_name'] as $n => $dummy) {
            if ($_FILES['attachment']['name'][$n] == '') {
                continue;
            }
            // Have we reached the maximum number of files we are allowed?
            $quantity++;
            if (!empty($modSettings['attachmentNumPerPostLimit']) && $quantity > $modSettings['attachmentNumPerPostLimit']) {
                fatal_lang_error('attachments_limit_per_post', false, array($modSettings['attachmentNumPerPostLimit']));
            }
            // Check the total upload size for this post...
            $total_size += $_FILES['attachment']['size'][$n];
            if (!empty($modSettings['attachmentPostLimit']) && $total_size > $modSettings['attachmentPostLimit'] * 1024) {
                fatal_lang_error('smf122', false, array($modSettings['attachmentPostLimit']));
            }
            $attachmentOptions = array('post' => isset($_REQUEST['msg']) ? $_REQUEST['msg'] : 0, 'poster' => $ID_MEMBER, 'name' => $_FILES['attachment']['name'][$n], 'tmp_name' => $_FILES['attachment']['tmp_name'][$n], 'size' => $_FILES['attachment']['size'][$n]);
            if (createAttachment($attachmentOptions)) {
                $attachIDs[] = $attachmentOptions['id'];
                if (!empty($attachmentOptions['thumb'])) {
                    $attachIDs[] = $attachmentOptions['thumb'];
                }
            } else {
                if (in_array('could_not_upload', $attachmentOptions['errors'])) {
                    fatal_lang_error('smf124');
                }
                if (in_array('too_large', $attachmentOptions['errors'])) {
                    fatal_lang_error('smf122', false, array($modSettings['attachmentSizeLimit']));
                }
                if (in_array('bad_extension', $attachmentOptions['errors'])) {
                    fatal_error($attachmentOptions['name'] . '.<br />' . $txt['smf123'] . ' ' . $modSettings['attachmentExtensions'] . '.', false);
                }
                if (in_array('directory_full', $attachmentOptions['errors'])) {
                    fatal_lang_error('smf126');
                }
                if (in_array('bad_filename', $attachmentOptions['errors'])) {
                    fatal_error(basename($attachmentOptions['name']) . '.<br />' . $txt['smf130b'] . '.');
                }
                if (in_array('taken_filename', $attachmentOptions['errors'])) {
                    fatal_lang_error('smf125');
                }
            }
        }
    }
    // Make the poll...
    if (isset($_REQUEST['poll'])) {
        // Create the poll.
        db_query("\n\t\t\tINSERT INTO {$db_prefix}polls\n\t\t\t\t(question, hideResults, maxVotes, expireTime, ID_MEMBER, posterName, changeVote)\n\t\t\tVALUES (SUBSTRING('{$_POST['question']}', 1, 255), {$_POST['poll_hide']}, {$_POST['poll_max_votes']},\n\t\t\t\t" . (empty($_POST['poll_expire']) ? '0' : time() + $_POST['poll_expire'] * 3600 * 24) . ", {$ID_MEMBER}, SUBSTRING('{$_POST['guestname']}', 1, 255), {$_POST['poll_change_vote']})", __FILE__, __LINE__);
        $ID_POLL = db_insert_id();
        // Create each answer choice.
        $i = 0;
        $setString = '';
        foreach ($_POST['options'] as $option) {
            $setString .= "\n\t\t\t\t\t({$ID_POLL}, {$i}, SUBSTRING('{$option}', 1, 255)),";
            $i++;
        }
        db_query("\n\t\t\tINSERT INTO {$db_prefix}poll_choices\n\t\t\t\t(ID_POLL, ID_CHOICE, label)\n\t\t\tVALUES" . substr($setString, 0, -1), __FILE__, __LINE__);
    } else {
        $ID_POLL = 0;
    }
    // Creating a new topic?
    $newTopic = empty($_REQUEST['msg']) && empty($topic);
    // Collect all parameters for the creation or modification of a post.
    $msgOptions = array('id' => empty($_REQUEST['msg']) ? 0 : (int) $_REQUEST['msg'], 'subject' => $_POST['subject'], 'body' => $_POST['message'], 'icon' => preg_replace('~[\\./\\\\*\':"<>]~', '', $_POST['icon']), 'smileys_enabled' => !isset($_POST['ns']), 'attachments' => empty($attachIDs) ? array() : $attachIDs);
    $topicOptions = array('id' => empty($topic) ? 0 : $topic, 'board' => $board, 'poll' => isset($_REQUEST['poll']) ? $ID_POLL : null, 'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null, 'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null, 'mark_as_read' => true);
    $posterOptions = array('id' => $ID_MEMBER, 'name' => $_POST['guestname'], 'email' => $_POST['email'], 'update_post_count' => !$user_info['is_guest'] && !isset($_REQUEST['msg']) && $board_info['posts_count']);
    // This is an already existing message. Edit it.
    if (!empty($_REQUEST['msg'])) {
        // Have admins allowed people to hide their screwups?
        if (time() - $row['posterTime'] > $modSettings['edit_wait_time'] || $ID_MEMBER != $row['ID_MEMBER']) {
            $msgOptions['modify_time'] = time();
            $msgOptions['modify_name'] = addslashes($user_info['name']);
        }
        modifyPost($msgOptions, $topicOptions, $posterOptions);
    } else {
        createPost($msgOptions, $topicOptions, $posterOptions);
        if (isset($topicOptions['id'])) {
            $topic = $topicOptions['id'];
        }
    }
    // Editing or posting an event?
    if (isset($_POST['calendar']) && (!isset($_REQUEST['eventid']) || $_REQUEST['eventid'] == -1)) {
        require_once $sourcedir . '/Calendar.php';
        calendarCanLink();
        calendarInsertEvent($board, $topic, $_POST['evtitle'], $ID_MEMBER, $_POST['month'], $_POST['day'], $_POST['year'], isset($_POST['span']) ? $_POST['span'] : null);
    } elseif (isset($_POST['calendar'])) {
        $_REQUEST['eventid'] = (int) $_REQUEST['eventid'];
        // Validate the post...
        require_once $sourcedir . '/Subs-Post.php';
        calendarValidatePost();
        // If you're not allowed to edit any events, you have to be the poster.
        if (!allowedTo('calendar_edit_any')) {
            // Get the event's poster.
            $request = db_query("\n\t\t\t\tSELECT ID_MEMBER\n\t\t\t\tFROM {$db_prefix}calendar\n\t\t\t\tWHERE ID_EVENT = {$_REQUEST['eventid']}", __FILE__, __LINE__);
            $row2 = mysql_fetch_assoc($request);
            mysql_free_result($request);
            // Silly hacker, Trix are for kids. ...probably trademarked somewhere, this is FAIR USE! (parody...)
            isAllowedTo('calendar_edit_' . ($row2['ID_MEMBER'] == $ID_MEMBER ? 'own' : 'any'));
        }
        // Delete it?
        if (isset($_REQUEST['deleteevent'])) {
            db_query("\n\t\t\t\tDELETE FROM {$db_prefix}calendar\n\t\t\t\tWHERE ID_EVENT = {$_REQUEST['eventid']}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__);
        } else {
            $span = !empty($modSettings['cal_allowspan']) && !empty($_REQUEST['span']) ? min((int) $modSettings['cal_maxspan'], (int) $_REQUEST['span'] - 1) : 0;
            $start_time = mktime(0, 0, 0, (int) $_REQUEST['month'], (int) $_REQUEST['day'], (int) $_REQUEST['year']);
            db_query("\n\t\t\t\tUPDATE {$db_prefix}calendar\n\t\t\t\tSET endDate = '" . strftime('%Y-%m-%d', $start_time + $span * 86400) . "',\n\t\t\t\t\tstartDate = '" . strftime('%Y-%m-%d', $start_time) . "',\n\t\t\t\t\ttitle = '" . $func['htmlspecialchars']($_REQUEST['evtitle'], ENT_QUOTES) . "'\n\t\t\t\tWHERE ID_EVENT = {$_REQUEST['eventid']}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__);
        }
        updateStats('calendar');
    }
    // Marking read should be done even for editing messages....
    if (!$user_info['is_guest']) {
        // Mark all the parents read.  (since you just posted and they will be unread.)
        if (!empty($board_info['parent_boards'])) {
            db_query("\n\t\t\t\tUPDATE {$db_prefix}log_boards\n\t\t\t\tSET ID_MSG = {$modSettings['maxMsgID']}\n\t\t\t\tWHERE ID_MEMBER = {$ID_MEMBER}\n\t\t\t\t\tAND ID_BOARD IN (" . implode(',', array_keys($board_info['parent_boards'])) . ")", __FILE__, __LINE__);
        }
    }
    // Turn notification on or off.  (note this just blows smoke if it's already on or off.)
    if (!empty($_POST['notify'])) {
        if (allowedTo('mark_any_notify')) {
            db_query("\n\t\t\t\tINSERT IGNORE INTO {$db_prefix}log_notify\n\t\t\t\t\t(ID_MEMBER, ID_TOPIC, ID_BOARD)\n\t\t\t\tVALUES ({$ID_MEMBER}, {$topic}, 0)", __FILE__, __LINE__);
        }
    } elseif (!$newTopic) {
        db_query("\n\t\t\tDELETE FROM {$db_prefix}log_notify\n\t\t\tWHERE ID_MEMBER = {$ID_MEMBER}\n\t\t\t\tAND ID_TOPIC = {$topic}\n\t\t\tLIMIT 1", __FILE__, __LINE__);
    }
    // Log an act of moderation - modifying.
    if (!empty($moderationAction)) {
        logAction('modify', array('topic' => $topic, 'message' => (int) $_REQUEST['msg'], 'member' => $row['ID_MEMBER']));
    }
    if (isset($_POST['lock']) && $_POST['lock'] != 2) {
        logAction('lock', array('topic' => $topicOptions['id']));
    }
    if (isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics'])) {
        logAction('sticky', array('topic' => $topicOptions['id']));
    }
    // Notify any members who have notification turned on for this topic.
    if ($newTopic) {
        notifyMembersBoard();
    } elseif (empty($_REQUEST['msg'])) {
        sendNotifications($topic, 'reply');
    }
    // Returning to the topic?
    if (!empty($_REQUEST['goback'])) {
        // Mark the board as read.... because it might get confusing otherwise.
        db_query("\n\t\t\tUPDATE {$db_prefix}log_boards\n\t\t\tSET ID_MSG = {$modSettings['maxMsgID']}\n\t\t\tWHERE ID_MEMBER = {$ID_MEMBER}\n\t\t\t\tAND ID_BOARD = {$board}", __FILE__, __LINE__);
    }
    if (!empty($_POST['announce_topic'])) {
        redirectexit('action=announce;sa=selectgroup;topic=' . $topic . (!empty($_POST['move']) && allowedTo('move_any') ? ';move' : '') . (empty($_REQUEST['goback']) ? '' : ';goback'));
    }
    if (!empty($_POST['move']) && allowedTo('move_any')) {
        redirectexit('action=movetopic;topic=' . $topic . '.0' . (empty($_REQUEST['goback']) ? '' : ';goback'));
    }
    // Return to post if the mod is on.
    if (isset($_REQUEST['msg']) && !empty($_REQUEST['goback'])) {
        redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg'], $context['browser']['is_ie']);
    } elseif (!empty($_REQUEST['goback'])) {
        redirectexit('topic=' . $topic . '.new#new', $context['browser']['is_ie']);
    } else {
        redirectexit('board=' . $board . '.0');
    }
}
Beispiel #25
0
function removeMessage($message, $decreasePostCount = true)
{
    global $db_prefix, $board, $sourcedir, $modSettings, $ID_MEMBER, $user_info;
    if (empty($message) || !is_numeric($message)) {
        return false;
    }
    $request = db_query("\n\t\tSELECT\n\t\t\tm.ID_MEMBER, m.icon, m.posterTime, m.subject," . (empty($modSettings['search_custom_index_config']) ? '' : ' m.body,') . "\n\t\t\tt.ID_TOPIC, t.ID_FIRST_MSG, t.ID_LAST_MSG, t.numReplies, t.ID_BOARD,\n\t\t\tt.ID_MEMBER_STARTED AS ID_MEMBER_POSTER,\n\t\t\tb.countPosts\n\t\tFROM ({$db_prefix}messages AS m, {$db_prefix}topics AS t, {$db_prefix}boards AS b)\n\t\tWHERE m.ID_MSG = {$message}\n\t\t\tAND t.ID_TOPIC = m.ID_TOPIC\n\t\t\tAND b.ID_BOARD = t.ID_BOARD\n\t\tLIMIT 1", __FILE__, __LINE__);
    if (mysql_num_rows($request) == 0) {
        return false;
    }
    $row = mysql_fetch_assoc($request);
    mysql_free_result($request);
    if (empty($board) || $row['ID_BOARD'] != $board) {
        $delete_any = boardsAllowedTo('delete_any');
        if (!in_array(0, $delete_any) && !in_array($row['ID_BOARD'], $delete_any)) {
            $delete_own = boardsAllowedTo('delete_own');
            $delete_own = in_array(0, $delete_own) || in_array($row['ID_BOARD'], $delete_own);
            $delete_replies = boardsAllowedTo('delete_replies');
            $delete_replies = in_array(0, $delete_replies) || in_array($row['ID_BOARD'], $delete_replies);
            if ($row['ID_MEMBER'] == $ID_MEMBER) {
                if (!$delete_own) {
                    if ($row['ID_MEMBER_POSTER'] == $ID_MEMBER) {
                        if (!$delete_replies) {
                            fatal_lang_error('cannot_delete_replies');
                        }
                    } else {
                        fatal_lang_error('cannot_delete_own');
                    }
                } elseif (($row['ID_MEMBER_POSTER'] != $ID_MEMBER || !$delete_replies) && !empty($modSettings['edit_disable_time']) && $row['posterTime'] + $modSettings['edit_disable_time'] * 60 < time()) {
                    fatal_lang_error('modify_post_time_passed', false);
                }
            } elseif ($row['ID_MEMBER_POSTER'] == $ID_MEMBER) {
                if (!$delete_replies) {
                    fatal_lang_error('cannot_delete_replies');
                }
            } else {
                fatal_lang_error('cannot_delete_any');
            }
        }
    } else {
        // Check permissions to delete this message.
        if ($row['ID_MEMBER'] == $ID_MEMBER) {
            if (!allowedTo('delete_own')) {
                if ($row['ID_MEMBER_POSTER'] == $ID_MEMBER && !allowedTo('delete_any')) {
                    isAllowedTo('delete_replies');
                } elseif (!allowedTo('delete_any')) {
                    isAllowedTo('delete_own');
                }
            } elseif (!allowedTo('delete_any') && ($row['ID_MEMBER_POSTER'] != $ID_MEMBER || !allowedTo('delete_replies')) && !empty($modSettings['edit_disable_time']) && $row['posterTime'] + $modSettings['edit_disable_time'] * 60 < time()) {
                fatal_lang_error('modify_post_time_passed', false);
            }
        } elseif ($row['ID_MEMBER_POSTER'] == $ID_MEMBER && !allowedTo('delete_any')) {
            isAllowedTo('delete_replies');
        } else {
            isAllowedTo('delete_any');
        }
    }
    // Delete the *whole* topic, but only if the topic consists of one message.
    if ($row['ID_FIRST_MSG'] == $message) {
        if (empty($board) || $row['ID_BOARD'] != $board) {
            $remove_any = boardsAllowedTo('remove_any');
            $remove_any = in_array(0, $remove_any) || in_array($row['ID_BOARD'], $remove_any);
            if (!$remove_any) {
                $remove_own = boardsAllowedTo('remove_own');
                $remove_own = in_array(0, $remove_own) || in_array($row['ID_BOARD'], $remove_own);
            }
            if ($row['ID_MEMBER'] != $ID_MEMBER && !$remove_any) {
                fatal_lang_error('cannot_remove_any');
            } elseif (!$remove_any && !$remove_own) {
                fatal_lang_error('cannot_remove_own');
            }
        } else {
            // Check permissions to delete a whole topic.
            if ($row['ID_MEMBER'] != $ID_MEMBER) {
                isAllowedTo('remove_any');
            } elseif (!allowedTo('remove_any')) {
                isAllowedTo('remove_own');
            }
        }
        // ...if there is only one post.
        if (!empty($row['numReplies'])) {
            fatal_lang_error('delFirstPost', false);
        }
        removeTopics($row['ID_TOPIC']);
        return true;
    }
    // Default recycle to false.
    $recycle = false;
    // If recycle topics has been set, make a copy of this message in the recycle board.
    // Make sure we're not recycling messages that are already on the recycle board.
    if (!empty($modSettings['recycle_enable']) && $row['ID_BOARD'] != $modSettings['recycle_board'] && $row['icon'] != 'recycled') {
        // Check if the recycle board exists and if so get the read status.
        $request = db_query("\n\t\t\tSELECT (IFNULL(lb.ID_MSG, 0) >= b.ID_MSG_UPDATED) AS isSeen\n\t\t\tFROM {$db_prefix}boards AS b\n\t\t\t\tLEFT JOIN {$db_prefix}log_boards AS lb ON (lb.ID_BOARD = b.ID_BOARD AND lb.ID_MEMBER = {$ID_MEMBER})\n\t\t\tWHERE b.ID_BOARD = {$modSettings['recycle_board']}", __FILE__, __LINE__);
        if (mysql_num_rows($request) == 0) {
            fatal_lang_error('recycle_no_valid_board');
        }
        list($isRead) = mysql_fetch_row($request);
        mysql_free_result($request);
        // Insert a new topic in the recycle board.
        db_query("\n\t\t\tINSERT INTO {$db_prefix}topics\n\t\t\t\t(ID_BOARD, ID_MEMBER_STARTED, ID_MEMBER_UPDATED, ID_FIRST_MSG, ID_LAST_MSG)\n\t\t\tVALUES ({$modSettings['recycle_board']}, {$row['ID_MEMBER']}, {$row['ID_MEMBER']}, {$message}, {$message})", __FILE__, __LINE__);
        // Capture the ID of the new topic...
        $topicID = db_insert_id();
        // If the topic creation went successful, move the message.
        if ($topicID > 0) {
            db_query("\n\t\t\t\tUPDATE {$db_prefix}messages\n\t\t\t\tSET \n\t\t\t\t\tID_TOPIC = {$topicID},\n\t\t\t\t\tID_BOARD = {$modSettings['recycle_board']},\n\t\t\t\t\ticon = 'recycled'\n\t\t\t\tWHERE ID_MSG = {$message}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__);
            // Mark recycled topic as read.
            if (!$user_info['is_guest']) {
                db_query("\n\t\t\t\t\tREPLACE INTO {$db_prefix}log_topics\n\t\t\t\t\t\t(ID_TOPIC, ID_MEMBER, ID_MSG)\n\t\t\t\t\tVALUES ({$topicID}, {$ID_MEMBER}, {$modSettings['maxMsgID']})", __FILE__, __LINE__);
            }
            // Mark recycle board as seen, if it was marked as seen before.
            if (!empty($isRead) && !$user_info['is_guest']) {
                db_query("\n\t\t\t\t\tREPLACE INTO {$db_prefix}log_boards\n\t\t\t\t\t\t(ID_BOARD, ID_MEMBER, ID_MSG)\n\t\t\t\t\tVALUES ({$modSettings['recycle_board']}, {$ID_MEMBER}, {$modSettings['maxMsgID']})", __FILE__, __LINE__);
            }
            // Add one topic and post to the recycle bin board.
            db_query("\n\t\t\t\tUPDATE {$db_prefix}boards\n\t\t\t\tSET\n\t\t\t\t\tnumTopics = numTopics + 1,\n\t\t\t\t\tnumPosts = numPosts + 1\n\t\t\t\tWHERE ID_BOARD = {$modSettings['recycle_board']}\n\t\t\t\tLIMIT 1", __FILE__, __LINE__);
            // Make sure this message isn't getting deleted later on.
            $recycle = true;
            // Make sure we update the search subject index.
            updateStats('subject', $topicID, $row['subject']);
        }
    }
    // Deleting a recycled message can not lower anyone's post count.
    if ($row['icon'] == 'recycled') {
        $decreasePostCount = false;
    }
    // This is the last post, update the last post on the board.
    if ($row['ID_LAST_MSG'] == $message) {
        // Find the last message, set it, and decrease the post count.
        $request = db_query("\n\t\t\tSELECT ID_MSG, ID_MEMBER\n\t\t\tFROM {$db_prefix}messages\n\t\t\tWHERE ID_TOPIC = {$row['ID_TOPIC']}\n\t\t\t\tAND ID_MSG != {$message}\n\t\t\tORDER BY ID_MSG DESC\n\t\t\tLIMIT 1", __FILE__, __LINE__);
        $row2 = mysql_fetch_assoc($request);
        mysql_free_result($request);
        db_query("\n\t\t\tUPDATE {$db_prefix}topics\n\t\t\tSET\n\t\t\t\tID_LAST_MSG = {$row2['ID_MSG']},\n\t\t\t\tnumReplies = IF(numReplies = 0, 0, numReplies - 1),\n\t\t\t\tID_MEMBER_UPDATED = {$row2['ID_MEMBER']}\n\t\t\tWHERE ID_TOPIC = {$row['ID_TOPIC']}\n\t\t\tLIMIT 1", __FILE__, __LINE__);
    } else {
        db_query("\n\t\t\tUPDATE {$db_prefix}topics\n\t\t\tSET numReplies = IF(numReplies = 0, 0, numReplies - 1)\n\t\t\tWHERE ID_TOPIC = {$row['ID_TOPIC']}\n\t\t\tLIMIT 1", __FILE__, __LINE__);
    }
    db_query("\n\t\tUPDATE {$db_prefix}boards\n\t\tSET numPosts = IF(numPosts = 0, 0, numPosts - 1)\n\t\tWHERE ID_BOARD = {$row['ID_BOARD']}\n\t\tLIMIT 1", __FILE__, __LINE__);
    // If the poster was registered and the board this message was on incremented
    // the member's posts when it was posted, decrease his or her post count.
    if (!empty($row['ID_MEMBER']) && $decreasePostCount && empty($row['countPosts'])) {
        updateMemberData($row['ID_MEMBER'], array('posts' => '-'));
    }
    // Only remove posts if they're not recycled.
    if (!$recycle) {
        // Remove the message!
        db_query("\n\t\t\tDELETE FROM {$db_prefix}messages\n\t\t\tWHERE ID_MSG = {$message}\n\t\t\tLIMIT 1", __FILE__, __LINE__);
        if (!empty($modSettings['search_custom_index_config'])) {
            $customIndexSettings = unserialize($modSettings['search_custom_index_config']);
            $words = text2words($row['body'], $customIndexSettings['bytes_per_word'], true);
            if (!empty($words)) {
                db_query("\n\t\t\t\t\tDELETE FROM {$db_prefix}log_search_words\n\t\t\t\t\tWHERE ID_WORD IN (" . implode(', ', $words) . ")\n\t\t\t\t\t\tAND ID_MSG = {$message}", __FILE__, __LINE__);
            }
        }
        // Delete attachment(s) if they exist.
        require_once $sourcedir . '/ManageAttachments.php';
        removeAttachments('a.attachmentType = 0 AND a.ID_MSG = ' . $message);
    }
    // Update the pesky statistics.
    updateStats('message');
    updateStats('topic');
    updateStats('calendar');
    // And now to update the last message of each board we messed with.
    require_once $sourcedir . '/Subs-Post.php';
    if ($recycle) {
        updateLastMessages(array($row['ID_BOARD'], $modSettings['recycle_board']));
    } else {
        updateLastMessages($row['ID_BOARD']);
    }
    return false;
}
Beispiel #26
0
function createAttachment(&$attachmentOptions)
{
    global $modSettings, $sourcedir, $backend_subdir;
    require_once $sourcedir . '/lib/Subs-Graphics.php';
    // We need to know where this thing is going.
    if (!empty($modSettings['currentAttachmentUploadDir'])) {
        if (!is_array($modSettings['attachmentUploadDir'])) {
            $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);
        }
        // Just use the current path for temp files.
        $attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
        $id_folder = $modSettings['currentAttachmentUploadDir'];
    } else {
        $attach_dir = $modSettings['attachmentUploadDir'];
        $id_folder = 1;
    }
    $attachmentOptions['errors'] = array();
    if (!isset($attachmentOptions['post'])) {
        $attachmentOptions['post'] = 0;
    }
    if (!isset($attachmentOptions['approved'])) {
        $attachmentOptions['approved'] = 1;
    }
    $already_uploaded = preg_match('~^post_tmp_' . $attachmentOptions['poster'] . '_\\d+$~', $attachmentOptions['tmp_name']) != 0;
    $file_restricted = @ini_get('open_basedir') != '' && !$already_uploaded;
    if ($already_uploaded) {
        $attachmentOptions['tmp_name'] = $attach_dir . '/' . $attachmentOptions['tmp_name'];
    }
    // Make sure the file actually exists... sometimes it doesn't.
    if (!$file_restricted && !file_exists($attachmentOptions['tmp_name']) || !$already_uploaded && !is_uploaded_file($attachmentOptions['tmp_name'])) {
        $attachmentOptions['errors'] = array('could_not_upload');
        return false;
    }
    // These are the only valid image types for SMF.
    $validImageTypes = array(1 => 'gif', 2 => 'jpeg', 3 => 'png', 5 => 'psd', 6 => 'bmp', 7 => 'tiff', 8 => 'tiff', 9 => 'jpeg', 14 => 'iff');
    if (!$file_restricted || $already_uploaded) {
        $size = @getimagesize($attachmentOptions['tmp_name']);
        list($attachmentOptions['width'], $attachmentOptions['height']) = $size;
        // If it's an image get the mime type right.
        if (empty($attachmentOptions['mime_type']) && $attachmentOptions['width']) {
            // Got a proper mime type?
            if (!empty($size['mime'])) {
                $attachmentOptions['mime_type'] = $size['mime'];
            } elseif (isset($validImageTypes[$size[2]])) {
                $attachmentOptions['mime_type'] = 'image/' . $validImageTypes[$size[2]];
            }
        }
    }
    // Get the hash if no hash has been given yet.
    if (empty($attachmentOptions['file_hash'])) {
        $attachmentOptions['file_hash'] = getAttachmentFilename($attachmentOptions['name'], false, null, true);
    }
    // Is the file too big?
    if (!empty($modSettings['attachmentSizeLimit']) && $attachmentOptions['size'] > $modSettings['attachmentSizeLimit'] * 1024) {
        $attachmentOptions['errors'][] = 'too_large';
    }
    if (!empty($modSettings['attachmentCheckExtensions'])) {
        $allowed = explode(',', strtolower($modSettings['attachmentExtensions']));
        foreach ($allowed as $k => $dummy) {
            $allowed[$k] = trim($dummy);
        }
        if (!in_array(strtolower(substr(strrchr($attachmentOptions['name'], '.'), 1)), $allowed)) {
            $attachmentOptions['errors'][] = 'bad_extension';
        }
    }
    if (!empty($modSettings['attachmentDirSizeLimit'])) {
        // This is a really expensive operation for big numbers of
        // attachments, which is also very easy to cache. Only do it
        // every ten minutes.
        if (empty($modSettings['attachment_dirsize']) || empty($modSettings['attachment_dirsize_time']) || $modSettings['attachment_dirsize_time'] < time() - 600) {
            // It has been cached - just work with this value for now!
            $dirSize = $modSettings['attachment_dirsize'];
        } else {
            // Make sure the directory isn't full.
            $dirSize = 0;
            $dir = @opendir($attach_dir) or fatal_lang_error('cant_access_upload_path', 'critical');
            while ($file = readdir($dir)) {
                if ($file == '.' || $file == '..') {
                    continue;
                }
                if (preg_match('~^post_tmp_\\d+_\\d+$~', $file) != 0) {
                    // Temp file is more than 5 hours old!
                    if (filemtime($attach_dir . '/' . $file) < time() - 18000) {
                        @unlink($attach_dir . '/' . $file);
                    }
                    continue;
                }
                $dirSize += filesize($attach_dir . '/' . $file);
            }
            closedir($dir);
            updateSettings(array('attachment_dirsize' => $dirSize, 'attachment_dirsize_time' => time()));
        }
        // Too big!  Maybe you could zip it or something...
        if ($attachmentOptions['size'] + $dirSize > $modSettings['attachmentDirSizeLimit'] * 1024) {
            $attachmentOptions['errors'][] = 'directory_full';
        } elseif (!isset($modSettings['attachment_full_notified']) && $modSettings['attachmentDirSizeLimit'] > 4000 && $attachmentOptions['size'] + $dirSize > ($modSettings['attachmentDirSizeLimit'] - 2000) * 1024) {
            require_once $sourcedir . '/lib/Subs-Admin.php';
            emailAdmins('admin_attachments_full');
            updateSettings(array('attachment_full_notified' => 1));
        }
    }
    // Check if the file already exists.... (for those who do not encrypt their filenames...)
    if (empty($modSettings['attachmentEncryptFilenames'])) {
        // Make sure they aren't trying to upload a nasty file.
        $disabledFiles = array('con', 'com1', 'com2', 'com3', 'com4', 'prn', 'aux', 'lpt1', '.htaccess', 'index.php');
        if (in_array(strtolower(basename($attachmentOptions['name'])), $disabledFiles)) {
            $attachmentOptions['errors'][] = 'bad_filename';
        }
        // Check if there's another file with that name...
        $request = smf_db_query('
			SELECT id_attach
			FROM {db_prefix}attachments
			WHERE filename = {string:filename}
			LIMIT 1', array('filename' => strtolower($attachmentOptions['name'])));
        if (mysql_num_rows($request) > 0) {
            $attachmentOptions['errors'][] = 'taken_filename';
        }
        mysql_free_result($request);
    }
    if (!empty($attachmentOptions['errors'])) {
        return false;
    }
    if (!is_writable($attach_dir)) {
        fatal_lang_error('attachments_no_write', 'critical');
    }
    // Assuming no-one set the extension let's take a look at it.
    if (empty($attachmentOptions['fileext'])) {
        $attachmentOptions['fileext'] = strtolower(strrpos($attachmentOptions['name'], '.') !== false ? substr($attachmentOptions['name'], strrpos($attachmentOptions['name'], '.') + 1) : '');
        if (strlen($attachmentOptions['fileext']) > 8 || '.' . $attachmentOptions['fileext'] == $attachmentOptions['name']) {
            $attachmentOptions['fileext'] = '';
        }
    }
    smf_db_insert('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'filename' => 'string-255', 'file_hash' => 'string-40', 'fileext' => 'string-8', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'mime_type' => 'string-20', 'approved' => 'int'), array($id_folder, (int) $attachmentOptions['post'], $attachmentOptions['name'], $attachmentOptions['file_hash'], $attachmentOptions['fileext'], (int) $attachmentOptions['size'], empty($attachmentOptions['width']) ? 0 : (int) $attachmentOptions['width'], empty($attachmentOptions['height']) ? '0' : (int) $attachmentOptions['height'], !empty($attachmentOptions['mime_type']) ? $attachmentOptions['mime_type'] : '', (int) $attachmentOptions['approved']), array('id_attach'));
    $attachmentOptions['id'] = smf_db_insert_id('{db_prefix}attachments', 'id_attach');
    if (empty($attachmentOptions['id'])) {
        return false;
    }
    // If it's not approved add to the approval queue.
    if (!$attachmentOptions['approved']) {
        smf_db_insert('', '{db_prefix}approval_queue', array('id_attach' => 'int', 'id_msg' => 'int'), array($attachmentOptions['id'], (int) $attachmentOptions['post']), array());
    }
    $attachmentOptions['destination'] = getAttachmentFilename(basename($attachmentOptions['name']), $attachmentOptions['id'], $id_folder, false, $attachmentOptions['file_hash']);
    if ($already_uploaded) {
        rename($attachmentOptions['tmp_name'], $attachmentOptions['destination']);
    } elseif (!move_uploaded_file($attachmentOptions['tmp_name'], $attachmentOptions['destination'])) {
        fatal_lang_error('attach_timeout', 'critical');
    }
    // Udate the cached directory size, if we care for it.
    if (!empty($modSettings['attachmentDirSizeLimit'])) {
        updateSettings(array('attachment_dirsize' => $modSettings['attachment_dirsize'] + $attachmentOptions['size'], 'attachment_dirsize_time' => time()));
    }
    // Attempt to chmod it.
    @chmod($attachmentOptions['destination'], 0644);
    $size = @getimagesize($attachmentOptions['destination']);
    list($attachmentOptions['width'], $attachmentOptions['height']) = empty($size) ? array(null, null, null) : $size;
    // We couldn't access the file before...
    if ($file_restricted) {
        // Have a go at getting the right mime type.
        if (empty($attachmentOptions['mime_type']) && $attachmentOptions['width']) {
            if (!empty($size['mime'])) {
                $attachmentOptions['mime_type'] = $size['mime'];
            } elseif (isset($validImageTypes[$size[2]])) {
                $attachmentOptions['mime_type'] = 'image/' . $validImageTypes[$size[2]];
            }
        }
        if (!empty($attachmentOptions['width']) && !empty($attachmentOptions['height'])) {
            smf_db_query('
				UPDATE {db_prefix}attachments
				SET
					width = {int:width},
					height = {int:height},
					mime_type = {string:mime_type}
				WHERE id_attach = {int:id_attach}', array('width' => (int) $attachmentOptions['width'], 'height' => (int) $attachmentOptions['height'], 'id_attach' => $attachmentOptions['id'], 'mime_type' => empty($attachmentOptions['mime_type']) ? '' : $attachmentOptions['mime_type']));
        }
    }
    // Security checks for images
    // Do we have an image? If yes, we need to check it out!
    if (isset($validImageTypes[$size[2]])) {
        if (!checkImageContents($attachmentOptions['destination'], !empty($modSettings['attachment_image_paranoid']))) {
            // It's bad. Last chance, maybe we can re-encode it?
            if (empty($modSettings['attachment_image_reencode']) || !reencodeImage($attachmentOptions['destination'], $size[2])) {
                // Nothing to do: not allowed or not successful re-encoding it.
                require_once $sourcedir . '/lib/Subs-ManageAttachments.php';
                removeAttachments(array('id_attach' => $attachmentOptions['id']));
                $attachmentOptions['id'] = null;
                $attachmentOptions['errors'][] = 'bad_attachment';
                return false;
            }
            // Success! However, successes usually come for a price:
            // we might get a new format for our image...
            $old_format = $size[2];
            $size = @getimagesize($attachmentOptions['destination']);
            if (!empty($size) && $size[2] != $old_format) {
                // Let's update the image information
                // !!! This is becoming a mess: we keep coming back and update the database,
                //  instead of getting it right the first time.
                if (isset($validImageTypes[$size[2]])) {
                    $attachmentOptions['mime_type'] = 'image/' . $validImageTypes[$size[2]];
                    smf_db_query('
						UPDATE {db_prefix}attachments
						SET
							mime_type = {string:mime_type}
						WHERE id_attach = {int:id_attach}', array('id_attach' => $attachmentOptions['id'], 'mime_type' => $attachmentOptions['mime_type']));
                }
            }
        }
    }
    if (!empty($attachmentOptions['skip_thumbnail']) || empty($attachmentOptions['width']) && empty($attachmentOptions['height'])) {
        return true;
    }
    // Like thumbnails, do we?
    if (!empty($modSettings['attachmentThumbnails']) && !empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attachmentOptions['width'] > $modSettings['attachmentThumbWidth'] || $attachmentOptions['height'] > $modSettings['attachmentThumbHeight'])) {
        if (createThumbnail($attachmentOptions['destination'], $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) {
            // Figure out how big we actually made it.
            $size = @getimagesize($attachmentOptions['destination'] . '_thumb');
            list($thumb_width, $thumb_height) = $size;
            if (!empty($size['mime'])) {
                $thumb_mime = $size['mime'];
            } elseif (isset($validImageTypes[$size[2]])) {
                $thumb_mime = 'image/' . $validImageTypes[$size[2]];
            } else {
                $thumb_mime = '';
            }
            $thumb_filename = $attachmentOptions['name'] . '_thumb';
            $thumb_size = filesize($attachmentOptions['destination'] . '_thumb');
            $thumb_file_hash = getAttachmentFilename($thumb_filename, false, null, true);
            // To the database we go!
            smf_db_insert('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'attachment_type' => 'int', 'filename' => 'string-255', 'file_hash' => 'string-40', 'fileext' => 'string-8', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'mime_type' => 'string-20', 'approved' => 'int'), array($id_folder, (int) $attachmentOptions['post'], 3, $thumb_filename, $thumb_file_hash, $attachmentOptions['fileext'], $thumb_size, $thumb_width, $thumb_height, $thumb_mime, (int) $attachmentOptions['approved']), array('id_attach'));
            $attachmentOptions['thumb'] = smf_db_insert_id('{db_prefix}attachments', 'id_attach');
            if (!empty($attachmentOptions['thumb'])) {
                smf_db_query('
					UPDATE {db_prefix}attachments
					SET id_thumb = {int:id_thumb}
					WHERE id_attach = {int:id_attach}', array('id_thumb' => $attachmentOptions['thumb'], 'id_attach' => $attachmentOptions['id']));
                rename($attachmentOptions['destination'] . '_thumb', getAttachmentFilename($thumb_filename, $attachmentOptions['thumb'], $id_folder, false, $thumb_file_hash));
            }
        }
    }
    return true;
}
/**
 *	Receives the form for moving tickets to topics, and actually handles the move.
 *
 *	After checking permissions, and so on, begin to actually move posts.
 *
 *	This is done by invoking SMF's createPost function to make the new thread and repost all the ticket's posts as new thread posts
 *	using defaults for some settings.
 *
 *	Operations:
 *	- check the user can see the board they are linking to
 *	- move the ticket's text as the opening post
 *	- update the ticket row if the post was modified before
 *	- get the rest of the replies
 *	- step through and post, updating for modified details
 *	- send the notification PM if we're doing that
 *	- update the attachments table
 *	- update the action log
 *	- remove the ticket from the DB
 *
 *	@see shd_tickettotopic()
 *	@since 1.0
*/
function shd_tickettotopic2()
{
    global $smcFunc, $context, $txt, $modSettings, $scripturl, $sourcedir;
    checkSession();
    checkSubmitOnce('check');
    if (empty($context['ticket_id'])) {
        fatal_lang_error('shd_no_ticket');
    }
    if (isset($_POST['send_pm']) && (!isset($_POST['pm_content']) || trim($_POST['pm_content']) == '')) {
        checkSubmitOnce('free');
        fatal_lang_error('shd_move_no_pm', false);
    }
    // Just in case, are they cancelling?
    if (isset($_REQUEST['cancel'])) {
        redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id']);
    }
    require_once $sourcedir . '/Subs-Post.php';
    // The destination board must be numeric.
    $_POST['toboard'] = (int) $_POST['toboard'];
    $msg_assoc = array();
    // This is complex, very complex. Hopefully 5 minutes will be enough...
    @set_time_limit(300);
    // Make sure they can see the board they are trying to move to (and get whether posts count in the target board).
    $request = shd_db_query('', '
		SELECT b.count_posts, b.name, hdt.subject, hdt.id_member_started, hdtr.body, hdt.id_first_msg, hdtr.smileys_enabled,
		hdtr.modified_time, hdtr.modified_name, hdtr.poster_time, hdtr.id_msg, hdt.deleted_replies, hdt.id_dept
		FROM {db_prefix}boards AS b
			INNER JOIN {db_prefix}helpdesk_tickets AS hdt ON (hdt.id_ticket = {int:ticket})
			INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hdtr.id_msg = hdt.id_first_msg)
		WHERE {query_see_board}
			AND {query_see_ticket}
			AND b.id_board = {int:to_board}
			AND b.redirect = {string:blank_redirect}
		LIMIT 1', array('ticket' => $context['ticket_id'], 'to_board' => $_POST['toboard'], 'blank_redirect' => ''));
    if ($smcFunc['db_num_rows']($request) == 0) {
        fatal_lang_error('no_board');
    } else {
        list($pcounter, $board_name, $subject, $owner, $body, $firstmsg, $smileys_enabled, $modified_time, $modified_name, $time, $shd_id_msg, $deleted_replies, $dept) = $smcFunc['db_fetch_row']($request);
    }
    $smcFunc['db_free_result']($request);
    if (!shd_allowed_to('shd_ticket_to_topic', $dept) || !empty($modSettings['shd_helpdesk_only']) || !empty($modSettings['shd_disable_tickettotopic'])) {
        fatal_lang_error('shd_cannot_move_ticket', false);
    }
    // Are we changing the subject?
    $old_subject = $subject;
    $subject = !empty($_POST['change_subject']) && !empty($_POST['subject']) ? $_POST['subject'] : $subject;
    $context['deleted_prompt'] = false;
    // Hang on... are there any deleted replies?
    if ($deleted_replies > 0) {
        if (shd_allowed_to('shd_access_recyclebin')) {
            $dr_opts = array('abort', 'delete', 'undelete');
            $context['deleted_prompt'] = isset($_REQUEST['deleted_replies']) && in_array($_REQUEST['deleted_replies'], $dr_opts) ? $_REQUEST['deleted_replies'] : 'abort';
        } else {
            fatal_lang_error('shd_cannot_move_ticket_with_deleted');
        }
    }
    if (!empty($context['deleted_prompt']) && $context['deleted_prompt'] == 'abort') {
        redirectexit('action=helpdesk;sa=ticket;ticket=' . $context['ticket_id'] . ';recycle');
    }
    // Now the madness that is custom fields. First, load the custom fields we might/will be using.
    $query = $smcFunc['db_query']('', '
		SELECT hdcf.id_field, hdcf.field_name, hdcf.field_order, hdcf.field_type, hdcf.can_see, hdcf.field_options, hdcf.bbc, hdcf.placement
		FROM {db_prefix}helpdesk_custom_fields_depts AS hdd
			INNER JOIN {db_prefix}helpdesk_custom_fields AS hdcf ON (hdd.id_field = hdcf.id_field)
		WHERE hdd.id_dept = {int:dept}
			AND hdcf.active = {int:active}
		ORDER BY hdcf.field_order', array('dept' => $dept, 'active' => 1));
    $context['custom_fields'] = array();
    $is_staff = shd_allowed_to('shd_staff', $dept);
    $is_admin = shd_allowed_to('admin_helpdesk', $dept);
    while ($row = $smcFunc['db_fetch_assoc']($query)) {
        list($user_see, $staff_see) = explode(',', $row['can_see']);
        $context['custom_fields'][$row['id_field']] = array('id_field' => $row['id_field'], 'name' => $row['field_name'], 'type' => $row['field_type'], 'bbc' => !empty($row['bbc']), 'options' => !empty($row['field_options']) ? unserialize($row['field_options']) : array(), 'placement' => $row['placement'], 'visible' => array('user' => $user_see, 'staff' => $staff_see, 'admin' => true), 'values' => array());
    }
    $smcFunc['db_free_result']($query);
    // Having got all the possible fields for this ticket, let's fetch the values for it. That way if we don't have any values for a field, we don't have to care about showing the user.
    // But first, we need all the message ids.
    $context['ticket_messages'] = array();
    $query = $smcFunc['db_query']('', '
		SELECT id_msg
		FROM {db_prefix}helpdesk_ticket_replies AS hdtr
		WHERE id_ticket = {int:ticket}', array('ticket' => $context['ticket_id']));
    while ($row = $smcFunc['db_fetch_row']($query)) {
        $context['ticket_messages'][] = $row[0];
    }
    $smcFunc['db_free_result']($query);
    // Now get a reference for the field values.
    $query = $smcFunc['db_query']('', '
		SELECT cfv.id_post, cfv.id_field, cfv.post_type, cfv.value
		FROM {db_prefix}helpdesk_custom_fields_values AS cfv
		WHERE (cfv.id_post = {int:ticket} AND cfv.post_type = 1)' . (!empty($context['ticket_messages']) ? '
			OR (cfv.id_post IN ({array_int:msgs}) AND cfv.post_type = 2)' : ''), array('ticket' => $context['ticket_id'], 'msgs' => $context['ticket_messages']));
    while ($row = $smcFunc['db_fetch_assoc']($query)) {
        if (isset($context['custom_fields'][$row['id_field']])) {
            $context['custom_fields'][$row['id_field']]['values'][$row['post_type']][$row['id_post']] = $row['value'];
        }
    }
    $smcFunc['db_free_result']($query);
    // Having now established what fields we do actually have values for, let's proceed to deal with them.
    foreach ($context['custom_fields'] as $field_id => $field) {
        // Didn't we have any values? If not, prune it, not interested.
        if (empty($field['values'])) {
            unset($context['custom_fields'][$field_id]);
        }
        // If the user is an administrator, they can always see the fields.
        if ($is_admin) {
            // But users might not be able to, in which case we need to validate that actually, they did need to authorise this one.
            if (!$field['visible']['user'] || !$field['visible']['staff']) {
                $context['custom_fields_warning'] = true;
            }
        } elseif ($is_staff) {
            // So they're staff. But the field might not be visible to them; they can't deal with it whatever.
            if (!$field['visible']['staff']) {
                fatal_lang_error('cannot_shd_move_ticket_topic_hidden_cfs', false);
            } elseif (!$field['visible']['user']) {
                $context['custom_fields_warning'] = true;
            }
        } else {
            // Non staff aren't special. They should not be able to make this decision. If someone can't see it, they don't get to make the choice.
            if (!$field['visible']['user'] || !$field['visible']['staff']) {
                fatal_lang_error('cannot_shd_move_ticket_topic_hidden_cfs', false);
            }
        }
        // Are we ignoring this field? If so, we can now safely get rid of it at this very point.
        if (isset($_POST['field' . $field_id]) && $_POST['field' . $field_id] == 'lose') {
            unset($context['custom_fields'][$field_id]);
        }
    }
    // Were there any special fields? We need to check - and check that they ticked the right box!
    if (!empty($context['custom_fields_warning']) && empty($_POST['accept_move'])) {
        checkSubmitOnce('free');
        fatal_lang_error('shd_ticket_move_reqd_nonselected', false);
    }
    // Just before we do this, make sure we call any hooks. $context has lots of interesting things, as does $_POST.
    call_integration_hook('shd_hook_tickettotopic');
    // OK, so we have some fields, and we're doing something with them. First we need to attach the fields from the ticket to the opening post.
    shd_append_custom_fields($body, $context['ticket_id'], CFIELD_TICKET);
    // All okay, it seems. Let's go create the topic.
    $msgOptions = array('subject' => $subject, 'body' => $body, 'icon' => 'xx', 'smileys_enabled' => !empty($smileys_enabled) ? 1 : 0);
    $topicOptions = array('board' => $_POST['toboard'], 'lock_mode' => 0, 'mark_as_read' => false);
    $posterOptions = array('id' => $owner, 'update_post_count' => empty($pcounter));
    createPost($msgOptions, $topicOptions, $posterOptions);
    // Keep track of SHD msg id to SMF msg id
    $msg_assoc[$shd_id_msg] = $msgOptions['id'];
    // createPost() doesn't handle modified time and name, so we'll fix that here, along with the poster time.
    if (!empty($modified_time)) {
        shd_db_query('', '
			UPDATE {db_prefix}messages
			SET
				modified_time = {int:modified_time},
				modified_name = {string:modified_name},
				poster_time = {int:poster_time}
			WHERE id_msg = {int:id_msg}', array('id_msg' => $firstmsg, 'modified_time' => $modified_time, 'modified_name' => $modified_name, 'poster_time' => $time));
    }
    // Topic created, let's dig out the replies and post them in the topic, if there are any.
    if (isset($topicOptions['id'])) {
        $request = shd_db_query('', '
			SELECT body, id_member, poster_time, poster_name, poster_email, poster_ip, smileys_enabled,
				modified_time, modified_member, modified_name, poster_time, id_msg, message_status
			FROM {db_prefix}helpdesk_ticket_replies AS hdtr
			WHERE id_ticket = {int:ticket}
				AND id_msg > {int:ticket_msg}
			ORDER BY id_msg', array('ticket' => $context['ticket_id'], 'ticket_msg' => $firstmsg));
        // The ID of the topic we created
        $topic = $topicOptions['id'];
        if ($smcFunc['db_num_rows']($request) != 0) {
            // Now loop through each reply and post it.  Hopefully there aren't too many. *looks at clock*
            while ($row = $smcFunc['db_fetch_assoc']($request)) {
                if ($row['message_status'] == MSG_STATUS_DELETED && !empty($context['deleted_prompt']) && $context['deleted_prompt'] == 'delete') {
                    // we don't want these replies!
                    continue;
                }
                shd_append_custom_fields($row['body'], $row['id_msg'], CFIELD_REPLY);
                $msgOptions = array('subject' => $txt['response_prefix'] . $subject, 'body' => $row['body'], 'icon' => 'xx', 'smileys_enabled' => !empty($row['smileys_enabled']) ? 1 : 0);
                $topicOptions = array('id' => $topic, 'board' => $_POST['toboard'], 'lock_mode' => 0, 'mark_as_read' => false);
                $posterOptions = array('id' => $row['id_member'], 'name' => !empty($row['poster_name']) ? $row['poster_name'] : '', 'email' => !empty($row['poster_email']) ? $row['poster_email'] : '', 'ip' => !empty($row['poster_ip']) ? $row['poster_ip'] : '', 'update_post_count' => empty($pcounter));
                createPost($msgOptions, $topicOptions, $posterOptions);
                // Don't forget to note what id
                $msg_assoc[$row['id_msg']] = $msgOptions['id'];
                // Meh, createPost() doesn't have any hooks for modified time and user. Let's fix that now.
                if (!empty($row['modified_time'])) {
                    shd_db_query('', '
						UPDATE {db_prefix}messages
						SET
							modified_time = {int:modified_time},
							modified_name = {string:modified_name},
							poster_time = {int:poster_time}
						WHERE id_msg = {int:id_msg}', array('id_msg' => $msgOptions['id'], 'modified_time' => $row['modified_time'], 'modified_name' => $row['modified_name'], 'poster_time' => $row['poster_time']));
                }
            }
        }
        // Topic: check; Replies: check; Notfiy the ticket starter, if desired.
        if (isset($_POST['send_pm'])) {
            $request = shd_db_query('pm_find_username', '
				SELECT id_member, real_name
				FROM {db_prefix}members
				WHERE id_member = {int:user}
				LIMIT 1', array('user' => $owner));
            list($userid, $username) = $smcFunc['db_fetch_row']($request);
            $smcFunc['db_free_result']($request);
            // Fix the content
            $replacements = array('{user}' => $username, '{subject}' => $old_subject, '{board}' => '[url=' . $scripturl . '?board=' . $_POST['toboard'] . '.0]' . $board_name . '[/url]', '{link}' => $scripturl . '?topic=' . $topic . '.0');
            $message = str_replace(array_keys($replacements), array_values($replacements), $_POST['pm_content']);
            $recipients = array('to' => array($owner), 'bcc' => array());
            sendpm($recipients, $txt['shd_ticket_moved_subject'], un_htmlspecialchars($message));
        }
        // Right, time to do all the attachment fussing too
        if (!empty($msg_assoc)) {
            $attachIDs = array();
            $query = shd_db_query('', '
				SELECT id_attach, id_msg
				FROM {db_prefix}helpdesk_attachments
				WHERE id_msg IN ({array_int:msgs})', array('msgs' => array_keys($msg_assoc)));
            while ($row = $smcFunc['db_fetch_assoc']($query)) {
                $attachIDs[] = $row;
            }
            $smcFunc['db_free_result']($query);
            if (!empty($attachIDs)) {
                // 1. Update all the attachments in the master table; this is the bit that hurts since it can't be done without
                // a query per row :(
                foreach ($attachIDs as $attach) {
                    shd_db_query('', '
						UPDATE {db_prefix}attachments
						SET id_msg = {int:new_msg}
						WHERE id_attach = {int:attach}', array('attach' => $attach['id_attach'], 'new_msg' => $msg_assoc[$attach['id_msg']]));
                }
                // 2. Remove the entries from the SD table since we don't need them no more
                shd_db_query('', '
					DELETE FROM {db_prefix}helpdesk_attachments
					WHERE id_msg IN ({array_int:msgs})', array('msgs' => array_keys($msg_assoc)));
            }
        }
        // Well, it's possible there are some phantom attachments on deleted replies that need to disappear
        if (!empty($context['deleted_replies']) && $context['deleted_replies'] == 'delete') {
            $query = shd_db_query('', '
				SELECT id_msg
				FROM {db_prefix}helpdesk_attachments AS hda
					INNER JOIN {db_prefix}helpdesk_ticket_replies AS hdtr ON (hda.id_msg = hdtr.id_msg)
				WHERE id_ticket = {int:ticket}
					AND hdtr.message_status = {int:deleted}', array('ticket' => $context['ticket_id'], 'deleted' => MSG_STATUS_DELETED));
            if ($smcFunc['db_num_rows']($query) > 0) {
                $msgs = array();
                while ($row = $smcFunc['db_fetch_row']($query)) {
                    $msgs[] = $row[0];
                }
                if (!empty($msgs)) {
                    // Get rid of the parents
                    require_once $sourcedir . '/ManageAttachments.php';
                    $attachmentQuery = array('attachment_type' => 0, 'id_msg' => 0, 'id_attach' => $msgs);
                    removeAttachments($attachmentQuery);
                    // Get rid of the remainder in hda table
                    shd_db_query('', '
						DELETE FROM {db_prefix}helpdesk_attachments
						WHERE id_ticket = {int:ticket}', array('ticket' => $context['ticket_id']));
                }
            }
            $smcFunc['db_free_result']($query);
        }
        // Now we'll add this to the log.
        $log_params = array('subject' => $subject, 'board_id' => $_POST['toboard'], 'board_name' => $board_name, 'ticket' => $topic);
        shd_log_action('tickettotopic', $log_params);
        // Lastly, delete the ticket from the database.
        shd_db_query('', '
			DELETE FROM {db_prefix}helpdesk_tickets
			WHERE id_ticket = {int:ticket}
			LIMIT 1', array('ticket' => $context['ticket_id']));
        // And the replies, too.
        shd_db_query('', '
			DELETE FROM {db_prefix}helpdesk_ticket_replies
			WHERE id_ticket = {int:ticket}', array('ticket' => $context['ticket_id']));
        // And custom fields.
        shd_db_query('', '
			DELETE FROM {db_prefix}helpdesk_custom_fields_values
			WHERE (id_post = {int:ticket} AND post_type = 1)' . (!empty($context['ticket_messages']) ? '
				OR (id_post IN ({array_int:msgs}) AND post_type = 2)' : ''), array('ticket' => $context['ticket_id'], 'msgs' => $context['ticket_messages']));
    } else {
        fatal_lang_error('shd_move_topic_not_created', false);
    }
    // Clear our cache
    shd_clear_active_tickets($dept);
    // Send them to the topic.
    redirectexit('topic=' . $topic . '.0');
}
function loadAttachmentContext($id_msg)
{
    global $attachments, $modSettings, $txt, $scripturl, $topic, $sourcedir, $smcFunc;
    // Set up the attachment info - based on code by Meriadoc.
    $attachmentData = array();
    $have_unapproved = false;
    if (isset($attachments[$id_msg]) && !empty($modSettings['attachmentEnable'])) {
        foreach ($attachments[$id_msg] as $i => $attachment) {
            $attachmentData[$i] = array('id' => $attachment['id_attach'], 'name' => preg_replace('~&amp;#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($attachment['filename'])), 'downloads' => $attachment['downloads'], 'size' => round($attachment['filesize'] / 1024, 2) . ' ' . $txt['kilobyte'], 'byte_size' => $attachment['filesize'], 'href' => $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['id_attach'], 'link' => '<a href="' . $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['id_attach'] . '">' . htmlspecialchars($attachment['filename']) . '</a>', 'is_image' => !empty($attachment['width']) && !empty($attachment['height']) && !empty($modSettings['attachmentShowImages']), 'is_approved' => $attachment['approved']);
            // If something is unapproved we'll note it so we can sort them.
            if (!$attachment['approved']) {
                $have_unapproved = true;
            }
            if (!$attachmentData[$i]['is_image']) {
                continue;
            }
            $attachmentData[$i]['real_width'] = $attachment['width'];
            $attachmentData[$i]['width'] = $attachment['width'];
            $attachmentData[$i]['real_height'] = $attachment['height'];
            $attachmentData[$i]['height'] = $attachment['height'];
            // Let's see, do we want thumbs?
            if (!empty($modSettings['attachmentThumbnails']) && !empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attachment['width'] > $modSettings['attachmentThumbWidth'] || $attachment['height'] > $modSettings['attachmentThumbHeight']) && strlen($attachment['filename']) < 249) {
                // A proper thumb doesn't exist yet? Create one!
                if (empty($attachment['id_thumb']) || $attachment['thumb_width'] > $modSettings['attachmentThumbWidth'] || $attachment['thumb_height'] > $modSettings['attachmentThumbHeight'] || $attachment['thumb_width'] < $modSettings['attachmentThumbWidth'] && $attachment['thumb_height'] < $modSettings['attachmentThumbHeight']) {
                    $filename = getAttachmentFilename($attachment['filename'], $attachment['id_attach'], $attachment['id_folder']);
                    require_once $sourcedir . '/Subs-Graphics.php';
                    if (createThumbnail($filename, $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) {
                        // So what folder are we putting this image in?
                        if (!empty($modSettings['currentAttachmentUploadDir'])) {
                            if (!is_array($modSettings['attachmentUploadDir'])) {
                                $modSettings['attachmentUploadDir'] = @unserialize($modSettings['attachmentUploadDir']);
                            }
                            $path = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
                            $id_folder_thumb = $modSettings['currentAttachmentUploadDir'];
                        } else {
                            $path = $modSettings['attachmentUploadDir'];
                            $id_folder_thumb = 1;
                        }
                        // Calculate the size of the created thumbnail.
                        $size = @getimagesize($filename . '_thumb');
                        list($attachment['thumb_width'], $attachment['thumb_height']) = $size;
                        $thumb_size = filesize($filename . '_thumb');
                        // These are the only valid image types for SMF.
                        $validImageTypes = array(1 => 'gif', 2 => 'jpeg', 3 => 'png', 5 => 'psd', 6 => 'bmp', 7 => 'tiff', 8 => 'tiff', 9 => 'jpeg', 14 => 'iff');
                        // What about the extension?
                        $thumb_ext = isset($validImageTypes[$size[2]]) ? $validImageTypes[$size[2]] : '';
                        // Figure out the mime type.
                        if (!empty($size['mime'])) {
                            $thumb_mime = $size['mime'];
                        } else {
                            $thumb_mime = 'image/' . $thumb_ext;
                        }
                        $thumb_filename = $attachment['filename'] . '_thumb';
                        $thumb_hash = getAttachmentFilename($thumb_filename, false, null, true);
                        // Add this beauty to the database.
                        $smcFunc['db_insert']('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'attachment_type' => 'int', 'filename' => 'string', 'file_hash' => 'string', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'fileext' => 'string', 'mime_type' => 'string'), array($id_folder_thumb, $id_msg, 3, $thumb_filename, $thumb_hash, (int) $thumb_size, (int) $attachment['thumb_width'], (int) $attachment['thumb_height'], $thumb_ext, $thumb_mime), array('id_attach'));
                        $old_id_thumb = $attachment['id_thumb'];
                        $attachment['id_thumb'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
                        if (!empty($attachment['id_thumb'])) {
                            $smcFunc['db_query']('', '
								UPDATE {db_prefix}attachments
								SET id_thumb = {int:id_thumb}
								WHERE id_attach = {int:id_attach}', array('id_thumb' => $attachment['id_thumb'], 'id_attach' => $attachment['id_attach']));
                            $thumb_realname = getAttachmentFilename($thumb_filename, $attachment['id_thumb'], $id_folder_thumb, false, $thumb_hash);
                            rename($filename . '_thumb', $thumb_realname);
                            // Do we need to remove an old thumbnail?
                            if (!empty($old_id_thumb)) {
                                require_once $sourcedir . '/ManageAttachments.php';
                                removeAttachments(array('id_attach' => $old_id_thumb), '', false, false);
                            }
                        }
                    }
                }
                // Only adjust dimensions on successful thumbnail creation.
                if (!empty($attachment['thumb_width']) && !empty($attachment['thumb_height'])) {
                    $attachmentData[$i]['width'] = $attachment['thumb_width'];
                    $attachmentData[$i]['height'] = $attachment['thumb_height'];
                }
            }
            if (!empty($attachment['id_thumb'])) {
                $attachmentData[$i]['thumbnail'] = array('id' => $attachment['id_thumb'], 'href' => $scripturl . '?action=dlattach;topic=' . $topic . '.0;attach=' . $attachment['id_thumb'] . ';image');
            }
            $attachmentData[$i]['thumbnail']['has_thumb'] = !empty($attachment['id_thumb']);
            // If thumbnails are disabled, check the maximum size of the image.
            if (!$attachmentData[$i]['thumbnail']['has_thumb'] && (!empty($modSettings['max_image_width']) && $attachment['width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attachment['height'] > $modSettings['max_image_height'])) {
                if (!empty($modSettings['max_image_width']) && (empty($modSettings['max_image_height']) || $attachment['height'] * $modSettings['max_image_width'] / $attachment['width'] <= $modSettings['max_image_height'])) {
                    $attachmentData[$i]['width'] = $modSettings['max_image_width'];
                    $attachmentData[$i]['height'] = floor($attachment['height'] * $modSettings['max_image_width'] / $attachment['width']);
                } elseif (!empty($modSettings['max_image_width'])) {
                    $attachmentData[$i]['width'] = floor($attachment['width'] * $modSettings['max_image_height'] / $attachment['height']);
                    $attachmentData[$i]['height'] = $modSettings['max_image_height'];
                }
            } elseif ($attachmentData[$i]['thumbnail']['has_thumb']) {
                // If the image is too large to show inline, make it a popup.
                if (!empty($modSettings['max_image_width']) && $attachmentData[$i]['real_width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attachmentData[$i]['real_height'] > $modSettings['max_image_height']) {
                    $attachmentData[$i]['thumbnail']['javascript'] = 'return reqWin(\'' . $attachmentData[$i]['href'] . ';image\', ' . ($attachment['width'] + 20) . ', ' . ($attachment['height'] + 20) . ', true);';
                } else {
                    $attachmentData[$i]['thumbnail']['javascript'] = 'return expandThumb(' . $attachment['id_attach'] . ');';
                }
            }
            if (!$attachmentData[$i]['thumbnail']['has_thumb']) {
                $attachmentData[$i]['downloads']++;
            }
        }
    }
    // Do we need to instigate a sort?
    if ($have_unapproved) {
        usort($attachmentData, 'approved_attach_sort');
    }
    return $attachmentData;
}
Beispiel #29
0
function shd_attachment_info($attach_info)
{
    global $scripturl, $context, $modSettings, $txt, $sourcedir, $smcFunc;
    $filename = preg_replace('~&amp;#(\\d{1,7}|x[0-9a-fA-F]{1,6});~', '&#\\1;', htmlspecialchars($attach_info['filename']));
    $deleteable = shd_allowed_to('shd_delete_attachment', $context['ticket']['dept']);
    $attach = array('id' => $attach_info['id_attach'], 'name' => $filename, 'size' => round($attach_info['filesize'] / 1024, 2) . ' ' . $txt['kilobyte'], 'byte_size' => $attach_info['filesize'], 'href' => $scripturl . '?action=dlattach;ticket=' . $context['ticket_id'] . '.0;attach=' . $attach_info['id_attach'], 'link' => shd_attach_icon($filename) . '&nbsp;<a href="' . $scripturl . '?action=dlattach;ticket=' . $context['ticket_id'] . '.0;attach=' . $attach_info['id_attach'] . '">' . htmlspecialchars($attach_info['filename']) . '</a>', 'is_image' => !empty($modSettings['attachmentShowImages']) && !empty($attach_info['width']) && !empty($attach_info['height']), 'can_delete' => $deleteable);
    if ($attach['is_image']) {
        $attach += array('real_width' => $attach_info['width'], 'width' => $attach_info['width'], 'real_height' => $attach_info['height'], 'height' => $attach_info['height']);
        // Let's see, do we want thumbs?
        if (!empty($modSettings['attachmentThumbnails']) && !empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attach_info['width'] > $modSettings['attachmentThumbWidth'] || $attach_info['height'] > $modSettings['attachmentThumbHeight']) && strlen($attach_info['filename']) < 249) {
            // A proper thumb doesn't exist yet? Create one!
            if (empty($attach_info['id_thumb']) || $attach_info['thumb_width'] > $modSettings['attachmentThumbWidth'] || $attach_info['thumb_height'] > $modSettings['attachmentThumbHeight'] || $attach_info['thumb_width'] < $modSettings['attachmentThumbWidth'] && $attach_info['thumb_height'] < $modSettings['attachmentThumbHeight']) {
                $filename = getAttachmentFilename($attach_info['filename'], $attach_info['id_attach'], $attach_info['id_folder']);
                require_once $sourcedir . '/Subs-Graphics.php';
                if (createThumbnail($filename, $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight'])) {
                    // So what folder are we putting this image in?
                    if (!empty($modSettings['currentAttachmentUploadDir'])) {
                        if (!is_array($modSettings['attachmentUploadDir'])) {
                            $modSettings['attachmentUploadDir'] = json_decode($modSettings['attachmentUploadDir'], true);
                        }
                        $path = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
                        $id_folder_thumb = $modSettings['currentAttachmentUploadDir'];
                    } else {
                        $path = $modSettings['attachmentUploadDir'];
                        $id_folder_thumb = 1;
                    }
                    // Calculate the size of the created thumbnail.
                    $size = @getimagesize($filename . '_thumb');
                    list($attach_info['thumb_width'], $attach_info['thumb_height']) = $size;
                    $thumb_size = filesize($filename . '_thumb');
                    // These are the only valid image types for SMF.
                    $validImageTypes = array(1 => 'gif', 2 => 'jpeg', 3 => 'png', 5 => 'psd', 6 => 'bmp', 7 => 'tiff', 8 => 'tiff', 9 => 'jpeg', 14 => 'iff');
                    // What about the extension?
                    $thumb_ext = isset($validImageTypes[$size[2]]) ? $validImageTypes[$size[2]] : '';
                    // Figure out the mime type.
                    if (!empty($size['mime'])) {
                        $thumb_mime = $size['mime'];
                    } else {
                        $thumb_mime = 'image/' . $thumb_ext;
                    }
                    $thumb_filename = $attach_info['filename'] . '_thumb';
                    $thumb_hash = getAttachmentFilename($thumb_filename, false, null, true);
                    // Add this beauty to the database.
                    $smcFunc['db_insert']('', '{db_prefix}attachments', array('id_folder' => 'int', 'id_msg' => 'int', 'attachment_type' => 'int', 'filename' => 'string', 'file_hash' => 'string', 'size' => 'int', 'width' => 'int', 'height' => 'int', 'fileext' => 'string', 'mime_type' => 'string'), array($id_folder_thumb, 0, 3, $thumb_filename, $thumb_hash, (int) $thumb_size, (int) $attach_info['thumb_width'], (int) $attach_info['thumb_height'], $thumb_ext, $thumb_mime), array('id_attach'));
                    $old_id_thumb = $attach_info['id_thumb'];
                    $attach_info['id_thumb'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
                    if (!empty($attach_info['id_thumb'])) {
                        // Update the tables to notify that we has us a thumbnail
                        $smcFunc['db_query']('', '
							UPDATE {db_prefix}attachments
							SET id_thumb = {int:id_thumb}
							WHERE id_attach = {int:id_attach}', array('id_thumb' => $attach_info['id_thumb'], 'id_attach' => $attach_info['id_attach']));
                        $smcFunc['db_insert']('replace', '{db_prefix}helpdesk_attachments', array('id_attach' => 'int', 'id_ticket' => 'int', 'id_msg' => 'int'), array($attach_info['id_thumb'], $attach_info['id_ticket'], $attach_info['id_msg']), array('id_attach'));
                        $thumb_realname = getAttachmentFilename($thumb_filename, $attach_info['id_thumb'], $id_folder_thumb, false, $thumb_hash);
                        rename($filename . '_thumb', $thumb_realname);
                        // Do we need to remove an old thumbnail?
                        if (!empty($old_id_thumb)) {
                            require_once $sourcedir . '/ManageAttachments.php';
                            removeAttachments(array('id_attach' => $old_id_thumb), '', false, false);
                        }
                    }
                }
            }
            // Only adjust dimensions on successful thumbnail creation.
            if (!empty($attach_info['thumb_width']) && !empty($attach_info['thumb_height'])) {
                $attach['width'] = $attach_info['thumb_width'];
                $attach['height'] = $attach_info['thumb_height'];
            }
        }
        if (!empty($attach_info['id_thumb'])) {
            $attach['thumbnail'] = array('id' => $attach_info['id_thumb'], 'href' => $scripturl . '?action=dlattach;ticket=' . $context['ticket_id'] . '.0;attach=' . $attach_info['id_thumb'] . ';image');
        }
        $attach['thumbnail']['has_thumb'] = !empty($attach_info['id_thumb']);
        // If thumbnails are disabled, check the maximum size of the image.
        if (!$attach['thumbnail']['has_thumb'] && (!empty($modSettings['max_image_width']) && $attach_info['width'] > $modSettings['max_image_width'] || !empty($modSettings['max_image_height']) && $attach_info['height'] > $modSettings['max_image_height'])) {
            if (!empty($modSettings['max_image_width']) && (empty($modSettings['max_image_height']) || $attach_info['height'] * $modSettings['max_image_width'] / $attach_info['width'] <= $modSettings['max_image_height'])) {
                $attach['width'] = $modSettings['max_image_width'];
                $attach['height'] = floor($attach_info['height'] * $modSettings['max_image_width'] / $attach_info['width']);
            } elseif (!empty($modSettings['max_image_width'])) {
                $attach['width'] = floor($attach['width'] * $modSettings['max_image_height'] / $attach['height']);
                $attach['height'] = $modSettings['max_image_height'];
            }
        } elseif ($attach['thumbnail']['has_thumb']) {
            // Make it a popup (since invariably it'll break the layout otherwise)
            $attach['thumbnail']['javascript'] = 'return reqWin(\'' . $attach['href'] . ';image\', ' . ($attach_info['width'] + 20) . ', ' . ($attach_info['height'] + 20) . ', true);';
        }
    }
    return $attach;
}