Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP Fatal error: Uncaught Error: mysqli_result object is already closed #3

Open
Gerdix opened this issue Jan 1, 2024 · 8 comments
Open

Comments

@Gerdix
Copy link

Gerdix commented Jan 1, 2024

Hi Visman,
This error was in my error log this morning. But the script runs without problems. Unusual.
[01-Jan-2024 06:11:30 UTC] PHP Fatal error: Uncaught Error: mysqli_result object is already closed in /xxx/xxx/xxx/include/dblayer/mysqli_innodb.php:285
Stack trace:
#0 /xxx/xxx/xxx/include/dblayer/mysqli_innodb.php(285): mysqli_free_result()
#1 /xxx/xxx/xxx/footer.php(95): DBLayer->close()
#2 /xxx/xxx/xxx/search.php(393): require('/xxx/xxx/p...')
#3 /xxx/xxx/xxx/rewrite.php(69): require('/xxx/xxx/p...')
punbb#4 {main}
thrown in /xxx/xxx/xxx/include/dblayer/mysqli_innodb.php on line 285

The line numbers do not match the original in footer.php, search.php, rewrite.php because I compressed the files a bit.
Except the include/dblayer/mysqli_innodb.php, which is untouched

PHP 8.3
phpMyAdmin 5.2.1

@MioVisman
Copy link
Owner

