<?

// Definitions/general-purpose functions for links/files database

define('NO_REGISTER_GLOBALS', 1);
define('THIS_VERSION', '1.51');

// ======== Configuration
// Database table prefix - switch lines to use standard VB database table names
define('THIS_TABLE', 'local_');
// define ('THIS_TABLE', TABLE_PREFIX);

// Download handling matches VBulletin.  With Internet Explorer, left click 
// with some mimetypes may open file in a browser window. Right click 
// offers "Save As" option.
define('HEADER_BEHAVIOUR','inline');
// Or... left-click always offers Open/Save As dialogue. Can cause "Open"
// problems for pdf files with Internet Explorer and Adobe Acrobat.
// define('HEADER_BEHAVIOUR','');

// Debug handling: creates file error.html in main forums directory
// define('LDEBUG', 1);

globalize($_REQUEST, array(
	'perpage' => INT,
	'pagenumber' => INT
));

$mysql_version = '';
$asb = $DB_site->query("SHOW VARIABLES LIKE 'version'");
while ($myrow = $DB_site->fetch_array($asb)) {
	if ($myrow[Variable_name] == "version") {
		$mysql_version = $myrow[Value];
	}
}
if (preg_match("/(\d+)\.(\d+)\.(\d+)/", $mysql_version, $matches)==1 and $matches[1]>=4) {
	define('CANDO_BOOLEAN','');
}

function write_debug($string) {
	global $bbuserinfo;
	if (defined('LDEBUG')) {
		$fw = fopen("error.html","a");
		fwrite($fw, $bbuserinfo['userid'].': '.$string."<br />\n");
		fclose($fw);
	}
}

write_debug("Action= ".$_REQUEST['action']);

// Assume usergroup 6 is admin - apparently safe?
$is_admin = is_member_of($bbuserinfo, 6);

// Link statuses
$LINK_BROKEN		=	 0;
$LINK_OK			=	 1;
$LINK_NO_ACCESS		=   -1;
$LINK_HIDDEN		=   -3;

// Moderation statuses
$LINK_TO_MODERATE	=   -2;
$LINK_ACCEPTED		=    0;

// Voting limits
$MIN_VOTE			=	 1;
$MAX_VOTE			=	 5;

// Special categories
$BASE_CAT			= 	-1;
$FAVS_CAT			=	-2;
$HIDE_CAT			=   -3;
$AVL_CAT			=   -4;
$BRKN_CAT			=   -5;
$INVD_CAT			=   -6;
$HOT_CAT			=   -7;
$NEW_CAT			=   -8;
$RND_CAT			=   -9;

$READ_BUFFER_SIZE   = 2048;

// Protocols supported
$schemes = array( "http", "https", "ftp", "irc" );
// Access modes (see also admin force_redirect parameter)
// 0 = standard read/rewrite access to url
// 1 = forced redirect 
// 2 = direct html link
$modes   = array( "http"=>0 , "https"=>0 , "ftp"=>0 , "irc"=>2 );

$open_basedir = ini_get('open_basedir');

// ######################### READ PERMISSIONS ############################

$links_permissions = array();
$links_defaults	= array();

// Moderation off by default
$links_defaults["moderate_links"] = '0';

$asb = $DB_site->query("SELECT * FROM ".THIS_TABLE."linksadmin");
while ($admin_settings = $DB_site->fetch_array($asb)) {
	if (substr($admin_settings["settingname"],0,3) == "can") {
		$array = preg_split("/[\s,]+/", $admin_settings["setting"]);
		$links_permissions[$admin_settings["settingname"]] = 0;
		foreach ($array as $group) {
			if (is_member_of($bbuserinfo, $group)) {
				$links_permissions[$admin_settings["settingname"]] = 1;
			}
		}
	} else {
		$links_defaults[$admin_settings["settingname"]] = $admin_settings["setting"];
	}
}

if (!isset($links_defaults["this_version"]) or $links_defaults["this_version"] <> THIS_VERSION) {
	echo '<b>Critical error</b>: software version '.THIS_VERSION.', database version '.$links_defaults["this_version"].'<br />';
	echo 'Cannot continue - ask administrator to install correct verson</b><br />';
	exit;
}
$lfd_version = $links_defaults["this_version"];

if (!isset($links_defaults["default_forumid"])) require_admin_row('default_forumid', '-999');

if (!forumid_is_valid($links_defaults["default_forumid"])) {
	if ($is_admin) {
		eval(print_standard_error('Default_forumid set to an invalid value '.$links_defaults["default_forumid"].
			': <a href='.ADMIN_SCRIPT.'.php?action=admin><b>Administer</b></a>',0));
	} else {
		echo '<b>Critical error</b>: default_forumid set to an invalid value '.$links_defaults["default_forumid"].'<br />';
		echo 'Cannot continue - ask administrator to correct</b><br />';
		exit;
	}
}

// Admin permissions always available to admin group, otherwise we get locked out
if ($is_admin) $links_permissions["can_admin_links"] = 1;

// ######################### CACHE ############################

$linkscat = array();
$linkscat_set = 0;

function get_linkscat() {
	global $DB_site, $linkscat, $linkscat_set;

	if (!$linkscat_set) {
		$asb = $DB_site->query("SELECT * FROM ".THIS_TABLE."linkscat ORDER BY displayorder, catname");
		while ($myrow = $DB_site->fetch_array($asb)) $linkscat[$myrow["catid"]] = $myrow;
		$linkscat_set = 1;
	}

	foreach ($linkscat as $catid => $thiscat) {
		$linkscat[$catid]['childlinks'] = $thiscat['catentry'];
		$linkscat[$catid]['childcats'] = 0;
		$linkscat[$catid]['catsub'] = 0;
	}

	foreach ($linkscat as $thiscatid=>$thiscat) {
		$parents = explode(',', $thiscat['parentlist']);
		foreach ($parents as $p) {
			if ($p > 0) {
				$linkscat[$p]['childlinks'] += $thiscat['catentry'];
				$linkscat[$p]['childcats'] += 1;
			}
		}
		if ($thiscat['parentid'] > 0) {
			$linkscat[$thiscat['parentid']]['catsub'] += 1;
		}
	}

}

get_linkscat();

$links_totrate = array();
$links_numrate = array();
$links_rate_set = 0;

