<?

/*
** DGS Search
** $Id: dgsindex.php,v 1.2 2006/01/24 07:08:09 sella Exp $
** Copyright (c) 2000-2001 Digital Genesis Software, LLC. All Rights Reserved.
** Released under the GPL Version 2 License.
** http://www.digitalgenesis.com
*/

function getQuickIndexOffset(&$offset, &$handle, $keyword) {
	//Put our cursor in a known location.
	if (fseek($handle, 0) == -1)
		return false;

	$tmp = unpack('LquickEnd/LpairCount', fread($handle, 8));

	$quickEnd = $tmp['quickEnd'];
	$pairCount = $tmp['pairCount'];
	$indexSize = ((($quickEnd - 12) / $pairCount ) - 4);

	if ($indexSize < 0)
		return false;

	$indexStr = "";
	$offset = "";

	$lastOffset = 0;
	for($i = 0; $i < $pairCount; $i++) {
		$indexSize = 4;
		$formatStr = sprintf("a%dword/Loffset", $indexSize);
		$tmp = unpack($formatStr, fread($handle, $indexSize + 4));
		$indexStr = $tmp['word'];
		$offset = $tmp['offset'];

		if (strlen($indexStr) < 1)
			return false;
		//If we go past, then we know the last one was right.
		if (strcasecmp($indexStr, $keyword) > 0) {
			break;
		}
		$lastOffset = $offset;
	}

	$offset = $lastOffset;

	return true;
}

function getKeywordOffset(&$offset, &$handle, $keyword) {
	if (!getFilenameOffset($filenameOffset, $handle))
		return false;

	if (!getQuickIndexOffset($offset, $handle, $keyword))
		return false;

	//Jump close to our keyword
	if (fseek($handle, $offset) == -1)
		return false;

	$nextOffset = 0;
	do {
		if (!getKeywordAtOffset($buffer, $handle, $offset))
			return false;

 		$compare = strcasecmp($keyword, $buffer);
		if (!$compare)	
			return true;

		if (!getNextOffset($nextOffset, $handle, $offset))
			return false;

		$offset += $nextOffset;
	} while ($offset < $filenameOffset && $compare < 0);

	return false;
}

function getNextOffset(&$retOffset, &$handle, $offset) {
	//Put our cursor to the keyword.
	if (fseek($handle, $offset) == -1)
		return false;
	if (feof($handle))
		return false;
	
	$tmp = unpack('LkeywordEnd', fread($handle, 4));
	$retOffset = $tmp['keywordEnd'];

	if ($retOffset != 0)
		return true;
	else
		return false;
}

function getKeywordAtOffset(&$keyword, &$handle, $offset) {
	//Put our cursor to the keyword.
	if (fseek($handle, $offset) == -1)
		return false;
	
	$tmp = unpack('LkeywordEnd/LfilenameCount/LkeywordTotal', fread($handle, 12));
	$keywordLen = $tmp['keywordEnd'] - (($tmp['filenameCount'] * 8) + 12);

	$formatStr = sprintf('a%dkeyword', $keywordLen);
	$tmp = unpack($formatStr, fread($handle, $keywordLen));

	if (strlen($tmp['keyword']) < 1)
		return false;

	$keyword = $tmp['keyword'];

	return true;
}

function getKeywordTotal(&$total, &$handle, $keyword) {
	if (!getKeywordOffset($offset, $handle, $keyword))
		return false;

	//Put our cursor to the keyword.
	if (fseek($handle, $offset) == -1)
		return false;

	$tmp = unpack('LkeywordEnd/LfilenameCount/LkeywordTotal', fread($handle, 12));
	$total = $tmp['keywordTotal'];

	if ($total < 1)
		return false;

	return true;
}

function getKeywordFilenameCount(&$count, &$handle, $keyword) {
	if (!getKeywordOffset($offset, $handle, $keyword))
		return false;

	//Put our cursor to the keyword.
	if (fseek($handle, $offset) == -1)
		return false;

	$tmp = unpack('LkeywordEnd/LfilenameCount', fread($handle, 8));
	$count = $tmp['filenameCount'];

	if ($count < 1)
		return false;

	return true;
}