This is an elusive error :(
I believe that the $this->query_result check and the mysqli_free_result() command are not needed when closing the connection.

But for now I suggest complicating the condition for testing

			if ($this->query_result instanceof mysqli_result)
				@mysqli_free_result($this->query_result);

replace to

			if ($this->query_result instanceof mysqli_result && property_exists($this->query_result, 'num_rows'))
				@mysqli_free_result($this->query_result);

@Gerdix
Copy link
Author

Gerdix commented Jan 3, 2024

Hi,
I copied your two lines of code, but I get the same error again. This happens when I type something in the (site) search. After entering I get a white page. But if I comment out this line: @mysqli_free_result($this->query_result); the site works without errors. And the search works. Here is currently my test environment: [ndd7.de]

And thank you for all your efforts and work over the past few years. You keep punbb alive. That is invaluable

@MioVisman
Copy link
Owner

Please show me your file /include/search_functions.php

@Gerdix
Copy link
Author

Gerdix commented Jan 3, 2024

<?php
/**
 * Loads various functions that are used for searching the forum.
 *
 * @copyright (C) 2008-2012 PunBB, partially based on code (C) 2008-2009 FluxBB.org
 * @license http://www.gnu.org/licenses/gpl.html GPL version 2 or higher
 * @package PunBB
 */
//
// Cache the results of a search and redirect the user to the results page
//
function create_search_cache($keywords, $author, $search_in = false, $forum = array(-1), $show_as = 'topics', $sort_by = null, $sort_dir = 'DESC') {
	global $forum_db, $forum_user, $forum_config, $forum_url, $lang_search, $lang_common, $db_type;
	$return = ($hook = get_hook('sf_fn_create_search_cache_start')) ? eval($hook) : null;
	if ($return !== null)
		return;
	if (@utf8_strlen(str_replace(array('*', '%'), '', $author)) < 2)
		$author = '';
	if (utf8_strlen(str_replace(array('*', '%'), '', $keywords)) < FORUM_SEARCH_MIN_WORD)
		$keywords = '';
	if (!$keywords && !$author)
		message($lang_search['No terms']);
	$keywords = utf8_strtolower($keywords);
	$author = utf8_strtolower($author);
	// Flood protection
	if ($forum_user['last_search'] && (time() - $forum_user['last_search']) < $forum_user['g_search_flood'] && (time() - $forum_user['last_search']) >= 0)
		message(sprintf($lang_search['Search flood'], $forum_user['g_search_flood']));
	if ($forum_user['is_guest']) {
		$query = array(
			'UPDATE'	=> 'online',
			'SET'		=> 'last_search='.time(),
			'WHERE'		=> 'ident=\''.$forum_db->escape(get_remote_address()).'\'');
	}
	else {
		$query = array(
			'UPDATE'	=> 'users',
			'SET'		=> 'last_search='.time(),
			'WHERE'		=> 'id='.$forum_user['id']);
	}
	($hook = get_hook('sf_fn_create_search_cache_qr_update_last_search_time')) ? eval($hook) : null;
	$forum_db->query_build($query) or error(__FILE__, __LINE__);
	// We need to grab results, insert them into the cache and reload with a search id before showing them
	$keyword_results = $author_results = array();
	// If it's a search for keywords
	if ($keywords) {
		// Remove any apostrophes which aren't part of words
		$keywords = substr(preg_replace('((?<=\W)\'|\'(?=\W))', '', ' '.$keywords.' '), 1, -1);
		// Remove symbols and multiple whitespace
		$keywords = preg_replace('/[\^\$&\(\)<>`"\|,@_\?%~\+\[\]{}:=\/#\\\\;!\.\s]+/', ' ', $keywords);
		// Fill an array with all the words
		$keywords_array = array_unique(explode(' ', $keywords));
		// Remove any words that are not indexed
		$keywords_array = array_filter($keywords_array, 'validate_search_word');
		if (empty($keywords_array))
			no_search_results();
		$word_count = 0;
		$match_type = 'and';
		$result_list = array();
		foreach ($keywords_array as $cur_word) {
			switch ($cur_word) {
				case 'and':
				case 'or':
				case 'not':
					$match_type = $cur_word;
					break;
				default: {
					$query = array(
						'SELECT'	=> 'm.post_id',
						'FROM'		=> 'search_words AS w',
						'JOINS'		=> array(
							array(
								'INNER JOIN'	=> 'search_matches AS m',
								'ON'			=> 'm.word_id=w.id'
							)
						),
						'WHERE'		=> 'w.word LIKE \''.$forum_db->escape(str_replace('*', '%', $cur_word)).'\'');
					// Search in what?
					if ($search_in)
						$query['WHERE'] .= ($search_in > 0 ? ' AND m.subject_match=0' : ' AND m.subject_match=1');
					($hook = get_hook('sf_fn_create_search_cache_qr_get_keyword_hits')) ? eval($hook) : null;
					$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
					$row = array();
					while (list($post_id) = $forum_db->fetch_row($result)) {
						$row[$post_id] = 1;
						if (!$word_count)
							$result_list[$post_id] = 1;
						else if ($match_type == 'or')
							$result_list[$post_id] = 1;
						else if ($match_type == 'not')
							$result_list[$post_id] = 0;
					}
					if ($match_type == 'and' && $word_count) {
						foreach (array_keys($result_list) as $post_id) {
							if (!isset($row[$post_id]))
								$result_list[$post_id] = 0;
						}
					}
					++$word_count;
					$forum_db->free_result($result);
					break;
				}
			}
		}
		foreach ($result_list as $post_id => $matches) {
			if ($matches)
				$keyword_results[] = $post_id;
		}
		unset($result_list);
	}
	// If it's a search for author name (and that author name isn't Guest)
	if ($author && $author != 'guest' && $author != utf8_strtolower($lang_common['Guest'])) {
		$query = array(
			'SELECT'	=> 'u.id',
			'FROM'		=> 'users AS u',
			'WHERE'		=> 'u.username '.($db_type == 'pgsql' ? 'ILIKE' : 'LIKE').' \''.$forum_db->escape(str_replace('*', '%', $author)).'\'');
		($hook = get_hook('sf_fn_create_search_cache_qr_get_author')) ? eval($hook) : null;
		$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
		$user_ids = array();
		while ($row = $forum_db->fetch_row($result)) {
			$user_ids[] = $row[0];
		}
		if (!empty($user_ids)) {
			$query = array(
				'SELECT'	=> 'p.id',
				'FROM'		=> 'posts AS p',
				'WHERE'		=> 'p.poster_id IN('.implode(',', $user_ids).')');
			($hook = get_hook('sf_fn_create_search_cache_qr_get_author_hits')) ? eval($hook) : null;
			$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
			$search_ids = array();
			while ($row = $forum_db->fetch_row($result))
				$author_results[] = $row[0];
			$forum_db->free_result($result);
		}
	}
	if ($author && $keywords) {
		// If we searched for both keywords and author name we want the intersection between the results
		$search_ids = array_intersect($keyword_results, $author_results);
		unset($keyword_results, $author_results);
	}
	else if ($keywords)
		$search_ids = $keyword_results;
	else
		$search_ids = $author_results;
	if (count($search_ids) == 0)
		no_search_results();
	// Setup the default show_as topics search
	$query = array(
		'SELECT'	=> 't.id',
		'FROM'		=> 'posts AS p',
		'JOINS'		=> array(
			array(
				'INNER JOIN'	=> 'topics AS t',
				'ON'			=> 't.id=p.topic_id'
			),
			array(
				'LEFT JOIN'		=> 'forum_perms AS fp',
				'ON'			=> '(fp.forum_id=t.forum_id AND fp.group_id='.$forum_user['g_id'].')'
			)
		),
		'WHERE'		=> '(fp.read_forum IS NULL OR fp.read_forum=1) AND p.id IN('.implode(',', $search_ids).')',
		'GROUP BY'	=> 't.id');
	// Search a specific forum?
	if (!in_array(-1, $forum) || ($forum_config['o_search_all_forums'] == '0' && !$forum_user['is_admmod']))
		$query['WHERE'] .= ' AND t.forum_id IN('.implode(',', $forum).')';
	// Adjust the query if show_as posts
	if ($show_as == 'posts') {
		$query['SELECT'] = 'p.id';
		unset($query['GROUP BY']);
	}
	($hook = get_hook('sf_fn_create_search_cache_qr_get_hits')) ? eval($hook) : null;
	$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
	$search_ids = array();
	while ($row = $forum_db->fetch_row($result))
		$search_ids[] = $row[0];
	// Prune "old" search results
	$query = array(
		'SELECT'	=> 'o.ident',
		'FROM'		=> 'online AS o');
	($hook = get_hook('sf_fn_create_search_cache_qr_get_online_idents')) ? eval($hook) : null;
	$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
	$online_idents = array();
	while ($row = $forum_db->fetch_row($result)) {
		$online_idents[] = '\''.$forum_db->escape($row[0]).'\'';
	}
	if (!empty($online_idents)) {
		$query = array(
			'DELETE'	=> 'search_cache',
			'WHERE'		=> 'ident NOT IN('.implode(',', $online_idents).')');
		($hook = get_hook('sf_fn_create_search_cache_qr_delete_old_cached_searches')) ? eval($hook) : null;
		$forum_db->query_build($query) or error(__FILE__, __LINE__);
	}
	// Final search results
	$search_results = implode(',', $search_ids);
	// Fill an array with our results and search properties
	$search_data = serialize(compact('search_results', 'sort_by', 'sort_dir', 'show_as'));
	$search_id = mt_rand(1, 2147483647);
	$ident = ($forum_user['is_guest']) ? get_remote_address() : $forum_user['username'];
	$query = array(
		'INSERT'	=> 'id, ident, search_data',
		'INTO'		=> 'search_cache',
		'VALUES'	=> $search_id.', \''.$forum_db->escape($ident).'\', \''.$forum_db->escape($search_data).'\'');
	($hook = get_hook('sf_fn_create_search_cache_qr_cache_search')) ? eval($hook) : null;
	$forum_db->query_build($query) or error(__FILE__, __LINE__);
	$return = ($hook = get_hook('sf_fn_create_search_cache_end')) ? eval($hook) : null;
	if ($return !== null)
		return;
	$forum_db->end_transaction();
	$forum_db->close();
	// Redirect the user to the cached result page
	header('Location: '.str_replace('&amp;', '&', forum_link($forum_url['search_results'], $search_id)));
	exit;
}
//
// Generate query to grab the results for a cached search
//
function generate_cached_search_query($search_id, &$show_as) {
	global $forum_db, $db_type, $forum_user, $forum_config;
	$return = ($hook = get_hook('sf_fn_generate_cached_search_query_start')) ? eval($hook) : null;
	if ($return !== null)
		return $return;
	$ident = ($forum_user['is_guest']) ? get_remote_address() : $forum_user['username'];
	$query = array(
		'SELECT'	=> 'sc.search_data',
		'FROM'		=> 'search_cache AS sc',
		'WHERE'		=> 'sc.id='.$search_id.' AND sc.ident=\''.$forum_db->escape($ident).'\'');
	($hook = get_hook('sf_fn_generate_cached_search_query_qr_get_cached_search_data')) ? eval($hook) : null;
	$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
	if ($row = $forum_db->fetch_assoc($result)) {
		$search_data = unserialize($row['search_data']);
		$search_results = $search_data['search_results'];
		$sort_by = $search_data['sort_by'];
		$sort_dir = $search_data['sort_dir'];
		$show_as = $search_data['show_as'];
		unset($search_data);
	}
	else
		return false;
	// If there are no posts, we don't need to execute the query
	if (empty($search_results))
		return false;
	switch ($sort_by) {
		case 1:
			$sort_by_sql = ($show_as == 'topics') ? 't.poster' : 'p.poster';
			break;
		case 2:
			$sort_by_sql = 't.subject';
			break;
		case 3:
			$sort_by_sql = 't.forum_id';
			break;
		default:
			$sort_by_sql = ($show_as == 'topics') ? 't.posted' : 'p.posted';
			($hook = get_hook('sf_fn_generate_cached_search_query_qr_cached_sort_by')) ? eval($hook) : null;
			break;
	}
	if ($show_as == 'posts') {
		$query = array(
			'SELECT'	=> 'p.id AS pid, p.poster AS pposter, p.posted AS pposted, p.poster_id, p.message, p.hide_smilies, t.id AS tid, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.forum_id, f.forum_name',
			'FROM'		=> 'posts AS p',
			'JOINS'		=> array(
				array(
					'INNER JOIN'	=> 'topics AS t',
					'ON'			=> 't.id=p.topic_id'
				),
				array(
					'INNER JOIN'	=> 'forums AS f',
					'ON'			=> 'f.id=t.forum_id'
				)
			),
			'WHERE'		=> 'p.id IN('.$search_results.')',
			'ORDER BY'	=> $sort_by_sql . ' ' . $sort_dir);
		($hook = get_hook('sf_fn_generate_cached_search_query_qr_get_cached_hits_as_posts')) ? eval($hook) : null;
	}
	else {
		$query = array(
			'SELECT'	=> 't.id AS tid, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id, f.forum_name',
			'FROM'		=> 'topics AS t',
			'JOINS'		=> array(
				array(
					'INNER JOIN'	=> 'forums AS f',
					'ON'			=> 'f.id=t.forum_id'
				)
			),
			'WHERE'		=> 't.id IN('.$search_results.')',
			'ORDER BY'	=> $sort_by_sql . ' ' . $sort_dir);
		// With "has posted" indication
		if (!$forum_user['is_guest'] && $forum_config['o_show_dot'] == '1') {
			$query['SELECT'] .= ', p.poster_id AS has_posted';
			$query['JOINS'][]	= array(
				'LEFT JOIN'		=> 'posts AS p',
				'ON'			=> '(p.poster_id='.$forum_user['id'].' AND p.topic_id=t.id)');
			// Must have same columns as in prev SELECT
			$query['GROUP BY'] = 't.id, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id, f.forum_name, p.poster_id';
			($hook = get_hook('sf_fn_generate_cached_search_query_qr_get_has_posted')) ? eval($hook) : null;
		}
		($hook = get_hook('sf_fn_generate_cached_search_query_qr_get_cached_hits_as_topics')) ? eval($hook) : null;
	}
	($hook = get_hook('sf_fn_generate_cached_search_query_end')) ? eval($hook) : null;
	return $query;
}
//
// Generate query to grab the results for an action search (i.e. quicksearch)
//
function generate_action_search_query($action, $value, &$search_id, &$url_type, &$show_as) {
	global $forum_db, $forum_user, $forum_config, $lang_common, $forum_url, $db_type;
	$return = ($hook = get_hook('sf_fn_generate_action_search_query_start')) ? eval($hook) : null;
	if ($return !== null)
		return $return;
	switch ($action) {
		case 'show_new':
			if ($forum_user['is_guest'])
				message($lang_common['No permission']);
			$query = array(
				'SELECT'	=> 't.id AS tid, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id, f.forum_name',
				'FROM'		=> 'topics AS t',
				'JOINS'		=> array(
					array(
						'INNER JOIN'	=> 'forums AS f',
						'ON'			=> 'f.id=t.forum_id'
					),
					array(
						'LEFT JOIN'		=> 'forum_perms AS fp',
						'ON'			=> '(fp.forum_id=f.id AND fp.group_id='.$forum_user['g_id'].')'
					)
				),
				'WHERE'		=> '(fp.read_forum IS NULL OR fp.read_forum=1) AND t.last_post>'.$forum_user['last_visit'].' AND t.moved_to IS NULL',
				'ORDER BY'	=> 't.last_post DESC');
			if ($value != -1)
				$query['WHERE'] .= ' AND f.id='.$value;
			// With "has posted" indication
			if (!$forum_user['is_guest'] && $forum_config['o_show_dot'] == '1') {
				$query['SELECT'] .= ', p.poster_id AS has_posted';
				$query['JOINS'][]	= array(
					'LEFT JOIN'		=> 'posts AS p',
					'ON'			=> '(p.poster_id='.$forum_user['id'].' AND p.topic_id=t.id)');
				// Must have same columns as in prev SELECT
				$query['GROUP BY'] = 't.id, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id, f.forum_name, p.poster_id';
				($hook = get_hook('sf_fn_generate_action_search_query_qr_get_new_topics_has_posted')) ? eval($hook) : null;
			}
			$url_type = $forum_url['search_new_results'];
			$search_id = $value;
			($hook = get_hook('sf_fn_generate_action_search_query_qr_get_new')) ? eval($hook) : null;
			break;
		case 'show_recent':
			$query = array(
				'SELECT'	=> 't.id AS tid, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id, f.forum_name',
				'FROM'		=> 'topics AS t',
				'JOINS'		=> array(
					array(
						'INNER JOIN'	=> 'forums AS f',
						'ON'			=> 'f.id=t.forum_id'
					),
					array(
						'LEFT JOIN'		=> 'forum_perms AS fp',
						'ON'			=> '(fp.forum_id=f.id AND fp.group_id='.$forum_user['g_id'].')'
					)
				),
				'WHERE'		=> '(fp.read_forum IS NULL OR fp.read_forum=1) AND t.last_post>'.(time() - $value).' AND t.moved_to IS NULL',
				'ORDER BY'	=> 't.last_post DESC');
			// With "has posted" indication
			if (!$forum_user['is_guest'] && $forum_config['o_show_dot'] == '1') {
				$query['SELECT'] .= ', p.poster_id AS has_posted';
				$query['JOINS'][]	= array(
					'LEFT JOIN'		=> 'posts AS p',
					'ON'			=> '(p.poster_id='.$forum_user['id'].' AND p.topic_id=t.id)');
				// Must have same columns as in prev SELECT
				$query['GROUP BY'] = 't.id, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id, f.forum_name, p.poster_id';
				($hook = get_hook('sf_fn_generate_action_search_query_qr_get_recent_topics_has_posted')) ? eval($hook) : null;
			}
			$url_type = $forum_url['search_recent_results'];
			$search_id = $value;
			($hook = get_hook('sf_fn_generate_action_search_query_qr_get_recent')) ? eval($hook) : null;
			break;
		case 'show_user_posts':
			$query = array(
				'SELECT'	=> 'p.id AS pid, p.poster AS pposter, p.posted AS pposted, p.poster_id, p.message, p.hide_smilies, t.id AS tid, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.forum_id, f.forum_name',
				'FROM'		=> 'posts AS p',
				'JOINS'		=> array(
					array(
						'INNER JOIN'	=> 'topics AS t',
						'ON'			=> 't.id=p.topic_id'
					),
					array(
						'INNER JOIN'	=> 'forums AS f',
						'ON'			=> 'f.id=t.forum_id'
					),
					array(
						'LEFT JOIN'		=> 'forum_perms AS fp',
						'ON'			=> '(fp.forum_id=f.id AND fp.group_id='.$forum_user['g_id'].')'
					)
				),
				'WHERE'		=> '(fp.read_forum IS NULL OR fp.read_forum=1) AND p.poster_id='.$value,
				'ORDER BY'	=> 'pposted DESC');
			$url_type = $forum_url['search_user_posts'];
			$search_id = $value;
			$show_as = 'posts';
			($hook = get_hook('sf_fn_generate_action_search_query_qr_get_user_posts')) ? eval($hook) : null;
			break;
		case 'show_user_topics':
			$query = array(
				'SELECT'	=> 't.id AS tid, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id, f.forum_name',
				'FROM'		=> 'topics AS t',
				'JOINS'		=> array(
					array(
						'INNER JOIN'	=> 'posts AS p',
						'ON'			=> 't.first_post_id=p.id'
					),
					array(
						'INNER JOIN'	=> 'forums AS f',
						'ON'			=> 'f.id=t.forum_id'
					),
					array(
						'LEFT JOIN'		=> 'forum_perms AS fp',
						'ON'			=> '(fp.forum_id=f.id AND fp.group_id='.$forum_user['g_id'].')'
					)
				),
				'WHERE'		=> '(fp.read_forum IS NULL OR fp.read_forum=1) AND p.poster_id='.$value,
				'ORDER BY'	=> 't.last_post DESC');
			// With "has posted" indication
			if (!$forum_user['is_guest'] && $forum_config['o_show_dot'] == '1') {
				$query['SELECT'] .= ', ps.poster_id AS has_posted';
				$query['JOINS'][]	= array(
					'LEFT JOIN'		=> 'posts AS ps',
					'ON'			=> '(ps.poster_id='.$forum_user['id'].' AND ps.topic_id=t.id)');
				// Must have same columns as in prev SELECT
				$query['GROUP BY'] = 't.id, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id, f.forum_name, ps.poster_id';
				($hook = get_hook('sf_fn_generate_action_search_query_qr_get_user_topics_has_posted')) ? eval($hook) : null;
			}
			$url_type = $forum_url['search_user_topics'];
			$search_id = $value;
			($hook = get_hook('sf_fn_generate_action_search_query_qr_get_user_topics')) ? eval($hook) : null;
			break;
		case 'show_subscriptions':
			if ($forum_user['is_guest'])
				message($lang_common['Bad request']);
			// Check we're allowed to see the subscriptions we're trying to look at
			if ($forum_user['g_id'] != FORUM_ADMIN && $forum_user['id'] != $value)
				message($lang_common['Bad request']);
			$query = array(
				'SELECT'	=> 't.id AS tid, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id, f.forum_name',
				'FROM'		=> 'topics AS t',
				'JOINS'		=> array(
					array(
						'INNER JOIN'	=> 'subscriptions AS s',
						'ON'			=> '(t.id=s.topic_id AND s.user_id='.$value.')'
					),
					array(
						'INNER JOIN'	=> 'forums AS f',
						'ON'			=> 'f.id=t.forum_id'
					),
					array(
						'LEFT JOIN'		=> 'forum_perms AS fp',
						'ON'			=> '(fp.forum_id=f.id AND fp.group_id='.$forum_user['g_id'].')'
					)
				),
				'WHERE'		=> '(fp.read_forum IS NULL OR fp.read_forum=1)',
				'ORDER BY'	=> 't.last_post DESC');
			// With "has posted" indication
			if (!$forum_user['is_guest'] && $forum_config['o_show_dot'] == '1') {
				$query['SELECT'] .= ', p.poster_id AS has_posted';
				$query['JOINS'][]	= array(
					'LEFT JOIN'		=> 'posts AS p',
					'ON'			=> '(p.poster_id='.$forum_user['id'].' AND p.topic_id=t.id)');
				// Must have same columns as in prev SELECT
				$query['GROUP BY'] = 't.id, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id, f.forum_name, p.poster_id';
				($hook = get_hook('sf_fn_generate_action_search_query_qr_get_subscriptions_has_posted')) ? eval($hook) : null;
			}
			$url_type = $forum_url['search_subscriptions'];
			$search_id = $value;
			($hook = get_hook('sf_fn_generate_action_search_query_qr_get_subscriptions')) ? eval($hook) : null;
			break;
		case 'show_forum_subscriptions':
			if ($forum_user['is_guest'])
				message($lang_common['Bad request']);
			// Check we're allowed to see the subscriptions we're trying to look at
			if ($forum_user['g_id'] != FORUM_ADMIN && $forum_user['id'] != $value)
				message($lang_common['Bad request']);
			$query = array(
				'SELECT'	=> 'c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.forum_desc, f.redirect_url, f.moderators, f.num_topics, f.num_posts, f.last_post, f.last_post_id, f.last_poster',
				'FROM'		=> 'categories AS c',
				'JOINS'		=> array(
					array(
						'INNER JOIN'	=> 'forums AS f',
						'ON'			=> 'c.id=f.cat_id'
					),
					array(
						'INNER JOIN'	=> 'forum_subscriptions AS fs',
						'ON'			=> '(f.id=fs.forum_id AND fs.user_id='.$value.')'
					),
					array(
						'LEFT JOIN'		=> 'forum_perms AS fp',
						'ON'			=> '(fp.forum_id=f.id AND fp.group_id='.$forum_user['g_id'].')'
					)
				),
				'WHERE'		=> '(fp.read_forum IS NULL OR fp.read_forum=1)',
				'ORDER BY'	=> 'c.disp_position, c.id, f.disp_position');
			$url_type = $forum_url['search_forum_subscriptions'];
			$search_id = $value;
			($hook = get_hook('sf_fn_generate_action_search_query_qr_get_forum_subscriptions')) ? eval($hook) : null;
			break;
		case 'show_unanswered':
			$query = array(
				'SELECT'	=> 't.id AS tid, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id, f.forum_name',
				'FROM'		=> 'topics AS t',
				'JOINS'		=> array(
					array(
						'INNER JOIN'	=> 'forums AS f',
						'ON'			=> 'f.id=t.forum_id'
					),
					array(
						'LEFT JOIN'		=> 'forum_perms AS fp',
						'ON'			=> '(fp.forum_id=f.id AND fp.group_id='.$forum_user['g_id'].')'
					)
				),
				'WHERE'		=> '(fp.read_forum IS NULL OR fp.read_forum=1) AND t.num_replies=0 AND t.moved_to IS NULL',
				'ORDER BY'	=> 't.last_post DESC');
			// With "has posted" indication
			if (!$forum_user['is_guest'] && $forum_config['o_show_dot'] == '1') {
				$query['SELECT'] .= ', p.poster_id AS has_posted';
				$query['JOINS'][]	= array(
					'LEFT JOIN'		=> 'posts AS p',
					'ON'			=> '(p.poster_id='.$forum_user['id'].' AND p.topic_id=t.id)');
				// Must have same columns as in prev SELECT
				$query['GROUP BY'] = 't.id, t.poster, t.subject, t.first_post_id, t.posted, t.last_post, t.last_post_id, t.last_poster, t.num_replies, t.closed, t.sticky, t.forum_id, f.forum_name, p.poster_id';
				($hook = get_hook('sf_fn_generate_action_search_query_qr_get_unanswered_topics_has_posted')) ? eval($hook) : null;
			}
			$url_type = $forum_url['search_unanswered'];
			($hook = get_hook('sf_fn_generate_action_search_query_qr_get_unanswered')) ? eval($hook) : null;
			break;
	}
	($hook = get_hook('sf_fn_generate_action_search_query_end')) ? eval($hook) : null;
	return $query;
}
//
// Get search results for a specified query, returns number of results
//
function get_search_results($query, &$search_set) {
	global $forum_db, $forum_user, $forum_page, $lang_common;
	$return = ($hook = get_hook('sf_fn_get_search_results_start')) ? eval($hook) : null;
	if ($return !== null)
		return $return;
	$result = $forum_db->query_build($query) or error(__FILE__, __LINE__);
	$search_results = array();
	while ($row = $forum_db->fetch_assoc($result)) {
		$search_results[] = $row;
	}
	// Make sure we actually have some results
	$num_hits = count($search_results);
	if ($num_hits == 0)
		return 0;
	// Work out the settings for pagination
	$forum_page['num_pages'] = ($forum_page['per_page'] == 0) ? 1 : ceil($num_hits / $forum_page['per_page']);
	$forum_page['page'] = (!isset($_GET['p']) || !is_numeric($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $forum_page['num_pages']) ? 1 : $_GET['p'];
	// Determine the topic or post offset (based on $forum_page['page'])
	$forum_page['start_from'] = $forum_page['per_page'] * ($forum_page['page'] - 1);
	$forum_page['finish_at'] = ($forum_page['per_page'] == 0) ? $num_hits : min(($forum_page['start_from'] + $forum_page['per_page']), $num_hits);
	// Fill $search_set with out search hits
	$search_set = array();
	$row_num = 0;
	foreach ($search_results as $row) {
		if ($forum_page['start_from'] <= $row_num && $forum_page['finish_at'] > $row_num)
			$search_set[] = $row;
		++$row_num;
	}
	$forum_db->free_result($result);
	$return = ($hook = get_hook('sf_fn_get_search_results_end')) ? eval($hook) : null;
	if ($return !== null)
		return $return;
	return $num_hits;
}
//
// Output a message if there are no results
//
function no_search_results($action = 'search') {
	global $forum_page, $lang_search, $forum_url;
	$forum_page['search_again'] = '<a href="'.forum_link($forum_url['search']).'">'.$lang_search['Perform new search'].'</a>';
	$return = ($hook = get_hook('sf_fn_no_search_results_start')) ? eval($hook) : null;
	if ($return !== null)
		return;
	switch ($action) {
		case 'show_new':
			message($lang_search['No new posts'], $forum_page['search_again'], $lang_search['Topics with new']);
			break;
		case 'show_recent':
			message($lang_search['No recent posts'], $forum_page['search_again'], $lang_search['Recently active topics']);
			break;
		case 'show_user_posts':
			message($lang_search['No user posts'], $forum_page['search_again'], $lang_search['Posts by user']);
			break;
		case 'show_user_topics':
			message($lang_search['No user topics'], $forum_page['search_again'], $lang_search['Topics by user']);
			break;
		case 'show_subscriptions':
			message($lang_search['No subscriptions'], $forum_page['search_again'], $lang_search['Subscriptions']);
			break;
		case 'show_forum_subscriptions':
			message($lang_search['No forum subscriptions'], $forum_page['search_again'], $lang_search['Forum subscriptions']);
			break;
		case 'show_unanswered':
			message($lang_search['No unanswered'], $forum_page['search_again'], $lang_search['Unanswered topics']);
			break;
		default:
			message($lang_search['No hits'], $forum_page['search_again'], $lang_search['Search results']);
			break;
	}
}
//
// Generate search breadcrumbs
//
function generate_search_crumbs($action = null) {
	global $forum_page, $lang_common, $lang_search, $forum_url, $forum_user, $num_hits, $search_set, $search_id, $show_as;
	$return = ($hook = get_hook('sf_fn_generate_search_crumbs_start')) ? eval($hook) : null;
	if ($return !== null)
		return;
	switch ($action) {
		case 'show_new':
			$forum_page['crumbs'][] = $lang_search['Topics with new'];
			$forum_page['items_info'] = generate_items_info($lang_search['Topics found'], ($forum_page['start_from'] + 1), $num_hits);
			$forum_page['main_head_options']['defined_search'] = '<span'.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><a href="'.forum_link($forum_url['search']).'">'.$lang_search['User defined search'].'</a></span>';
			$forum_page['main_foot_options']['mark_all'] = '<span'.(empty($forum_page['main_foot_options']) ? ' class="first-item"' : '').'><a href="'.forum_link($forum_url['mark_read'], generate_form_token('markread'.$forum_user['id'])).'">'.$lang_common['Mark all as read'].'</a></span>';
			// Add link for show all topics, not only new (updated)
			if ($search_id != -1)
				$forum_page['main_head_options']['show_all'] = '<span'.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><a href="'.forum_link($forum_url['forum'], $search_set[0]['forum_id']).'">'.$lang_search['All Topics'].'</a></span>';
			break;
		case 'show_recent':
			$forum_page['crumbs'][] = $lang_search['Recently active topics'];
			$forum_page['items_info'] = generate_items_info($lang_search['Topics found'], ($forum_page['start_from'] + 1), $num_hits);
			$forum_page['main_head_options']['defined_search'] = '<span'.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><a href="'.forum_link($forum_url['search']).'">'.$lang_search['User defined search'].'</a></span>';
			break;
		case 'show_unanswered':
			$forum_page['crumbs'][] = $lang_search['Unanswered topics'];
			$forum_page['items_info'] = generate_items_info($lang_search['Topics found'], ($forum_page['start_from'] + 1), $num_hits);
			$forum_page['main_head_options']['defined_search'] = '<span'.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><a href="'.forum_link($forum_url['search']).'">'.$lang_search['User defined search'].'</a></span>';
			break;
		case 'show_user_posts':
			$forum_page['crumbs'][] = sprintf($lang_search['Posts by'], $search_set[0]['pposter'], ($forum_page['start_from'] + 1), $num_hits);
			$forum_page['items_info'] = generate_items_info($lang_search['Posts found'], ($forum_page['start_from'] + 1), $num_hits);
			$forum_page['main_head_options']['user_topics'] = '<span'.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><a href="'.forum_link($forum_url['search_user_topics'], $search_id).'">'.sprintf($lang_search['Topics by'], forum_htmlencode($search_set[0]['pposter'])).'</a></span>';
			$forum_page['main_head_options']['defined_search'] = '<span'.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><a href="'.forum_link($forum_url['search']).'">'.$lang_search['User defined search'].'</a></span>';
			break;
		case 'show_user_topics':
			$forum_page['crumbs'][] = sprintf($lang_search['Topics by'], $search_set[0]['poster']);
			$forum_page['items_info'] = generate_items_info($lang_search['Topics found'], ($forum_page['start_from'] + 1), $num_hits);
			$forum_page['main_head_options']['user_posts'] = '<span'.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><a href="'.forum_link($forum_url['search_user_posts'], $search_id).'">'.sprintf($lang_search['Posts by'], forum_htmlencode($search_set[0]['poster'])).'</a></span>';
			$forum_page['main_head_options']['defined_search'] = '<span'.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><a href="'.forum_link($forum_url['search']).'">'.$lang_search['User defined search'].'</a></span>';
			break;
		case 'show_subscriptions':
			$forum_page['crumbs'][] = $lang_search['Subscriptions'];
			$forum_page['items_info'] = generate_items_info($lang_search['Topics found'], ($forum_page['start_from'] + 1), $num_hits);
			$forum_page['main_head_options']['defined_search'] = '<span'.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><a href="'.forum_link($forum_url['search']).'">'.$lang_search['User defined search'].'</a></span>';
			break;
		case 'show_forum_subscriptions':
			$forum_page['crumbs'][] = $lang_search['Forum subscriptions'];
			$forum_page['items_info'] = generate_items_info($lang_search['Forums found'], ($forum_page['start_from'] + 1), $num_hits);
			$forum_page['main_head_options']['defined_search'] = '<span'.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><a href="'.forum_link($forum_url['search']).'">'.$lang_search['User defined search'].'</a></span>';
			break;
		default:
			$forum_page['crumbs'][] = $lang_search['Search results'];
			$forum_page['items_info'] = generate_items_info((($show_as == 'topics') ? $lang_search['Topics found'] : $lang_search['Posts found']), ($forum_page['start_from'] + 1), $num_hits);
			$forum_page['main_head_options']['new_search'] = '<span'.(empty($forum_page['main_head_options']) ? ' class="first-item"' : '').'><a href="'.forum_link($forum_url['search']).'">'.$lang_search['Perform new search'].'</a></span>';
			break;
	}
}
//
// Checks to see if an action is valid
//
function validate_search_action($action) {
	// A list of valid actions (extensions can add their own actions to the array)
	$valid_actions = array('search', 'show_new', 'show_recent', 'show_user_posts', 'show_user_topics', 'show_subscriptions', 'show_forum_subscriptions', 'show_unanswered');
	$return = ($hook = get_hook('sf_fn_validate_actions_start')) ? eval($hook) : null;
	if ($return !== null)
		return $return;
	return in_array($action, $valid_actions);
}

@Gerdix
Copy link
Author

Gerdix commented Jan 3, 2024

Hope, this is right...

@MioVisman
Copy link
Owner

Hmm, you seem to be using the original punbb, but I've made a lot of corrections here.
The current issue has been fixed in a commit ea37df5
You can read a description of all the changes starting from this post https://punbb.informer.com/forums/post/158390/#p158390 and further on the topic.

@Gerdix
Copy link
Author

Gerdix commented Jan 3, 2024

Correct, it was the last version of punbb 1.4.6 (punbb.informer.com) but with all your fixes. All error messages have been corrected. And now I'm on PHP 8.3. This mistake has been the most persistent one so far. I believe the changed line of code:
if ($this->query_result instanceof mysqli_result && property_exists($this->query_result, 'num_rows'))
and comment out this line of code: @mysqli_free_result($this->query_result); and return $result; has eliminated the error (it's just speculative).
At: return $result; the error came: PHP Warning: Undefined variable $result .
The search is working very well so far. But I'll keep testing and keep an eye on it.
It's not exactly a great way, but it's a way ;-)

@Gerdix
Copy link
Author

Gerdix commented Jan 4, 2024

oh my goodness. Somehow I messed up when uploading the files to the server. The file mysqli_innodb.php was already corrected local with your fixes. But somehow the old file ended up on the server. no wonder if it shows me a fatal error. I noticed this when I activated the pan_search_advanced extension and compared the files again. Please excuse the inconvenience and thank you for your time. 👍 💯 Sorry :-(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants