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'] = '&amp;' . $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'] = '&amp;' . $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);
			}
		');
    }
}
Exemple #2
0
 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>';
 }
Exemple #3
0
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);
    }
}
Exemple #4
0
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);
			}
		');
    }
}