function get_linksratings() {
	global $DB_site, $links_totrate, $links_numrate;
	if (!$links_rate_set) {
		$asb = $DB_site->query("
			SELECT linkid, linkvote
			FROM ".THIS_TABLE."linksrate
		");
		while ($myrow = $DB_site->fetch_array($asb)) {
			$links_totrate[$myrow['linkid']] += $myrow['linkvote'];
			$links_numrate[$myrow['linkid']] += 1;
		}
		$links_rate_set = 1;
	}
}

$mimetype_cache = array();
$mimetype_cache_set = 0;

function get_mimetype($type) {
	global $mimetype_cache, $mimetype_cache_set, $DB_site;

	if (!$mimetype_cache_set) {
		$jumpmime = $DB_site->query("
			SELECT extension, mimetype
			FROM " . TABLE_PREFIX . "attachmenttype AS attachmenttype
			");
		while ($jump=$DB_site->fetch_array($jumpmime)) {
			$mimetype_cache[$jump['extension']] = unserialize($jump['mimetype']);
		}
		$mimetype_cache_set = 1;
	}

	if (strlen($type) <= 1 or !isset($mimetype_cache[$type])) {
		$mimetype = '';
	} else {
		$mimetype = $mimetype_cache[$type];
	}
	return $mimetype;
}

$links_fav = array();
$links_fav_set = 0;

function get_linksfav() {
	global $DB_site, $links_fav, $links_fav_set, $bbuserinfo;

	if (!$links_fav_set) {
		$asb = $DB_site->query("
			SELECT linkid
			FROM ".THIS_TABLE."linksfavs
			WHERE userid='".$bbuserinfo['userid']."'
		");
		while ($myrow = $DB_site->fetch_array($asb)) {
			$links_fav[$myrow['linkid']] = 1;
		}
		$links_fav_set = 1;
	}
}

// ######################### UTILITY ROUTINES ############################

function build_forum_list($parentid = -1, $addbox = 1, $prependchars = '', $permission = '') {

	global $DB_site, $optionselected, $usecategories, $jumpforumid, $jumpforumtitle, $jumpforumbits, $curforumid, $daysprune;
	global $vboptions, $stylevar, $vbphrase, $defaultselected, $forumjump, $bbuserinfo, $selectedone, $session, $_FORUMOPTIONS;
	global $frmjmpsel; // allows context sensitivity for non-forum areas
	global $iforumcache, $forumcache, $gobutton, $permissions;

	if (!isset($iforumcache))
	{
		require_once('./includes/functions_forumlist.php');
		// cache_ordered_forums is probably going to be moved back to functions.php

		// get the iforumcache, as we use it all over the place, not just for forumjump
		cache_ordered_forums(1, 1);
	}


	if (empty($iforumcache["$parentid"]) OR !is_array($iforumcache["$parentid"]))
	{
		return;
	}

	foreach($iforumcache["$parentid"] AS $holder)
	{
		foreach($holder AS $forumid)
		{
			$forumperms = $bbuserinfo['forumpermissions']["$forumid"];
			if ((!($forumperms & CANVIEW) AND $vboptions['hideprivateforums']) OR !($forumcache["$forumid"]['options'] & $_FORUMOPTIONS['showonforumjump']) OR !$forumcache["$forumid"]['displayorder'] OR !($forumcache["$forumid"]['options'] & $_FORUMOPTIONS['active']))
			{
				continue;
			}
			else
			{
				// set $forum from the $forumcache
				$forum = $forumcache["$forumid"];

				$optionvalue = $forumid;
				$optiontitle = $prependchars . " $forum[title]";

				$optionclass = 'fjdpth' . iif($forum['depth'] > 4, 4, $forum['depth']);

				if ($curforumid == $optionvalue)
				{
					$optionselected = HTML_SELECTED;
					$optionclass = 'fjsel';
					$selectedone = 1;
				}
				else
				{
					$optionselected = '';
				}

				eval('$jumpforumbits .= "' . fetch_template('option') . '";');

				build_forum_list($optionvalue, 0, $prependchars . FORUM_PREPEND, $forumperms);

			} // if can view

		} // end foreach ($holder as $forum)
	} // end foreach ($iforumcache[$parentid] as $holder)

	if ($addbox)
	{
		if ($selectedone != 1)
		{
			$defaultselected = HTML_SELECTED;
		}
		if (!is_array($frmjmpsel))
		{
			$frmjmpsel = array();
		}
		if (empty($daysprune))
		{
			$daysprune = '';
		}
		else
		{
			$daysprune = intval($daysprune);
		}
		eval('$forumjump = "' . fetch_template('forumjump') . '";');
	}
}

function construct_category_item($thisparent, $prepend, $cat_selected, $linkscat) {
	$optbit = "";
	foreach ($linkscat as $myrow) {
		if ($myrow["parentid"] == $thisparent) {
			$catid	= $myrow["catid"];
			$catname  = $prepend." ".$myrow["catname"];
			$catsel = iif (in_array($catid, $cat_selected), "selected=\"selected\"", "");
			eval("\$optbit .= \"".fetch_template('links_addnewlink_select')."\";");
			$optbit .= construct_category_item($catid, $prepend."-", $cat_selected, $linkscat);
		}
	}
	return $optbit;
}

function construct_category_list($cat_selected, $allow_none = 0) {
	global $linkscat;
	$optbit = "";
	if ($allow_none) {
		$catname = "None";
		$catid = "-1";
		$catsel = iif (in_array($catid, $cat_selected), "selected=\"selected\"", "");
		eval("\$optbit .= \"".fetch_template('links_addnewlink_select')."\";");
	}
	$optbit .= construct_category_item(-1, "", $cat_selected, $linkscat);
	return $optbit;
}

function construct_parent_list($pcatid) {
	global $linkscat;
	$pbit = "";
	foreach ($pcatid as $thiscat) {
		if (isset($linkscat[$thiscat])) {
			if ($pbit <> "") $pbit .= ", ";
			$pbit .= $linkscat[$thiscat]["catname"];
		}
	}
	if ($pbit == "") $pbit = "None";
	return $pbit;
}

function build_cat_parentlist($catid) {
	global $DB_site, $linkscat;
// Fix category parentlists

	if ($catid == -1) {
		foreach ($linkscat as $thisid => $cat) {
			$linkscat[$thisid]['parentlist'] = "";
		}
	}

	$ids = array_keys($linkscat);
	foreach ($ids as $thisid) {
		if ($linkscat[$thisid]['parentid'] == $catid) {
			if ($linkscat[$thisid]['parentlist'] != "") {
				echo '<b>Fatal error: category loop found - please inform administrator</b><br />';
				exit;
			}
			if ($catid == -1) {
				$linkscat[$thisid]['parentlist'] = $catid;
			} else {
				$linkscat[$thisid]['parentlist'] = $catid.",".$linkscat[$catid]['parentlist'];
			}
			build_cat_parentlist($thisid);
		}
	}

}

function fix_cat_parentlist() {
	global $DB_site, $linkscat;
// Fix parentlists if necessary
	foreach ($linkscat as $thisid => $cat) {
		$tmp_parent[$thisid] = $linkscat[$thisid]['parentlist'];
	}
	build_cat_parentlist(-1);
	foreach ($linkscat as $thisid => $cat) {
		if ($linkscat[$thisid]['parentlist'] != $tmp_parent[$thisid]) {
			$DB_site->query("
				UPDATE ".THIS_TABLE."linkscat
				SET parentlist='".$linkscat[$thisid]['parentlist']."'
				WHERE catid='$thisid'
				LIMIT 1
			");
		}
	}
}

function fix_cat_count() {
	global $DB_site, $linkscat;

// Fix the category counts and dates
	$catcount = array();
	$catdate = array();
	foreach ($linkscat as $catid => $cat) {
		$catcount[$catid] = 0;
		$catdate[$catid] = 0;
	}
	$asb = $DB_site->query("
		SELECT ltoc.catid AS catid, link.linkdate AS linkdate
		FROM ".THIS_TABLE."linkslink AS link
		LEFT JOIN ".THIS_TABLE."linksltoc AS ltoc
		ON link.linkid = ltoc.linkid
	");
	while ($myrow = $DB_site->fetch_array($asb)) {
		if (!isset($catdate[$myrow[catid]])) {
			$catcount[$myrow[catid]] = 1;
			$catdate[$myrow[catid]] = $myrow[linkdate];
		} else {
			$catcount[$myrow[catid]] +=1;
			$catdate[$myrow[catid]] = max($catdate[$myrow[catid]], $myrow[linkdate]);
		}
	}
	foreach ($catcount as $catid => $count) {
		if ($linkscat[$catid]['catentry'] != $count or $linkscat[$catid]['catdate'] != $catdate[$catid]) {
			$DB_site->query("
				UPDATE ".THIS_TABLE."linkscat
				SET catentry=".$count.", catdate=".$catdate[$catid]."
				WHERE catid='$catid'
				LIMIT 1
			");
			$linkscat[$catid]['catentry'] = $count;
			$linkscat[$catid]['catdate'] = $catdate[$catid];
		}
	}
}

function cat_walk($level, $dig) {
	global $linkscat;
	$tree = array();
	if ($dig!=0) {
		$keys = array_keys($linkscat);
		foreach ($keys as $thiskey) {
			$thiscat = $linkscat[$thiskey];
			if ($thiscat['parentid'] == $level) {
				$tree[$thiscat['catid']] = cat_walk($thiscat['catid'], $dig-1);
			}
		}
	}
	return $tree;
}

function local_filename($path) {
	global $links_defaults, $bbuserinfo;
// convert path into an absolute filename, depending on setting of local_file_root
	$lpath = preg_replace("/(.*)\?.*/", "\\1", $path);
	if ($links_defaults['local_file_root']==1) {
		$return_path = realpath($path);
		if (!$return_path) $return_path = $lpath;
	} else {
		$return_path = $_SERVER["DOCUMENT_ROOT"].$lpath;
	}
	write_debug("local_filename($path) returns $return_path");
	return($return_path);
}

function cleanto_fopen($url) {
	global $bbuserinfo, $schemes;
// tidy up a (potentially local/relative) url so that we can use it within an fopen()
	$URLInfo = parse_url($url);
	if ($URLInfo['scheme'] == "" and $URLInfo['host'] == "") {
		$url_clean = local_filename($url);
	} elseif (in_array($URLInfo['scheme'], $schemes)) {
		$url_clean = preg_replace("/ *$/","",$URLInfo['path']);
		$url_clean = $URLInfo['scheme'].'://'.$URLInfo['host'].preg_replace("/ /","%20",$url_clean);
	} else {
		$url_clean = $url;
	}

	foreach($URLInfo as $k => $v) write_debug("cleanto_fopen(): '$k' = '$v'");
	write_debug("cleanto_fopen($url) returns $url_clean");

	return $url_clean;
}

function check_url($url) {
	global $LINK_BROKEN, $LINK_OK, $LINK_NO_ACCESS;
	global $bbuserinfo;
	global $schemes, $modes;
	$URLInfo = parse_url($url);
	if ($URLInfo['scheme'] != "" and !in_array($URLInfo['scheme'], $schemes)) {
		$status = $LINK_NO_ACCESS;
		write_debug("cannot handle scheme ".$URLInfo['scheme']);
	} elseif (isset($modes[$URLInfo['scheme']]) and $modes[$URLInfo['scheme']]==2) {
		$status = $LINK_OK;
	} elseif ($URLInfo['host'] == "") {
		$url_clean = local_filename($url);
		$conn = @fopen($url_clean, "rb");
		write_debug("fopen($url_clean) returns $conn");
		if (!$conn) {
			$status = $LINK_BROKEN;
		} else {
			$stat = @fstat($conn);
			fclose($conn);
			$status = iif ($stat[7]>0, $stat[7], $LINK_OK);
		}
	} else {
		$url_clean = cleanto_fopen($url);
		$conn = @fopen($url_clean, "rb");
		write_debug("fopen($url_clean) returns $conn");
		if (!$conn) {
			$status = $LINK_BROKEN;
		} else {
			fclose($conn);
			$status = $LINK_OK;
		}
	}

	foreach($URLInfo as $k => $v) write_debug("check_url(): '$k' = '$v'");
	write_debug("check_url($url) returns $status");

	return $status;
}

function require_admin_row($row, $initialvalue) {
	global $DB_site;
	$query = "
		SELECT *
		FROM ".THIS_TABLE."linksadmin
		WHERE settingname='".$row."'
		LIMIT 1
	";
	$asb = $DB_site->query($query);
	if (!$DB_site->num_rows($asb)) {
		$DB_site->query("
			INSERT INTO ".THIS_TABLE."linksadmin (settingname, setting)
			VALUES (
			'".$row."',
			'".$initialvalue."'
			)
		");
	}
}

function redirect($gotopage) {
	global $vbphrase;
	$gotopage = str_replace('&amp;', '&', $gotopage);
	echo '<p align="center" class="smallfont"><a href="' . $gotopage . '" onclick="javascript:clearTimeout(timerID);">' . $vbphrase['processing_complete_proceed'] . '</a></p>';
	echo "\n<script type=\"text/javascript\">\n";
	echo "window.location=\"$gotopage\";";
	echo "\n</script>\n";
	exit;
}

function forumid_is_valid($forumid) {
	if ($forumid == -999) {
		return 1;
	} elseif ($forumid <= 0) {
		return 0;
	} else {
		return verify_id('forum', $forumid, 0, 0, 0);
	}
}

function highlight($string, $words) {
	$find = array();
	$replace = array();
	if (preg_match_all("/\"(.*?)\"/", $words, $quoted, PREG_PATTERN_ORDER) != 0) foreach ($quoted[1] as $w) $find[] = '/('.$w.')/i';
	$words = preg_replace(array("/\".*?\"/", "/[\\\+\-<>\(\)\~\"\/]/", "/\*/", "/(^ +| +$)/"), array("", "", "\w*", ""), $words);
	$words = preg_split("/ +/", $words);
	foreach ($words AS $w) if ($w != "") $find[] = '/(\b'.$w.'\b)/i';
	foreach ($find AS $f) $replace[] = '<span class="highlight">$1</span>';
	return preg_replace($find, $replace, $string);
}

// #################### CONSTRUCT MAIN CATBIT

function get_catsubbit ($subtree) {
	global $linkscat, $limitfids;
	$subcatbit = '';
	foreach ($subtree as $subid=>$subchildren) {
		if (in_array($linkscat[$subid]["catforum"], $limitfids)) continue;
		$subname = $linkscat[$subid]["catname"];
		$sublink = $linkscat[$subid]["childlinks"];
		eval("\$subcatbit .= \"".fetch_template('links_subcatbit')."\";");
		$subcatbit .= get_catsubbit($subchildren);
	}
	return $subcatbit;
}

$catstyle = 1;
function get_catlistbit ($thisid, $thischildren, $template, $subdepth=1) {
	global $bbuserinfo, $limitfids, $linkscat, $catstyle, $links_defaults, $tomod;

	$catlistbit = "";
	$thiscat = $linkscat[$thisid];
	if (in_array($thiscat["catforum"], $limitfids)) return $catlistbit;
	if ($thiscat['catmoderate'] and $bbuserinfo['userid'] != $thiscat['catuserid']) return $catlistbit;

	$catid	= $thiscat["catid"];
	$catname  = parse_bbcode2($thiscat["catname"], $links_defaults['allow_html'], $links_defaults['allow_images'], $links_defaults['allow_smilies'], $links_defaults['allow_bbcode']);
	$catusername = $thiscat['catusername'];
	$catuserid = $thiscat['catuserid'];
	$catdesc  = parse_bbcode2($thiscat["catdesc"], $links_defaults['allow_html'], $links_defaults['allow_images'], $links_defaults['allow_smilies'], $links_defaults['allow_bbcode']);
	$catdate = vbdate($vboptions['dateformat'], $thiscat['catdate']);
	$catnew = iif($bbuserinfo['lastvisit'] < $thiscat['catdate'],1,0);
	$catsub = $thiscat["catsub"];
	$catchildsub = $thiscat["childcats"];
	$catentry = $thiscat["catentry"];
	$catchildentry = $thiscat["childlinks"];
	$catclosed = $thiscat["catclosed"];

	$catmoderate = $thiscat["catmoderate"];
	$linkmoderate = $tomod[$thiscat['catid']];

	$subcatnames = "";

	if ($subdepth>=$links_defaults['cat_depth_display'] and $links_defaults['cat_sub_display']>0) {
		$subtree = cat_walk($thisid, $links_defaults['cat_sub_display']);
		$subcatnames = get_catsubbit($subtree);
	}

	$displayorder = $thiscat["displayorder"];
	if (isset($thisorder) and $displayorder != $thisorder) {
		eval("\$catlistbit .= \"".fetch_template('links_linkseparator')."\";");
		$catstyle = 1;
	}
	eval("\$catlistbit .= \"".fetch_template($template)."\";");
	$catstyle = iif($catstyle==1,2,1);
	$thisorder = $displayorder;

	foreach ($thischildren as $childid=>$grandchildren) {
		$catlistbit .= get_catlistbit ($childid, $grandchildren, $template, $subdepth+1);
	}

	return $catlistbit;
}

// #################### CONSTRUCT MAIN LINKBIT

function get_linklistbit($query, $sstring, $pagenumber=1, $perpage=999999, $modlinks=0) {
	global $DB_site, $viewcatid, $vboptions, $links_permissions, $links_defaults;
	global $links_totrate, $links_numrate, $linkscat;
	global $bbuserinfo;
	global $LINK_TO_MODERATE, $LINK_HIDDEN;
	global $schemes, $modes;
	global $links_fav;

	$first = $pagenumber*$perpage - $perpage;
	$last = $first + $perpage - 1;

	write_debug("Query: $query");
	write_debug("Highlight: '$sstring'");
	write_debug("Page, perpage: $pagenumber, $perpage");

	$asb = $DB_site->query($query);
	$thits = 0;

	$linklistbit = "";
	$linkstyle = 1;
	$nhits = 0;
	$thisid = -1;
	$linkcatlist = array();

	unset($icons);
	if ($links_defaults["file_icons_dir"]!="") {
		if ($handle = @opendir($links_defaults["file_icons_dir"])) {
		    while (false !== ($file = readdir($handle))) {
		        if (preg_match("/(.*?).gif/", $file, $matches)) {
		            $icons[$matches[1]] = $links_defaults["file_icons_dir"].$file;
		        }
		    }
		    closedir($handle);
		}
	}

	unset($thisorder);
	while ($myrow=$DB_site->fetch_array($asb)) {
		if ($myrow["linkid"] == $thisid) {
// continuation of previous link in another category
			if (isset($myrow["linkcatid2"]) and $myrow["linkcatid2"] != $myrow["linkcatid"] and !in_array($myrow["linkcatid2"], $linkcatlist)) {
				$linkcatlist[] = $myrow["linkcatid2"];
			}
			continue;
		}

		if ($thisid > 0) {
			if ($thits >= $first and $nhits <= $perpage-1) {
// flush buffer
				$linkothercatsbit = "";
				$linkshowothercatbit = 0;
				foreach ($linkcatlist as $linkothercat) {
					$linkothercatname = $linkscat[$linkothercat]["catname"];
					$linkshowothercatbit = 1;
					eval("\$linkothercatsbit .= \"".fetch_template('links_othercatsbit')."\";");
				}
				if ($modlinks != 0) {
					eval("\$linklistbit .= \"".fetch_template('links_modbit')."\";");
				} else {
					eval("\$linklistbit .= \"".fetch_template('links_linkbit')."\";");
					if (isset($thisorder) and $myrow["linkdorder"] != $thisorder) {
						eval("\$linklistbit .= \"".fetch_template('links_linkseparator')."\";");
					}
				}
				$linkstyle = iif($linkstyle==1,2,1);
				$nhits++;
			}

			$thits++;
			$thisid = -1;
			unset ($linkcatlist);
			$linkcatlist = array();

		}

		$linkid	= $myrow["linkid"];
		$thisid = $linkid;
		$thisorder = $myrow["linkdorder"];

		if ($thits > $last) continue;

		$linkcatid = $myrow["linkcatid"];

		if (isset($myrow["linkcatid2"]) and $myrow["linkcatid2"] != $myrow["linkcatid"]) {
			$linkcatlist[] = $myrow["linkcatid2"];
		}

		$linkname	= highlight(parse_bbcode2(trim($myrow["linkname"]), $links_defaults['allow_html'], $links_defaults['allow_images'], $links_defaults['allow_smilies'], $links_defaults['allow_bbcode']), $sstring);
		$linkdesc	= highlight(parse_bbcode2(trim($myrow["linkdesc"]), $links_defaults['allow_html'], $links_defaults['allow_images'], $links_defaults['allow_smilies'], $links_defaults['allow_bbcode']), $sstring);

		$linkurl	= $myrow["linkurl"];
		if ($linkurl) {
			$urlInfo	= parse_url($linkurl);
			$urlType	= substr(strrchr(basename($urlInfo['path']), "."), 1);
			if (isset($urlInfo['scheme'])) {
				$linkmode   = iif(isset($modes[$urlInfo['scheme']]), $modes[$urlInfo['scheme']], 2);
			} else {
				$linkmode = 1;
			}
			$linkmode	= max($linkmode, $links_defaults["force_redirect"]);
			$linktypebit = '';
			if (isset($icons[$urlType])) {
				$linktypebit = '<img border="0" src="'.$icons[$urlType].'" alt="'.$urlType.'" />&nbsp;';
			} elseif (isset($icons[$urlInfo['scheme']])) {
				$linktypebit = '<img border="0" src="'.$icons[$urlInfo['scheme']].'" alt="'.$urlInfo['scheme'].'" />&nbsp;';
			}
		} else {
			$linktypebit = '';
		}
		$linkhits	= $myrow["linkhits"];
		$linkstatus = $myrow["linkstatus"];
		if ($linkstatus > 1)  $linkstatus = intval (round($linkstatus / 1024));
		$linkdate	= vbdate($vboptions['dateformat'], $myrow["linkdate"]);
		$linkuserid = $myrow["linkuserid"];
		$linkusername = $myrow["linkusername"];
		$linkmoderate = $myrow["linkmoderate"];
		$linkcatname = $linkscat[$linkcatid]["catname"];
		$linknew = iif($bbuserinfo['lastvisit'] < $myrow['linkdate'],1,0);
		if (isset($links_totrate[$linkid])) {
			$linkrate = round($links_totrate[$linkid] / $links_numrate[$linkid]);
			eval("\$linkratebit = \"".fetch_template('links_ratebit')."\";");
		} else {
			$linkratebit = "";
			$linkrate = "";
		}
		$linkfav = iif(isset($links_fav[$linkid]),1,0);
	}

	if ($thisid > 0) {
		if ($thits >= $first and $nhits <= $perpage-1) {
// flush buffer
			$linkothercatsbit = "";
			$linkshowothercatbit = 0;
			foreach ($linkcatlist as $linkothercat) {
				$linkothercatname = $linkscat[$linkothercat]["catname"];
				$linkshowothercatbit = 1;
				eval("\$linkothercatsbit .= \"".fetch_template('links_othercatsbit')."\";");
			}
			if ($modlinks != 0) {
				eval("\$linklistbit .= \"".fetch_template('links_modbit')."\";");
			} else {
				eval("\$linklistbit .= \"".fetch_template('links_linkbit')."\";");
			}
		}
		$thits ++;
	}

	return array($linklistbit, $thits);
}

function insert_link ($username, $userid, $linkname, $linkurl, $linkdesc, $pcatid, $pforum, $statuscheck, $moderate, $linkreviewfreq, $allowduplicate=1) {
	global $DB_site;

// Insert new link. Routine assumes that error checking is complete.
// If allowduplicates=1, url can be inserted more than once, otherwise insertion
// simply adds the link to new categories where necessary

	$statustime = TIMENOW;
	$pcatidn = $pcatid;
	$insert = 1;
	$linkid = -1;

	if ($allowduplicate == 0) {
		$asb = $DB_site->query("
			SELECT linkid FROM ".THIS_TABLE."linkslink
			WHERE linkurl='$linkurl' LIMIT 1
			");
		if ($DB_site->num_rows($asb)>0) {
			$insert = 0;
			$myrow = $DB_site->fetch_array($asb);
			$linkid = $myrow["linkid"];
			$asb = $DB_site->query("
				SELECT catid FROM ".THIS_TABLE."linksltoc
				WHERE linkid=$linkid
				");
			while ($myrow=$DB_site->fetch_array($asb)) {
				$unset = array_search($myrow["catid"], $pcatidn);
				if ($unset !== FALSE) {
					unset($pcatidn[$unset]);
				}
			}
		}
	}

	if ($insert) {
		$query = "
			INSERT INTO ".THIS_TABLE."linkslink (linkname, linkurl, linkdesc, linkhits, linkforum, linkcheck, linkstatus, linkdate, linkusername, linkuserid, linkmoderate, linkreviewfreq)
			VALUES (
			'".addslashes($linkname)."',
			'".addslashes(str_replace('"', '&quot;', $linkurl))."',
			'".addslashes($linkdesc)."',
			0,
			'".intval($pforum)."',
			$statustime,
			'".intval($statuscheck)."',
			$statustime,
			'".addslashes(htmlspecialchars($username))."',
			'".intval($userid)."',
			'".intval($moderate)."',
			'".intval($linkreviewfreq)."'
			)
		";
		write_debug($query);
		$DB_site->query($query);
		$linkid = $DB_site->insert_id();
	}

	foreach ($pcatidn as $p) {
		$DB_site->query("
			INSERT INTO ".THIS_TABLE."linksltoc (linkid, catid)
			VALUES ('$linkid', '".intval($p)."')
		");
		$DB_site->query("
			UPDATE ".THIS_TABLE."linkscat
			SET catentry=catentry+1, catdate=".$statustime."
			WHERE catid='".intval($p)."'
			LIMIT 1
		");
	}

	return $linkid;
}

?>