function getFilenameOffset(&$offset, &$handle) {
	//Put our cursor in a known location.
	fseek($handle, 0);

	$tmp = unpack('LquickEnd', fread($handle, 8));
	fseek($handle, $tmp['quickEnd'] - 4);

	$tmp = unpack('LfileOffset', fread($handle, 4));
	$offset = $tmp['fileOffset'];

	return true;
}

function getKeywordFilenameCountArray(&$filenameCount, &$handle, $keyword) {
	$filenameCount = array();

	if (!getKeywordOffset($offset, $handle, $keyword))
		return false;

	if (!getKeywordFilenameCount($count, $handle, $keyword))
		return false;

	//Jump to the first pair.
	if (fseek($handle, $offset + strlen($keyword) + 13) == -1)
		return false;

	for($i = 0; $i < $count; $i++) {
		$tmp = unpack('LfilenameSeek/LfilenameCount', fread($handle, 8));

		$filenameCount[$tmp['filenameSeek']] = $tmp['filenameCount'];
	}

	return true;
}

function getFilename(&$filename, &$handle, $offset) {
	if (!getFilenameOffset($filenameOffset, $handle))
		return false;

	//Jump to Filename List
	if (fseek($handle, $filenameOffset) == -1)
		return false;

	//Seek to wanted filename
	if (fseek($handle, $filenameOffset + $offset) == -1)
		return false;

	$tmp = unpack('LfilenameEnd', fread($handle, 4));
	$filenameEnd = $tmp['filenameEnd'];

	$formatStr = sprintf('a%dfilename', $filenameEnd);
	$tmp = unpack($formatStr, fread($handle, $filenameEnd));
	$filename = $tmp['filename'];

	//Make sure we have something to return.
	if (strlen($filename) < 1)
		return false;

	return true;
}

function requestIndexingLock() {
   global $config;
 
	$lockTTL	= $config['lockTTL'];
   $indexingLock = $config['indexDir'] . $config['fileSeparator'] . 'dgssearch.lock';
   $debug = $config['debug'];
   $warn = $config['warn'];

	if ($debug)
		printf(">Debug: requestIndexingLock()<BR>\n");

	clearstatcache(); //We want new info fro fileXtime() functions.

	if (file_exists($indexingLock)) {
		if ((time() - filectime($indexingLock)) <= $lockTTL || (time() - filemtime($indexingLock)) <= $lockTTL) {
			if ($debug)
				printf(">Debug: requestIndexingLock() - Skipping Indexing. Already a fresh indexing lock file.<BR>\n");

			return false;
		}
		if ($debug)
			printf(">Debug: requestIndexingLock() - Releasing stale indexing lock file.<BR>\n");
		releaseIndexingLock();
	}

	if ($debug)
		printf(">Debug: requestIndexingLock() - Attempting to lock for this process.<BR>\n");

	return touch($indexingLock);
}

function refreshIndexingLock() {
	global $config;

   $indexingLock = $config['indexDir'] . $config['fileSeparator'] . 'dgssearch.lock';

	if (!file_exists($indexingLock))
		return false;

	return touch($indexingLock);
}

function releaseIndexingLock() {
   global $config;
 
   $indexingLock = $config['indexDir'] . $config['fileSeparator'] . 'dgssearch.lock';

	if (!file_exists($indexingLock))
		return false;

	unlink($indexingLock);
	return true;
}

