<?php

/*
** DGS Search
** $Id: fs.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 fs($retVal, $sq, $timer) {
	global $config;

	$debug = $config['debug'];
	$warn = $config['warn'];
	$matchCount = count($retVal);

	if ($debug)
		printf("->Debug: fs() [Module]<BR>\n");

	if ($sq['s'] > 0 && $matchCount >= $sq['r'] + $sq['o']) //If we know the size already and have enough matches, return.
		return $retVal;

	$result = array();
	if ($config['indexTTL'] > 0) {
		if (createIndex()) //This will become a register_shutdown_function() later.
			echo "TRUE from createIndex()<BR>\n";
		else
			echo "FALSE from createIndex()<BR>\n";

//		displayIndexFile($config['indexFile']);
		$result = searchIndex($retVal, $sq, $timer);
//		$result = 0;
	}

	if ($debug && !is_array($result))
		printf("->Debug: fs() - searchIndex() returned in failure. Will attempt searchFilesystem().<BR>\n");

	if ($config['indexTTL'] < 1 || !is_array($result)) {
		$result = searchFilesystem($retVal, $sq, $timer);
	}

	if (is_array($result)) {
		$retVal = $result;
	} else if ($debug) {
		printf("->Debug: fs() - Search functions returned in failure. Values discarded.<BR>\n");
	}

	if ($debug) { //Time taken to locate all files.
		printf("->Debug: fs() - Module Search Time: %.1f sec<BR>\n", getTime() - $tm);
		flush();
	}

	return $retVal;
}

function searchIndex($retVal, $sq, $timer) {
	global $config;

	$debug = $config['debug'];
	$warn = $config['warn'];
	$tm = getTime();

	if (file_exists($config['indexFile'])) {
		$handle = fopen($config['indexFile'], 'r');
		if ($handle == false) {
			if ($debug)
				printf("> Debug: searchIndex() - Failed to open index file. Check permissions.<BR>\n");
			return false;
		}
	} else {
		if ($debug)
			printf("> Debug: searchIndex() - Index file not available.<BR>\n");
		return false;
	}

	//Loop collecting up all matches needed for boolean - Both pos and neg booleans
	$match = array();
	$match['not'] = array();
	$match['or'] = array();

	while(list($i, $query) = each($sq['q']['not'])) {
		getKeywordFilenameCountArray($match['not'][$query], $handle, $query);
	}

	while(list($i, $orArray) = each($sq['q']['or'])) {
		while(list($j, $query) = each($sq['q']['or'][$i])) {
			getKeywordFilenameCountArray($match['or'][$i][$query], $handle, $query);
		}
	}

//	$match['or'][0]['configuration'] = array(1 => 2);
//	$match['or'][1]['filesystem'] = array(2 => 20);
//	$match['or'][1]['is'] = array(2 => 45);
//	$match['or'][1]['is'][4] = 99;
//	$match['or'][1]['configuration'][2] = 10;
//	$match['or'][1]['configuration'][3] = 2;

	print_r($match);

	//Exclude matches that hit neg matches.
	reset($match['or']);
	while(list($i, $orArray) = each($match['or'])) {
		while(list($keyword, $matchSet) = each($orArray)) {
			if (count($matchSet) > 0) {
				//Check each match set against negs.. remove if match.
				while(list($fileIdx, $fileCount) = each($matchSet)) {
					reset($match['not']);
					while(list($notKeyword, $notSet) = each($match['not'])) {
						if ($notSet[$notKeyword] == $fileIdx) {
							unset($match['or'][$i][$keyword][$fileIdx]);
						}
					}
				}
			}
		}
	}

	echo "<BR>\n<B>Match: ";
	print_r($match);
	echo "</B><BR>\n";

	//Cleanup (This still needs to merge results within an and block into just valid matches (ie: only keep the ones where the filename index is the same for all matches, removing othres)
	reset($match['or']);
	while(list($i, $orArray) = each($match['or'])) {
		while(list($keyword, $matchSet) = each($orArray)) {
			printf("Count: %d<BR>", count($matchSet));
			if (count($matchSet) < 1) {
				printf("Unsetting $i<BR>\n");
				//If one of the keywords has no matches, then the whole 'and' set is a worthless.
				unset($match['or'][$i]);
				continue;
			}
		}
		//Do funky merge here, since empty sets are removed now... or maybe we can do this before the empty remove.
	}

	printf("Cleaned up<BR>\n");
	print_r($match);

	//Build a sorted match set.

	//Collect File names for needed matches.
	
	//Collect link, url, desc, fileSize, etc for our matches.

	//Add to our result set.
	$retVal[] = array('link' => $title, 'url' => $urlBase . $endPath, 'description' => $desc, 'fileSize' => filesize($finalFile), 'source' => 'fs');

	return $retVal;
}

function searchFilesystem($retVal, $sq, $timer) {
	global $config;

	$s = $sq['s'];
	$r = $sq['r'];
	$o = $sq['o'];
	$lowQ = strtolower($sq['origQ']);
	$qSize = strlen($lowQ);
	$metaDesc = $config['metaDesc'];
	$descWidth = ($config['descWidth'] > 0) ? $config['descWidth'] : $qSize;
	$descWindow = $descWidth / 2;
	$descHeight = $config['descHeight'];
	$maxFileSize = $config['maxFileSize'];
	$maxSearchTime = $config['maxSearchTime'];
	$urlBase = $config['urlBase'];
	$fsBase = $config['fsBase'];
	$siteBase = $config['siteBase'];
	$frameSet = $config['frameSet'];
	$dateFormat = $config['dateFormat'];
	$docExts = $config['docExts'];
	$extSeparator = $config['extSeparator'];
	$boldQuery = $config['boldQuery'];
	$descEnd = $config['descEnd'];
	$debug = $config['debug'];
	$warn = $config['warn'];
	$matchCount = count($retVal);
	$tm = getTime();

	$files = findext($fsBase, $config['exts']);

	/* Locate Matching Files and Inject into retVal. */
	/* NOTE: This loop a large portion of the programs execution time. More optimization is needed. */
	$lastDoc = '';
	reset($files);
	while(list(, $file) = each($files)) {
		if (getTime() - $timer > $maxSearchTime) {
			if ($debug)
				printf("->Debug: fs() - <B>Exceeded Max Search Time of %.1f secs. Currently %.1f secs. - Exiting fs module early.</B><BR>\n", $maxSearchTime, getTime() - $timer);
			break;
		}

		if ($debug)
			printf('->Debug: fs() - Searching: %s', $file);

		if (!is_readable($file) || filesize($file) > $maxFileSize) {
			if ($debug)
				printf(" <B>[Skipping (%dk > %dk)]</B><BR>\n", filesize($file) / 1024, $maxFileSize / 1024);
			continue;
		}

		if ($warn) {
			$content = file($file); //Without @ will show SAFE MODE warnings.
		} else {
			$content = @file($file); //Hide warnings.
		}

		if (!is_array($content)) {
			if ($debug)
				printf(" <B>[Skipping (Failed Read)]</B><BR>\n", $file);
			continue;
		}

		$content = implode(' ', $content);

		if (stristr(strip_tags($content), $lowQ) == false) { /* Scan for matches. */
			if ($debug)
				printf("<BR>\n");
			continue;
		} else if ($debug) {
			printf(" <B>[Match]</B><BR>\n", $file);
		}

		$matchCount++;

		if ($matchCount >= $o && $matchCount <= $r + $o) { //We only need the desc for those we will display.
			if ($metaDesc) {
				/* The windowing needs more work. This is hack. */
				$buffer = getMetaDesc($content);
				if (strlen($buffer) > 0) {
					$desc[0] = substr($buffer, 0, $descWidth);
					if ($boldQuery)
						$desc[0] = boldQuery($desc[0], $lowQ);
					if (strlen($content) > $descWidth) {
						$desc[0] .= $descEnd;
					}
				}
			}
			if (!isset($desc)) {
				$desc = processWindow($content, $descWidth, $descHeight, $sq['origQ'], $matchCount);
			}
		}

		/* Start - Frame Set Patch */
		if ($frameSet) {
				/* Check xy-1.html -> xy.html scheme. */
				$frameFile = eregi_replace('-[0-9]+(\.s?html?)$', '\\1', $file);
				if (($frameFile != $file) && file_exists($frameFile)) {
						if ($debug)
								printf("->Debug: fs() - Found: %s for %s [Frame Set Scheme 1]<BR>\n", $frameFile, $file);
						$file = $frameFile;
				}
				/* Check xy/1.html -> xy/xy.html scheme. */
				$frameFile = eregi_replace('([^\\/]+)([\\/])[0-9]+(\.s?html?)$', '\\1\\2\\1\\3', $file);
				if (($frameFile != $file) && file_exists($frameFile)) {
						if ($debug)
								printf("->Debug: fs() - Found: %s for %s [Frame Set Scheme 2]<BR>\n", $frameFile, $file);
						$file = $frameFile;
				}
				if ($file == $lastDoc) { /* Frame was shown before */
						continue;
				} else {
						$lastDoc = $file;
				}
		}
		/* End - Frame Set Patch */

		/* Start - Document Extension Patch */
		$title = getTitle($file);
		if (is_array($docExts)) {
			$fileExt = ereg_replace(sprintf('^.*\\%s([^\\%s]+$)', $extSeparator, $extSeparator), '\\1', basename($file));
			reset($docExts);
			while (list(, $ext) = each($docExts)) {
				$finalFile = ereg_replace($fileExt, $ext, $file);
				if (file_exists($finalFile) && is_readable($finalFile)) {
					if ($debug)
						printf("->Debug: fs() - Found: %s for %s<BR>\n", basename($finalFile), $file);
					$title = ereg_replace($fileExt, $ext, $title);
					break;
				}
				$finalFile = $file;
			}
		} else {
			$finalFile = $file;
		}

		$endPath = explode($siteBase, $finalFile);
		$endPath = str_replace('\\', '/', $endPath[1]);
	       
		if (filemtime($finalFile) > 0) {
			if (!isset($desc)) {
				$desc = '';
			}
			$retVal[] = array('link' => $title, 'url' => $urlBase . $endPath, 'description' => $desc, 'fileSize' => filesize($finalFile), 'lastMod' => date($dateFormat, filemtime($finalFile)), 'source' => 'fs');
		} else {
			$retVal[] = array('link' => $title, 'url' => $urlBase . $endPath, 'description' => $desc, 'fileSize' => filesize($finalFile), 'source' => 'fs');
		}
		/* End - Document Extension Patch */

		if ($s > 0 && $matchCount > $r + $o) //If we know the size already and have enough matches, break.
			break;
		unset($desc); //Start with a clean slate.
	}

	return $retVal;
}

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

?>
