config = array(); } function get_var($key) { if (!isset($this->config)) return null; $k = explode(".", $key); // split on dots return $this->do_get($this->config, $k, false); } function get_var_all($key) { if (!isset($this->config)) return null; $k = explode(".", $key); // split on dots return $this->do_get($this->config, $k, true); } function set_var($key, $value) { if (!isset($this->config)) // error recovery return FALSE; $k = explode(".", $key); // split on dots $this->config = $this->do_set($this->config, $k, $value); // do the set return TRUE; } function do_set($target, $path, $value) { if (count($path) <= 0) { // we've reached our destination return $value; // return the value } $element = array_shift($path); // get the next element if (!isset($target[$element])) $target[$element] = array(); $target[$element] = $this->do_set($target[$element], $path, $value); return $target; } function do_get($target, $path, $return_all) { if (count($path) <= 0) { // we've reached our destination $to_ret = $target; /* check if we want to return everything or just the first element */ if (is_array($target) && $return_all == false) $to_ret = array_shift($target); if ($return_all == true && (!is_array($target) || $this->associative($to_ret))) $to_ret = array($to_ret); return $to_ret; // return the value } $element = array_shift($path); // get the next element if (!isset($target[$element])) return null; return $this->do_get($target[$element], $path, $return_all); } /* here we want to detect whether this is a file config or otherwise */ function connect($file) { $new_config = FileResource::connect($file); return $new_config; } function associative($array) { foreach($array as $key => $value) { if (!is_int($key)) return TRUE; } return FALSE; } } class FileResource extends Resource { function FileResource($filename) { $this->{get_parent_class(__CLASS__)}(); $this->filename = $filename; } function connect($file) { /* get the file extension */ $ext = str_replace('.','',strstr($file, '.')); /* check if the file is an XML file */ if (strtolower($ext) == "xml") $config_obj = new XMLResource($file); /* otherwise use a plain text output */ // else // $new_config = new TextResource($file); return $config_obj; } function read_file() { $temp = file_get_contents($this->filename); if ($temp == FALSE) // file read error return $temp; $this->contents = $temp; return true; } function write_file() { $result = file_put_contents($this->filename, $this->contents); if ($result <= 0 && count($contents) > 0) // file write error return FALSE; return TRUE; // return to child class } function sync() { /* check to make sure we can sync */ // if (is_writeable($this->filename) == FALSE) { // return FALSE; // } /* make a serialization of this config */ $serial = $this->serialize(); if ($serial == FALSE) return FALSE; $old_contents = $this->contents; /* record old contents */ $this->contents = $serial; /* record this serialization */ $result = $this->write_file(); if ($result == FALSE) { // the write failed $this->contents = $old_contents; return FALSE; } return TRUE; } function is_synced() { /* make a serialization of this config */ $serial = $this->serialize(); /* grab the file contents */ $temp = file_get_contents($this->filename); if ($temp == $serial && $serial != FALSE) // if this didn't work out return TRUE; // success else // something went wrong return FALSE; } } class XMLResource extends FileResource { function serialize() { /* create the root config node */ $root = array(); $root['resource'] = $this->config; $mxml = new MiniXMLDoc(); $mxml->fromArray($root); return $mxml->toString(); } function XMLResource($filename) { $this->{get_parent_class(__CLASS__)}($filename); $this->initialize(); } function initialize() { /* we must be able to either read or write this file */ if (is_readable($this->filename) == FALSE && is_writeable($this->filename) == FALSE) { return FALSE; } /* if we can read the DOM */ if (is_readable($this->filename)) { $this->read_file(); // read its contents $this->config = $this->parse_xml($this->contents); } } function parse_xml($xml) { $mxml = new MiniXmlDoc(); $mxml->fromString($xml); $arr = $mxml->toArray(); return $arr['resource']; } } /* XXX Args.php XXX */ class Args { function get($name) { global $argv; global $argc; if (isset($_POST[$name])) { return $_POST[$name]; } else if (isset($_GET[$name])) { return $_GET[$name]; } else { for ($i = 1; $i < $argc; $i++) { $arg = $argv[$i]; $splitted = explode("=", $arg); if ($splitted[0] == $name && count($splitted) > 1) return $splitted[1]; } } return null; } } $config_file = "search-config.xml"; $start = Args::get("n"); $search_string = Args::get("s"); $search_database_index = Args::get("d"); require_once("minixml/minixml.inc.php"); if (!isset($start)) $start = 0; function template_cb($matches) { global $cur_page; return get_tag($cur_page, $matches[1]); } /* change this template to control result output */ function template($template, $page) { global $cur_page; $cur_page = $page; $template = preg_replace_callback("/%%%(.*?)%%%/is",'template_cb',$template); return $template; } function generate_count($search_words, $node) { $node = strtolower($node); foreach($search_words as $word) { $word = strtolower($word); $ret[$word] = substr_count(strtolower($node), strtolower($word)); } return $ret; } function total_count($count) { $total = 0; foreach ($count as $word => $a_word_count) { if ($a_word_count <= 0) return 0; $total += $a_word_count; } return $total; } function comp_results($aresult, $bresult) { $acount = $aresult["count"]; $bcount = $bresult["count"]; $apage = $aresult["page"]; $bpage = $bresult["page"]; if (total_count($acount) > total_count($bcount)) return -1; if (total_count($acount) < total_count($bcount)) return 1; if (total_count($acount) == total_count($bcount)) { if (get_tag($apage, "last-modified") > get_tag($bpage, "last-modified")) return -1; if (get_tag($apage, "last-modified") < get_tag($bpage, "last-modified")) return 1; else return 0; } } function get_tag($result, $tagname) { preg_match("&<$tagname>((?:(?!).)*)&is", $result, $matches); if (count($matches) > 1) return $matches[1]; else return ""; } function write_log_file($log_file, $log_file_size, $search_string) { /* if the log file isn't specified, don't write it */ if (!isset($log_file) || $log_file == "") return; /* if the size isn't set assume a big number */ if (!isset($log_file_size) || $log_file_size == "") $log_file_size = 30000; /* prepare to write the log file */ $log_array = array(); if (file_exists($log_file)) { // if one exists $log = file_get_contents($log_file); // read it in $log_array = split("\n", $log); // split on newlines if (count($log_array) > $log_file_size + 1) { // if it is too big array_unshift($log_array); // take off the leading tag array_unshift($log_array); // take off the first element array_shift($log_array, ""); // reinsert the leading tag } /* pop off the last bits of the file */ array_pop($log_array); array_pop($log_array); /* push the new query */ array_push($log_array, " " . $search_string . ""); /* push the final tag */ array_push($log_array, ""); } else { $log_array = array("", " " . $search_string . "", ""); } if (!$handle = fopen($log_file, "w")) { echo "Cannot open log file ($log_file)"; exit; } foreach ($log_array as $log_entry) { if (fwrite($handle, $log_entry . "\n") === FALSE) { echo "Cannot write to file ($log_file)"; exit; } } fclose($handle); } function get_search_database($index, $databases) { /* if the number is not valid, then search everything */ if ($index < 0 or $index > count($databases)) { $file = ""; /* load all files */ foreach ($databases as $fname) $file .= file_get_contents($fname); } else { /* decide which file to search from */ $fname = $databases[$index]; /* load the file */ $file = file_get_contents($fname); } return $file; } function get_matches($search, $to_search) { $results = array(); // prepare the results if ($search != "") { $words = explode(" ", $search); // break up search words $pages = explode("", $to_search); // split pages foreach($pages as $page) { $count = generate_count($words, $page); $total_count = total_count($count); if ($total_count > 0 && get_tag($page, "path") != "") { $results[] = array('count' => $count, 'page' => $page); } } } /* sort the results */ usort($results, 'comp_results'); return $results; } $config = Resource::connect($config_file); $per_page = $config->get_var("results_per_page"); $dbfiles = $config->get_var_all("files.file"); $frame_file = $config->get_var("frame_file"); $template = $config->get_var("result_template"); $log_file = $config->get_var("synced-files.file.path"); $log_size = $config->get_var("log_size"); $text = get_search_database($search_database_index, $dbfiles); $results = get_matches($search_string, $text); $no_result_string = $config->get_var("noresults_template"); $header = $config->get_var("header_template"); $next_string = $config->get_var("next_page_template"); $prev_string = $config->get_var("prev_page_template"); /* prepare the output */ $output = file_get_contents($frame_file); $oresults = ""; $total_results = count($results); $starting_result = $start + 1; $ending_result = min($total_results, $start + $per_page); /* print out results counts */ if ($total_results <= 0) $oresults .= $no_result_string; else $oresults .= $header; // $oresults .= "

Results $nstart-$end of $total_results

\n"; /* print each result */ for ($i = $start; $i < min(count($results), $start + $per_page); $i++) $oresults .= template($template, $results[$i]['page']); /* initialize the variables for next and prev links */ $prevstart = $start - $per_page; $nextstart = $start + $per_page; $to_go = min(count($results) - $nextstart, $per_page); $me = $_SERVER['PHP_SELF']; /* print next and previous links */ if ($start != 0) { $oresults .= "$prev_string "; } if ($to_go > 0) { $oresults .= "$next_string"; } $output = str_replace('{$SEARCH}', $oresults, $output); $output = str_replace('{$QUERY}', $search_string, $output); $output = str_replace('{$START_RESULT}', $starting_result, $output); $output = str_replace('{$END_RESULT}', $ending_result, $output); $output = str_replace('{$TOTAL_RESULTS}', $total_results, $output); $output = str_replace('{$PER_PAGE}', $per_page, $output); $output = str_replace('{$RESULTS_ON_NEXT_PAGE}', $to_go, $output); print $output; if (isset($log_file)) write_log_file($log_file, $log_size, $search_string); ?>