function displayIndexFile($filename) {
	printf("<CENTER>\n");	
	printf("<FONT SIZE=\"+1\"> <STRONG> Quick Index </STRONG> </FONT>\n");
	printf("<TABLE>\n");

	if (!($fp = @fopen($filename, 'r'))) {
		printf("No Index!<BR>");
		return false;
	}
	$buffer = unpack('Loffset/Lcount', fread($fp, 8));

	$quickIndex['wordOffset'] = $buffer['offset'];
	$quickIndex['keywordCount'] = $buffer['count'];
	$quickIndex['keywordSize'] = 4; // Will have to calculate at some point

	printf("<TR BGCOLOR=\"eaeaea\">\n");
	printf("<TD> [ File_Offset ] </TD>\n");
	printf("<TD> [ Word_Offset ] </TD>\n");
	printf("<TD> [ Word_Count ] </TD>\n");

	for ($i = 0; $i < $quickIndex['keywordCount']; $i++) {
		printf("<TD> [ Word </TD>\n");
		printf("<TD> Offset ] </TD>\n");
	}
	
	printf("<TD> [ Filename_Offset ] </TD>\n");
	printf("</TR>\n");
	printf("<TR BGCOLOR=\"eeeeee\">\n");
	printf("<TD> %08x </TD>", 0);
	printf("<TD> %08x </TD>", $quickIndex['wordOffset']);
	printf("<TD> %08x </TD>", $quickIndex['keywordCount']);

	$format = sprintf("a%dword/Loffset", $quickIndex['keywordSize']);
	for ($i = 0; $i < $quickIndex['keywordCount']; $i++) {
		$buffer = unpack($format, fread($fp, $quickIndex['keywordSize'] + 4));

		printf("<TD> %s </TD>", strtoupper($buffer['word']));
		printf("<TD> %08x </TD>", $buffer['offset']);
	}
	$buffer = unpack('Loffset', fread($fp, 4));
	$quickIndex['fileOffset'] = $buffer['offset'];

	printf("<TD> %08x </TD>", $quickIndex['fileOffset']);

	printf("</TR>\n");
	printf("</TABLE>\n");

	flush();

	printf("<FONT SIZE=\"+1\"> <STRONG> Word Index </STRONG> </FONT>\n");
	printf("<TABLE>\n");
	printf("<TR BGCOLOR=\"eaeaea\">\n");
	printf("<TD> [ File_Offset ] </TD>\n");
	printf("<TD> [ Next_Offset ] </TD>\n");
	printf("<TD> [ File_Count ] </TD>\n");
	printf("<TD> [ Total_Occurances ] </TD>\n");
	printf("<TD> [ Word ] </TD>\n");
	printf("<TD> [ File_Offset ] </TD>\n");
	printf("<TD> [ File_Occurances ] </TD>\n");
	printf("</TR>\n");

	while (ftell($fp) < $quickIndex['fileOffset']) {
		printf("<TR>\n");
		printf("<TD> %08x </TD>\n", ftell($fp));

		$buffer = unpack('Lnext/Lfiles/Ltotal', fread($fp, 12));

		printf("<TD> %08x </TD>\n", $buffer['next']);
		printf("<TD> %08x </TD>\n", $buffer['files']);
		printf("<TD> %08x </TD>\n", $buffer['total']);


		$fileCount = $buffer['files'];
		$format = sprintf("a%dword/Loffset/Loccurances", $buffer['next'] - ($buffer['files'] * 8) - 12);
		$buffer = unpack($format, fread($fp, $buffer['next'] - ($buffer['files'] * 8) - 12 + 8));

		printf("<TD> %s </TD>\n", strtoupper($buffer['word']));
		printf("<TD> %08x </TD>\n", $buffer['offset']);
		printf("<TD> %08x </TD>\n", $buffer['occurances']);
		printf("</TR>\n");

		for ($i = 0; $i < ($fileCount - 1); $i++) {
			$buffer = unpack('Loffset/Loccurances', fread($fp, 8));
			printf("<TR>\n<TD COLSPAN=\"5\"> &nbsp </TD>\n<TD> %08x </TD>\n<TD> %08x </TD>\n</TR>\n", $buffer['offset'], $buffer['occurances']);
		}
	}
	printf("</TABLE>\n");
	flush();

	printf("<FONT SIZE=\"+1\"> <STRONG> Word Index </STRONG> </FONT>\n");
	printf("<TABLE>\n");

	$offsetTotal = $quickIndex['fileOffset'];
	while (!feof($fp)) {
		printf("<TR BGCOLOR=\"eaeaea\">\n");

		$buffer = unpack('Loffset', fread($fp, 4));
		$offset = $buffer['offset'];
		$offsetTotal += $offset;

		$format = sprintf("a%dfilename", $offsetTotal - ftell($fp));
		$buffer = unpack($format, fread($fp, $offsetTotal - ftell($fp)));

		printf("<TD> %08x </TD> <TD> %s </TD>", $offset, $buffer['filename']);
		printf("</TR>\n");
	}
	printf("</TABLE>\n");
	fclose($fp);
}

/*
** Local Variables:
** c-basic-offset: 3
** tab-width: 3
** End:
** vim:
** vim: noet ts=3 sw=3
*/

?>
