function xthreads_forumdisplay() { global $db, $threadfield_cache, $fid, $mybb, $tf_filters, $xt_filters, $filters_set, $xthreads_forum_filter_form, $xthreads_forum_filter_args; // the position of the "forumdisplay_start" hook is kinda REALLY annoying... $fid = (int) $mybb->input['fid']; if ($fid < 1 || !($forum = get_forum($fid))) { return; } // replicate some MyBB behaviour if (!isset($mybb->input['sortby']) && !empty($forum['defaultsortby'])) { $mybb->input['sortby'] = $forum['defaultsortby']; } $threadfield_cache = xthreads_gettfcache($fid); // Quick Thread integration if (!empty($threadfield_cache) && function_exists('quickthread_run')) { xthreads_forumdisplay_quickthread(); } $fpermissions = forum_permissions($fid); $show_threads = $fpermissions['canview'] == 1 && $fpermissions['canviewthreads'] != 0; $tf_filters = array(); $filters_set = array('__search' => array('hiddencss' => '', 'visiblecss' => 'display: none;', 'selected' => array('' => ' selected="selected"'), 'checked' => array('' => ' checked="checked"'), 'active' => array('' => 'filtertf_active'), 'nullselected' => ' selected="selected"', 'nullchecked' => ' checked="checked"', 'nullactive' => 'filtertf_active'), '__all' => array('hiddencss' => '', 'visiblecss' => 'display: none;', 'nullselected' => ' selected="selected"', 'nullchecked' => ' checked="checked"', 'nullactive' => 'filtertf_active')); $xthreads_forum_filter_form = $xthreads_forum_filter_args = ''; $use_default_filter = true; if (!empty($threadfield_cache)) { if ($show_threads) { function xthreads_forumdisplay_dbhook(&$s, &$db) { global $threadfield_cache, $fid, $plugins, $threadfields, $xthreads_forum_sort; //if(empty($threadfield_cache)) return; $fields = ''; foreach ($threadfield_cache as &$v) { $fields .= ', tfd.`' . $v['field'] . '` AS `xthreads_' . $v['field'] . '`'; } $sortjoin = ''; if (!empty($xthreads_forum_sort) && isset($xthreads_forum_sort['sortjoin'])) { $sortjoin = ' LEFT JOIN ' . $db->table_prefix . $xthreads_forum_sort['sortjoin']; } $s = strtr($s, array('SELECT t.*, ' => 'SELECT t.*' . $fields . ', ', 'WHERE t.fid=' => 'LEFT JOIN `' . $db->table_prefix . 'threadfields_data` tfd ON t.tid=tfd.tid' . $sortjoin . ' WHERE t.fid=')); $plugins->add_hook('forumdisplay_thread', 'xthreads_forumdisplay_thread'); $threadfields = array(); } control_object($db, ' function query($string, $hide_errors=0, $write_query=0) { static $done=false; if(!$done && !$write_query && strpos($string, \'SELECT t.*, \') && strpos($string, \'t.username AS threadusername, u.username\') && strpos($string, \'FROM ' . TABLE_PREFIX . 'threads t\')) { $done = true; xthreads_forumdisplay_dbhook($string, $this); } return parent::query($string, $hide_errors, $write_query); } '); } // also check for forumdisplay filters/sort // and generate form HTML foreach ($threadfield_cache as $n => &$tf) { $filters_set[$n] = array('hiddencss' => '', 'visiblecss' => 'display: none;', 'nullselected' => ' selected="selected"', 'nullchecked' => ' checked="checked"', 'nullactive' => 'filtertf_active'); if ($tf['ignoreblankfilter']) { // will be overwritten if not blank $filters_set[$n]['selected'] = array('' => ' selected="selected"'); $filters_set[$n]['checked'] = array('' => ' checked="checked"'); $filters_set[$n]['active'] = array('' => 'filtertf_active'); } if ($tf['allowfilter'] && isset($mybb->input['filtertf_' . $n]) && xthreads_user_in_groups($tf['viewable_gids'])) { $tf_filters[$n] = $mybb->input['filtertf_' . $n]; $use_default_filter = false; // ignore blank inputs if ($tf['ignoreblankfilter'] && (is_array($tf_filters[$n]) && (empty($tf_filters[$n]) || array_unique($tf_filters[$n]) == array('')) || $tf_filters[$n] === '')) { unset($tf_filters[$n]); } } } // sorting by thread fields if ($mybb->input['sortby'] && substr($mybb->input['sortby'], 0, 2) == 'tf') { global $xthreads_forum_sort; if (substr($mybb->input['sortby'], 0, 3) == 'tf_') { $n = substr($mybb->input['sortby'], 3); if (isset($threadfield_cache[$n]) && xthreads_empty($threadfield_cache[$n]['multival']) && $threadfield_cache[$n]['inputtype'] != XTHREADS_INPUT_FILE && xthreads_user_in_groups($threadfield_cache[$n]['viewable_gids'])) { if ($threadfield_cache[$n]['inputtype'] != XTHREADS_INPUT_TEXTAREA) { // also disallow sorting by textarea inputs $xthreads_forum_sort = array('t' => 'tfd.', 'sortby' => $mybb->input['sortby'], 'sortfield' => '`' . $n . '`'); } } } elseif (substr($mybb->input['sortby'], 0, 4) == 'tfa_') { $p = strpos($mybb->input['sortby'], '_', 5); if ($p) { $field = strtolower(substr($mybb->input['sortby'], 4, $p - 4)); $n = substr($mybb->input['sortby'], $p + 1); if (isset($threadfield_cache[$n]) && xthreads_empty($threadfield_cache[$n]['multival']) && $threadfield_cache[$n]['inputtype'] == XTHREADS_INPUT_FILE && xthreads_user_in_groups($threadfield_cache[$n]['viewable_gids']) && in_array($field, array('filename', 'filesize', 'uploadtime', 'updatetime', 'downloads'))) { $xthreads_forum_sort = array('t' => 'xta.', 'sortby' => $mybb->input['sortby'], 'sortfield' => '`' . $field . '`', 'sortjoin' => 'xtattachments xta ON tfd.`' . $n . '`=xta.aid'); } } } } } if (!isset($xthreads_forum_sort) && $mybb->input['sortby'] && in_array($mybb->input['sortby'], array('prefix', 'icon', 'lastposter', 'numratings', 'attachmentcount'))) { global $xthreads_forum_sort; switch ($mybb->input['sortby']) { case 'prefix': if ($mybb->version_code >= 1500) { $xthreads_forum_sort = array('t' => $mybb->version_code >= 1604 ? 't.' : 'p.', 'sortby' => $mybb->input['sortby'], 'sortfield' => $mybb->input['sortby']); } break; case 'icon': $xthreads_forum_sort = array('t' => 't.', 'sortby' => $mybb->input['sortby'], 'sortfield' => $mybb->input['sortby']); break; case 'lastposter': case 'numratings': case 'attachmentcount': $xthreads_forum_sort = array('t' => 't.', 'sortby' => $mybb->input['sortby'], 'sortfield' => $mybb->input['sortby']); } } $xt_filters = array(); //$enabled_xtf = explode(',', $forum['xthreads_addfiltenable']); //if(!empty($enabled_xtf)) { //global $lang; //foreach($enabled_xtf as &$xtf) { $enabled_xtf = array('uid', 'icon', 'lastposteruid'); if ($mybb->version_code >= 1500) { $enabled_xtf[] = 'prefix'; } foreach ($enabled_xtf as &$xtf) { $filters_set['__xt_' . $xtf] = array('hiddencss' => '', 'visiblecss' => 'display: none;', 'nullselected' => ' selected="selected"', 'nullchecked' => ' checked="checked"', 'nullactive' => 'filtertf_active'); if (isset($mybb->input['filterxt_' . $xtf]) && $mybb->input['filterxt_' . $xtf] !== '') { $xt_filters[$xtf] = $mybb->input['filterxt_' . $xtf]; $use_default_filter = false; } } unset($enabled_xtf); //} if (function_exists('xthreads_evalcacheForumFilters')) { $xtforum = xthreads_evalcacheForumFilters($fid); if ($use_default_filter && (!empty($xtforum['defaultfilter_tf']) || !empty($xtforum['defaultfilter_xt'])) && !$mybb->input['filterdisable']) { $tf_filters = $xtforum['defaultfilter_tf']; foreach ($tf_filters as $n => &$filter) { if (!xthreads_user_in_groups($threadfield_cache[$n]['viewable_gids'])) { unset($tf_filters[$n]); continue; } } $xt_filters = $xtforum['defaultfilter_xt']; } //unset($enabled_xtf); } foreach ($tf_filters as $n => &$filter) { xthreads_forumdisplay_filter_input('filtertf_' . $n, $filter, $filters_set[$n]); } foreach ($xt_filters as $n => &$filter) { /* // sanitise input here as we may need to grab extra info if(is_array($filter)) $filter = array_map('intval', $filter); else $filter = (int)$filter; */ xthreads_forumdisplay_filter_input('filterxt_' . $n, $filter, $filters_set['__xt_' . $n]); /* if(is_array($filter)) $ids = implode(',', $filter); else $ids = $filter; // grab extra info for $filter_set array switch($n) { case 'uid': case 'lastposteruid': // perhaps might be nice if we could merge these two together... $info = xthreads_forumdisplay_xtfilter_extrainfo('users', array('username'), 'uid', $ids, 'guest'); $filters_set['__xt_'.$n]['name'] = $info['username']; break; case 'prefix': // displaystyles? if(!$lang->xthreads_no_prefix) $lang->load('xthreads'); $info = xthreads_forumdisplay_xtfilter_extrainfo('threadprefixes', array('prefix', 'displaystyle'), 'pid', $ids, 'xthreads_no_prefix'); $filters_set['__xt_'.$n]['name'] = $info['prefix']; $filters_set['__xt_'.$n]['displayname'] = $info['displaystyle']; break; case 'icon': // we'll retrieve icons from the cache rather than query the DB $icons = $GLOBALS['cache']->read('posticons'); if(is_array($filter)) $ids =& $filter; else $ids = array($ids); $filters_set['__xt_'.$n]['name'] = ''; $iconstr =& $filters_set['__xt_'.$n]['name']; foreach($ids as $id) { if($id && $icons[$id]) $iconstr .= ($iconstr?', ':'') . htmlspecialchars_uni($icons[$id]['name']); elseif(!$id) { if(!$lang->xthreads_no_icon) $lang->load('xthreads'); $iconstr .= ($iconstr?', ':'') . '<em>'.$lang->xthreads_no_icon.'</em>'; } } unset($icons); break; } */ } unset($filter); if ($xthreads_forum_filter_args) { $filters_set['__all']['urlarg'] = htmlspecialchars_uni(substr($xthreads_forum_filter_args, 1)); $filters_set['__all']['urlarga'] = '&' . $filters_set['__all']['urlarg']; $filters_set['__all']['urlargq'] = '?' . $filters_set['__all']['urlarg']; $filters_set['__all']['forminput'] = $xthreads_forum_filter_form; $filters_set['__all']['hiddencss'] = 'display: none;'; $filters_set['__all']['visiblecss'] = ''; unset($filters_set['__all']['nullselected'], $filters_set['__all']['nullchecked'], $filters_set['__all']['nullactive']); } if ($forum['xthreads_inlinesearch'] && isset($mybb->input['search']) && $mybb->input['search'] !== '') { $urlarg = 'search=' . rawurlencode($mybb->input['search']); $xthreads_forum_filter_args .= '&' . $urlarg; $GLOBALS['xthreads_forum_search_form'] = '<input type="hidden" name="search" value="' . htmlspecialchars_uni($mybb->input['search']) . '" />'; $filters_set['__search']['forminput'] =& $GLOBALS['xthreads_forum_search_form']; $filters_set['__search']['value'] = htmlspecialchars_uni($mybb->input['search']); $filters_set['__search']['urlarg'] = htmlspecialchars_uni($urlarg); $filters_set['__search']['urlarga'] = '&' . $filters_set['__search']['urlarg']; $filters_set['__search']['urlargq'] = '?' . $filters_set['__search']['urlarg']; $filters_set['__search']['selected'] = array($mybb->input['search'] => ' selected="selected"'); $filters_set['__search']['checked'] = array($mybb->input['search'] => ' checked="checked"'); $filters_set['__search']['active'] = array($mybb->input['search'] => 'filtertf_active'); $filters_set['__search']['hiddencss'] = 'display: none;'; $filters_set['__search']['visiblecss'] = ''; unset($filters_set['__search']['nullselected'], $filters_set['__search']['nullchecked'], $filters_set['__search']['nullactive']); } if ($show_threads) { $using_filter = $forum['xthreads_inlinesearch'] || !empty($tf_filters) || !empty($xt_filters); if ($using_filter || isset($xthreads_forum_sort)) { // only nice way to do all of this is to gain control of $templates, so let's do it control_object($GLOBALS['templates'], ' function get($title, $eslashes=1, $htmlcomments=1) { static $done=false; if(!$done && $title == \'forumdisplay_orderarrow\') { $done = true; ' . ($using_filter ? 'xthreads_forumdisplay_filter();' : '') . ' ' . (isset($xthreads_forum_sort) ? ' $orderbyhack = xthreads_forumdisplay_sorter(); return $orderbyhack.parent::get($title, $eslashes, $htmlcomments); ' : '') . ' } return parent::get($title, $eslashes, $htmlcomments); } '); /* if($forum['xthreads_inlinesearch']) { // give us a bit of a free speed up since this isn't really being used anyway... $templates->cache['forumdisplay_searchforum'] = ''; } */ // generate stuff for pagination/sort-links and fields for forms (sort listboxes, inline search) } } if ($forum['xthreads_fdcolspan_offset']) { control_object($GLOBALS['cache'], ' function read($name, $hard=false) { static $done=false; if(!$done && $name == "posticons" && isset($GLOBALS["colspan"])) { $done = true; $GLOBALS["colspan"] += $GLOBALS["foruminfo"]["xthreads_fdcolspan_offset"]; } return parent::read($name, $hard); } '); } }
function xthreads_admin_forumedit_hook_sorter(&$args) { global $lang; static $done = false; if ($done || $args['title'] != $lang->default_view_options) { return; } $done = true; global $view_options, $default_sort_by, $form, $forum_data; if (count($view_options) != 3) { return; } // back out if things seem a little odd // add our custom sortby options here if ($GLOBALS['mybb']->version_code >= 1500) { $default_sort_by['prefix'] = $lang->xthreads_sort_ext_prefix; } $default_sort_by['icon'] = $lang->xthreads_sort_ext_icon; $default_sort_by['lastposter'] = $lang->xthreads_sort_ext_lastposter; $default_sort_by['numratings'] = $lang->xthreads_sort_ext_numratings; $default_sort_by['attachmentcount'] = $lang->xthreads_sort_ext_attachmentcount; $threadfield_cache = xthreads_gettfcache($forum_data['fid'] ? $forum_data['fid'] : -1); if (!empty($threadfield_cache)) { //$changed = false; foreach ($threadfield_cache as &$tf) { if ($tf['inputtype'] == XTHREADS_INPUT_TEXTAREA || !xthreads_empty($tf['multival'])) { continue; } if (!$lang->xthreads_sort_threadfield_prefix) { $lang->load('xthreads'); } //$changed = true; $itemname = $lang->xthreads_sort_threadfield_prefix . $tf['title']; if ($tf['inputtype'] == XTHREADS_INPUT_FILE) { foreach (array('filename', 'filesize', 'uploadtime', 'updatetime', 'downloads') as $tfan) { $langvar = 'xthreads_sort_' . $tfan; $default_sort_by['tfa_' . $tfan . '_' . $tf['field']] = $itemname . ' [' . $lang->{$langvar} . ']'; } } else { $default_sort_by['tf_' . $tf['field']] = $itemname; } } } //if(!$changed) return; // regenerate stuff $view_options[1] = $lang->default_sort_by . "<br />\n" . $form->generate_select_box('defaultsortby', $default_sort_by, $forum_data['defaultsortby'], array('checked' => $forum_data['defaultsortby'], 'id' => 'defaultsortby')); $args['content'] = '<div class="forum_settings_bit">' . implode('</div><div class="forum_settings_bit">', $view_options) . '</div>'; }
function xthreads_upload_attachments() { global $xta_cache, $threadfield_cache, $mybb, $db, $lang, $fid; // only ever execute this function once per page static $done = false; if ($done) { return; } $done = true; if (!$fid) { if ($GLOBALS['forum']['fid']) { $fid = $GLOBALS['forum']['fid']; } elseif ($GLOBALS['foruminfo']['fid']) { $fid = $GLOBALS['foruminfo']['fid']; } elseif ($mybb->input['pid']) { // editpost - not good to trust user input, but should be fine $post = get_post((int) $mybb->input['pid']); if ($post['pid']) { $fid = $post['fid']; } } elseif ($mybb->input['fid']) { // newthread $fid = (int) $mybb->input['fid']; } // we _should_ now have an fid } if (!isset($threadfield_cache)) { $threadfield_cache = xthreads_gettfcache($fid); } // remove uneditable fields xthreads_filter_tfeditable($threadfield_cache, $fid); // NOTE: modifies the global tfcache! if (empty($threadfield_cache)) { return; } if (!is_array($xta_cache)) { $xta_cache = array(); } // first, run through to see if we have already uploaded some attachments // this code totally relies on the posthash being unique... if ($GLOBALS['thread']['tid']) { $attachwhere = 'tid=' . (int) $GLOBALS['thread']['tid']; } else { $attachwhere = 'posthash="' . $db->escape_string($mybb->input['posthash']) . '"'; } $query = $db->simple_select('xtattachments', '*', $attachwhere); $attach_fields = array(); while ($attach = $db->fetch_array($query)) { $xta_cache[$attach['aid']] = $attach; $attach_fields[$attach['field']][] = $attach['aid']; } $db->free_result($query); @ignore_user_abort(true); $errors = array(); $xta_remove = $threadfield_updates = array(); foreach ($threadfield_cache as $k => &$v) { if ($v['inputtype'] != XTHREADS_INPUT_FILE && $v['inputtype'] != XTHREADS_INPUT_FILE_URL) { continue; } $aid =& $mybb->input['xthreads_' . $k]; if ($v['inputtype'] != XTHREADS_INPUT_FILE_URL || is_numeric($mybb->input['xthreads_' . $k])) { $singleval = xthreads_empty($v['multival']); // now, we're ignoring what the user sends us, totally... if ($attach_fields[$k]) { if ($singleval) { $aid = (int) reset($attach_fields[$k]); } else { $aid = array_unique(array_map('intval', $attach_fields[$k])); // re-ordering support if (is_array($mybb->input['xtaorder'])) { $aid_order = array_unique(array_map('intval', $mybb->input['xtaorder'])); if (count($aid) == count($aid_order) && $aid != $aid_order && !count(array_diff($aid, $aid_order))) { $aid = $aid_order; $threadfield_updates[$k] = implode(',', $aid); } } $aid = array_combine($aid, $aid); } } else { $aid = 0; } } // handle file upload $ul = null; if ($singleval) { if (!empty($_FILES['xthreads_' . $k]) && !xthreads_empty($_FILES['xthreads_' . $k]['name']) && is_string($_FILES['xthreads_' . $k]['name'])) { $ul = $_FILES['xthreads_' . $k]; } elseif ($v['inputtype'] == XTHREADS_INPUT_FILE && XTHREADS_ALLOW_URL_FETCH && !xthreads_empty($mybb->input['xtaurl_' . $k])) { // the preg_match is just a basic prelim check - the real URL checking is done later; we need this prelim check to stop it erroring out on the defalt "http://" string if (preg_match('~^[a-z0-9\\-]+\\://[^/?#]+(?:/.*)?$~', $mybb->input['xtaurl_' . $k])) { $ul = $mybb->input['xtaurl_' . $k]; } } !isset($ul) or $ul = array($ul); } else { $ul = array(); if (is_array($mybb->input['xtaurl_' . $k])) { $input_urls = $mybb->input['xtaurl_' . $k]; $input_key_match = true; // if URL input is an array, we'll match with equivalent file input keys } else { $input_urls = explode("\n", str_replace("\r", '', $mybb->input['xtaurl_' . $k])); $input_key_match = false; } if (!empty($_FILES['xthreads_' . $k]) && is_array($_FILES['xthreads_' . $k])) { foreach ($_FILES['xthreads_' . $k]['name'] as $file_k => $filename) { if (!xthreads_empty($filename)) { $file_v = array(); // why does PHP does this and make our life difficult? foreach ($_FILES['xthreads_' . $k] as $fvkey => $fvval) { $file_v[$fvkey] = $fvval[$file_k]; } if ($input_key_match && is_numeric($file_k) || preg_match('~^aid\\d+$~', $file_k)) { $ul[$file_k] = $file_v; } else { $ul[] = $file_v; } } } } if ($v['inputtype'] == XTHREADS_INPUT_FILE && XTHREADS_ALLOW_URL_FETCH && !empty($input_urls) && is_array($input_urls)) { foreach ($input_urls as $url_k => $url_v) { $url_v = trim($url_v); if (preg_match('~^[a-z0-9\\-]+\\://[a-z0-9_\\-@:.]+(?:/.*)?$~', $url_v)) { if ($input_key_match && is_numeric($url_k) || preg_match('~^aid\\d+$~', $url_k)) { isset($ul[$url_k]) or $ul[$url_k] = $url_v; } else { $ul[] = $url_v; } } } } } unset($mybb->input['xtaurl_' . $k], $_FILES['xthreads_' . $k]); // remove files from list first (so we can properly measure the correct final number of attachments when uploading) // fix the threadfield_updates array later on if ($singleval) { if (empty($ul) && $mybb->input['xtarm_' . $k] && $v['editable'] != XTHREADS_EDITABLE_REQ) { // user wants to remove attachment $xta_remove[$aid] = $aid; $aid = 0; } } elseif (!empty($mybb->input['xtarm_' . $k]) && is_array($mybb->input['xtarm_' . $k])) { foreach ($mybb->input['xtarm_' . $k] as $rm_aid => $rm_confirm) { if (!$rm_confirm) { continue; } // double-check they really do want to remove this $xta_remove[$rm_aid] = $rm_aid; unset($aid[$rm_aid]); } } // upload new stuff if (!empty($ul)) { require_once MYBB_ROOT . 'inc/xthreads/xt_upload.php'; $update_aid = is_array($aid) ? 0 : $aid; $failed_urls = array(); // list of any URLs that failed to fetch foreach ($ul as $ul_key => $ul_file) { // hard limit number of files to at least 20 if (!$singleval && is_array($aid)) { // hard limit if (strlen(implode(',', $aid)) >= 245) { if (!$lang->xthreads_xtaerr_error_attachhardlimit) { $lang->load('xthreads'); } $errors[] = $lang->sprintf($lang->xthreads_xtaerr_error_attachhardlimit, htmlspecialchars_uni($v['title'])); break; } // admin defined limit if ($v['multival_limit'] && count($aid) >= $v['multival_limit']) { if (!$lang->xthreads_xtaerr_error_attachnumlimit) { $lang->load('xthreads'); } $errors[] = $lang->sprintf($lang->xthreads_xtaerr_error_attachnumlimit, $v['multival_limit'], htmlspecialchars_uni($v['title'])); break; } } // allow updating a specific attachment in a multi-field thing $update_aid2 = $update_aid; if (!$update_aid2 && is_array($aid) && substr($ul_key, 0, 3) == 'aid') { $update_aid2 = (int) substr($ul_key, 3); if (!in_array($update_aid2, $aid)) { $update_aid2 = 0; } } $attachedfile = upload_xtattachment($ul_file, $v, $mybb->user['uid'], $update_aid2, $GLOBALS['thread']['tid']); if ($attachedfile['error']) { if (!$lang->xthreads_threadfield_attacherror) { $lang->load('xthreads'); } $errors[] = $lang->sprintf($lang->xthreads_threadfield_attacherror, htmlspecialchars_uni($v['title']), $attachedfile['error']); if (is_string($ul_file)) { $failed_urls[] = $ul_file; } } else { //unset($attachedfile['posthash'], $attachedfile['tid'], $attachedfile['downloads']); $xta_cache[$attachedfile['aid']] = $attachedfile; if ($singleval) { unset($mybb->input['xtarm_' . $k]); // since successful upload, don't tick remove box $aid = $attachedfile['aid']; } else { if (is_array($mybb->input['xtarm_' . $k])) { unset($mybb->input['xtarm_' . $k][$attachedfile['aid']]); } is_array($aid) or $aid = array(); // if no aid already set, it will be 0, so turn into array if necessary $aid[$attachedfile['aid']] = $attachedfile['aid']; } // if we were going to remove this file, don't if (isset($xta_remove[$attachedfile['aid']])) { unset($xta_remove[$attachedfile['aid']]); } if ($attachedfile['aid'] != $update_aid2) { // adding a new attachment $threadfield_updates[$k] = $singleval ? $aid : true; } } } // list failed URLs in textboxes if (!empty($failed_urls)) { $mybb->input['xtaurl_' . $k] = implode("\n", $failed_urls); unset($failed_urls); } } // fix threadfield update if removing an item and not already done if (!empty($xta_remove) && !isset($threadfield_updates[$k])) { $threadfield_updates[$k] = $singleval ? 0 : true; } // fix placeholder value if ($threadfield_updates[$k] === true) { $threadfield_updates[$k] = implode(',', $aid); } unset($aid); } if (!empty($xta_remove)) { $db->delete_query('xtattachments', 'aid IN (' . implode(',', $xta_remove) . ')'); foreach ($xta_remove as $aid) { xthreads_rm_attach_fs($xta_cache[$aid]); } } $is_editing = $GLOBALS['current_page'] == 'editpost.php'; // if editing post, also commit change to thread field immediately (waiting for user to submit is unreliable) if (($is_editing || $GLOBALS['thread']['tid'] && $GLOBALS['current_page'] == 'newthread.php') && !empty($threadfield_updates)) { xthreads_db_update_replace('threadfields_data', $threadfield_updates, 'tid', $GLOBALS['thread']['tid']); } @ignore_user_abort(false); if (!empty($errors)) { global $plugins; $is_mybb_18 = $mybb->version_code >= 1700; // MyBB 1.4 - 1.5 // and MyBB 1.6 is inconsistent (does different things on newthread/editpost)... if ($mybb->version_code < 1600 || $is_editing) { // can't find a better way to check other than to check version numbers global $theme, $templates; $errstr = '<li>' . implode('</li><li>', $errors) . '</li>'; if ($is_editing && $is_mybb_18) { // special workaround for MyBB 1.8 $GLOBALS['xt_attach_errors'] =& $errstr; $templates->cache['__xt_orig_error_attacherror'] = $templates->cache['error_attacherror']; function xthreads_upload_attachments_error() { global $theme, $templates, $attacherror, $mybb, $lang, $fid; if ($attacherror) { return; } // already handled by template cache hack $attachedfile = array('error' => '<ul>' . $GLOBALS['xt_attach_errors'] . '</ul>'); eval('$attacherror = "' . $templates->get('__xt_orig_error_attacherror') . '";'); } $plugins->add_hook('editpost_action_start', 'xthreads_upload_attachments_error'); } else { $attachedfile = array('error' => '<ul>' . $errstr . '</ul>'); eval('$GLOBALS[\'attacherror\'] .= "' . $templates->get('error_attacherror') . '";'); } // if there's going to be a MyBB attachment error, and it's not been evaluated yet, shove it in the template to force it through - safe since this function is guaranteed to run only once $templates->cache['error_attacherror'] = str_replace('{$attachedfile[\'error\']}', '<ul>' . strtr($errstr, array('\\' => '\\\\', '$' => '\\$', '{' => '\\{', '}' => '\\}')) . '<li>{$attachedfile[\'error\']}</li></ul>', $templates->cache['error_attacherror']); } elseif ($is_mybb_18) { // for MyBB 1.8 $GLOBALS['xt_attach_errors'] =& $errors; function xthreads_upload_attachments_error() { if (empty($GLOBALS['errors'])) { $GLOBALS['errors'] =& $GLOBALS['xt_attach_errors']; } else { $GLOBALS['errors'] = array_merge($GLOBALS['errors'], $GLOBALS['xt_attach_errors']); } } $plugins->add_hook('newthread_start', 'xthreads_upload_attachments_error'); } else { // for MyBB 1.6 if (empty($GLOBALS['errors'])) { $GLOBALS['errors'] =& $errors; } else { $GLOBALS['errors'] = array_merge($GLOBALS['errors'], $errors); } } $mybb->input['action'] = $is_editing ? 'editpost' : 'newthread'; // block the preview, since a failed upload can stuff it up // lower priority to go before inputdisp function (contention, the function checks for 'previewpost') $plugins->add_hook('newthread_start', 'xthreads_newthread_ulattach_blockpreview', 5); $plugins->add_hook('editpost_start', 'xthreads_editthread_ulattach_blockpreview', 5); } }
function xthreads_get_threadfields($tid, &$threadfields, $noextra = true, $thread = array()) { $tid = (int) $tid; if (!$tid) { return; } if (empty($thread)) { $thread = get_thread($tid); } if ($thread['fid'] == $GLOBALS['fid']) { // use global cache if we're referring to current forum $threadfield_cache =& $GLOBALS['threadfield_cache']; } if (!isset($threadfield_cache)) { $threadfield_cache = xthreads_gettfcache((int) $thread['fid']); } if (!empty($threadfield_cache)) { global $db; $threadfields = $db->fetch_array($db->simple_select('threadfields_data', '`' . implode('`,`', array_keys($threadfield_cache)) . '`', 'tid=' . $tid)); if (!isset($threadfields)) { $threadfields = array(); } foreach ($threadfield_cache as $k => &$v) { xthreads_get_xta_cache($v, $tid); xthreads_sanitize_disp($threadfields[$k], $v, $thread['username'], $noextra); } } }
function xthreads_moderation_custom_do(&$tids, $editstr) { if (!$editstr) { return; } $edits = array(); // caching stuff static $threadfields = null; if (!isset($threadfields)) { $threadfields = xthreads_gettfcache(); } // grab all threadfields require_once MYBB_ROOT . 'inc/xthreads/xt_phptpl_lib.php'; foreach (explode("\n", str_replace("{\n}", "\r", str_replace("\r", '', $editstr))) as $editline) { $editline = trim(str_replace("\r", "\n", $editline)); list($n, $v) = explode('=', $editline, 2); if (!isset($v)) { continue; } // don't allow editing of file fields if (!isset($threadfields[$n]) || $threadfields[$n]['inputtype'] == XTHREADS_INPUT_FILE) { continue; } // we don't do much validation here as we trust admins, right? // this is just a prelim check (speed optimisation) - we'll need to check this again after evaluating conditionals $upperv = strtoupper($v); if (($upperv === '' || $upperv == 'NULL' || $upperv == 'NUL') && $threadfields[$n]['datatype'] != XTHREADS_DATATYPE_TEXT) { $edits[$n] = null; } else { $edits[$n] = $v; xthreads_sanitize_eval($edits[$n], array('VALUE' => null, 'TID' => null)); } } if (empty($edits)) { return; } $modfields = array_keys($edits); global $db; $query = $db->query(' SELECT t.tid, tfd.`' . implode('`, tfd.`', $modfields) . '` FROM ' . TABLE_PREFIX . 'threads t LEFT JOIN ' . TABLE_PREFIX . 'threadfields_data tfd ON t.tid=tfd.tid WHERE t.tid IN (' . implode(',', $tids) . ') '); //$query = $db->simple_select('threadfields_data', 'tid,`'.implode('`,`', $modfields).'`', 'tid IN ('.implode(',', $tids).')'); while ($thread = $db->fetch_array($query)) { $updates = array(); foreach ($edits as $n => $v) { if ($v !== null) { // TODO: allowing conditionals direct access to multivals? $v = trim(eval_str($v, array('VALUE' => $thread[$n], 'TID' => $thread['tid']))); if ($threadfields[$n]['datatype'] != XTHREADS_DATATYPE_TEXT) { $upperv = strtoupper($v); if ($upperv == '' || $upperv == 'NULL' || $upperv == 'NUL') { $v = null; } // TODO: intval/floatval here? } } if ($v !== $thread[$n]) { // we'll do some basic validation for multival fields if (!xthreads_empty($threadfields[$n]['multival'])) { $d = "\n"; if ($threadfields[$n]['inputtype'] == XTHREADS_INPUT_TEXT) { $d = ','; } $v = array_unique(array_map('trim', explode($d, str_replace("\r", '', $v)))); foreach ($v as $key => &$val) { if (xthreads_empty($val)) { unset($v[$key]); } } $v = implode($d, $v); } $updates[$n] = $v; } } if (!empty($updates)) { xthreads_db_update_replace('threadfields_data', $updates, 'tid', $thread['tid']); } } $db->free_result($query); }
function xthreads_portal() { global $threadfield_cache, $mybb; $threadfield_cache = xthreads_gettfcache(); $fids = array_flip(array_map('intval', explode(',', $mybb->settings['portal_announcementsfid']))); $all_fids = $mybb->settings['portal_announcementsfid'] == '-1'; $fields = ''; foreach ($threadfield_cache as $k => &$v) { $available = !$v['forums'] || $all_fids; if (!$available) { foreach (explode(',', $v['forums']) as $fid) { if (isset($fids[$fid])) { $available = true; break; } } } if ($available) { $fields .= ', tfd.`' . $v['field'] . '` AS `xthreads_' . $v['field'] . '`'; } else { unset($threadfield_cache[$k]); } } if ($fields) { // do DB hack control_object($GLOBALS['db'], ' function query($string, $hide_errors=0, $write_query=0) { static $done=false; if(!$done && !$write_query && strpos($string, \'SELECT t.*, t.username AS threadusername, u.username, u.avatar\')) { $done = true; $string = strtr($string, array( \'SELECT t.*, t.username AS threadusername, u.username, u.avatar\' => \'SELECT t.*, t.username AS threadusername, u.username, u.avatar' . $fields . '\', \'FROM ' . TABLE_PREFIX . 'threads t\' => \'FROM ' . TABLE_PREFIX . 'threads t LEFT JOIN ' . TABLE_PREFIX . 'threadfields_data tfd ON t.tid=tfd.tid\' )); } return parent::query($string, $hide_errors, $write_query); } '); } }