Browse Source

[svn r13377] Added search plugin to default Dokeos package. This is an attempt at integrating the search plugin better and make it available to all, although it requires a server-side installation. Might be removed in the future if proves inappropriate.

Yannick Warnier 17 years ago
parent
commit
5d4f981247

+ 138 - 0
plugin/search/README.txt

@@ -0,0 +1,138 @@
+Dokeos Search Plugin Installation Guide
+=======================================
+
+1. Introduction
+---------------
+This search plugin is composed of everything you need to get up and
+running with a full-text search feature on your Dokeos portal. However,
+this installation is not easy, and if you are not familiar with the
+term "indexing", or with the configuration of a Linux server, we
+highly recommend you seek advice from a qualified system administrator
+to help you doing this. Of course, the Dokeos company, for which I am
+directly working, offers this kind of services. Feel free to contact
+info@dokeos.com for a quote.
+
+This search plugin relies on a search server, called MnogoSearch, which 
+has to be installed independently on a Linux server (the Windows 
+version, sadly, is not GPL nor free to use).
+The following installation guides you through the steps of installing
+the server on a Debian or Ubuntu computer, but you might probably
+succeed in installing it on other architectures.
+
+Dokeos has made considerable efforts to have MnogoSearch integrated
+into the latest versions of PHP, but it would never have succeeded
+without the help of pierre.php@gmail.com who did all the technical 
+work.
+
+2. Installing files
+--------------------
+All the "conf" files and the "search.xml.php" file in this package
+need to be revised to configure properly. Most of all, you should look
+for a "DBAddr  mysql://db_user:db_pass@db_host/db_name/?dbmode=single"
+line in the server files to make sure it is using the correct database
+credentials.
+
+Now you will see that there are two directories in this plugin.
+The "client" directory needs to stay there. The "client/www" directory
+contains a PHP script that needs to be copied at the root of your
+Dokeos portal (this will later give the indexing server an access to 
+your Dokeos portal).
+
+The "server" directory has to be moved on the indexing server (which
+might be the same as your Dokeos portal's server if it is not too
+overloaded).
+
+This "server" directory contains three subdirectories.
+The "server/etc" directory contains the configuration of the
+mnogosearch server, which typically on Debian will be located in
+/etc/mnogosearch. Once you have installed the mnogosearch server, 
+you can pretty much overwrite the configuration with the files 
+contained in "server/etc", as they are already customised for indexing
+Dokeos.
+
+The "server/cron.d" directory contains an optional file that you might 
+want to put in /etc/cron.d, so that the indexing will be run every night
+5.00am.
+
+The "server/www" directory contains files that should be made available
+to the public, to access idexation results. Feel free to put these, for
+example, in /var/www/mnogosearch on your indexing server if that's where
+Apache takes its public files.
+
+3. Installing the search server (MnoGoSearch)
+---------------------------------------------
+The mnogosearch server installation comes in two parts:
+A) installing the mnogosearch indexing server itself. This can be done
+with a simple:
+  sudo apt-get install mnogosearch-common mnogosearch-mysql
+B) installing the PHP5-mnogosearch bindings. This can be done by using
+the PECL command-line installer
+  sudo pecl install mnogosearch-1.0.0
+
+Once the server is installed, you may need to install server specific
+additional programs to allow your indexer to go into documents (PDF,
+Word, Excel, etc) and index the contents of these documents as well.
+
+You can find a list of programs supposed to be there in the 
+server/etc/indexer.conf file. Search for "pdftotext" and you will find
+the lines nearby all define a program used to translate a document
+into pure text before indexing it. Make sure you are able to launch
+all of these commands on the command line. If you can't, the indexing
+server is not likely to be able to do it either...
+
+4. Creating the DB and Dokeos user
+----------------------------------
+In order to keep the index data, mnogosearch requires a database to
+store this data. It is recommended to create an alternative user, with
+access to only one database to do this.
+
+Once this user is configured and the DBAddr line is configured in 
+server/etc/indexer.conf, you can create the database structure by 
+calling (on the indexing server):
+ indexer -Ecreate indexer.conf
+
+The next step is to create a Dokeos user for the purpose of indexing 
+your courses (the user needs access to all courses to be able to index
+them). Create a simple user in the Dokeos administration interface. Then
+get his ID (you can get it by hovering the edition icon in the users 
+list: the user id is the number that shows after "user_id" in the URL)
+and use it inside indexer_login.php to replace the 'xxx' value.
+
+Also configure the IP address and the host name of the indexing server
+inside this file.
+
+Once these two steps are complete, you can start the first indexation
+of your portal, by calling, on the command line of your indexing server:
+  indexer -N10 index.conf
+N10 lets you limit the number of simultaneous threads that your indexing
+server will be allowed to use. More than 10 might put your Dokeos portal
+in overload. You might want to reduce this number to 3 for light servers.
+
+5. Installing the plugin
+------------------------
+Installing the plugin is done by dispatching the files contained in 
+this plugin as described in "2. Installing files", and configuring the
+various *.conf.php files as well as server/etc/indexer.conf and 
+server/www/search.xml.php
+
+Once the files have been moved and configured, you will still need to 
+index some data, then activate the plugin inside the Dokeos
+administration panel. Then, basically, you should be able to use
+the plugin straight away.
+
+6. International use
+--------------------
+To keep this plugin small, we had to remove a considerable amount of
+international-parsing helper files. If you need one for your language,
+it may well be included in the default installation file for the
+Debian mnogosearch-common package.
+
+If not, you should check more recent versions of mnogosearch on its
+website: http://www.mnogosearch.org/
+
+7. Seek help
+------------
+Commercial suppport is available for the configuration and remote use
+of this plugin at info@dokeos.com
+If you have plenty of time to learn it by yourself or any other reason,
+you might find some free help on our forums: http://www.dokeos.com/forum

+ 28 - 0
plugin/search/client/client.conf.php

@@ -0,0 +1,28 @@
+<?php //$id: $
+/**
+ * This script defines variables in use in the search plugin for this particular host in the client scripts
+ * @package dokeos.search
+ * @author Yannick Warnier <yannick.warnier@dokeos.com>
+ */
+/**
+ * Variables
+ */
+//// Addressing variables
+// $search_url is the relative URL from the HTTP root of this portal, to the
+// 'searchit.php' script. Something like /plugin/search/client/searchit.php
+$search_url = '/plugin/search/client/searchit.php';
+// $server_url is the URL of the server containing the search engine XML
+// interface (the contents of the server/www directory in this plugin package)
+// and, more precisely, the absolute web path to the search.php script
+$server_url = 'http://your.domain.com/subdir/search/search.php';
+
+//// Language variables
+// The name to be displayed on the 'Search' button
+$lang_search_button = 'Search';
+// The text to be suffixed to the number of search results found
+$lang_search_found = 'r&eacute;sultats trouv&eacute;s.';
+// The text to be suffixed to the number of seconds the search took
+$lang_seconds = 'secondes';
+// the text to be shown if no results were found
+$lang_no_result_found = 'La recherche n\'a pas renvoy&eacute; de r&eacute;sultat.';
+?>

+ 105 - 0
plugin/search/client/filter_user.lib.php

@@ -0,0 +1,105 @@
+<?php //$id:$
+/**
+ * This script declares a set of functions that will enable authorization check
+ * for a user's access to a course directory, as well as course name
+ * translations for search results display.
+ * @package dokeos.search
+ * @author Yannick Warnier <yannick.warnier@dokeos.com>
+ * @uses The Dokeos database library, to access the tables using its facilities
+ * @uses The Dokeos main api library to execute database queries
+ */
+/**
+ * Checks if a user can access a given course
+ * 
+ * The function gets the course code from the course directory, then
+ * checks in the course_user table if the user has access to that course.
+ * @param integer User ID (inside Dokeos)
+ * @param string  Course directory
+ * @return boolean True if user has access, false otherwise
+ */
+function get_boolean_user_access_to_course_dir($user_id,$course_dir){
+  if(api_is_platform_admin()){return true;}
+  $course_user = Database::get_main_table(TABLE_MAIN_COURSE);
+  $course      = Database::get_main_table(TABLE_MAIN_COURSE);
+  //Get the course code
+  $sql = "SELECT code FROM $course WHERE directory = '$course_dir'";
+  $res = api_sql_query($sql);
+  if(Database::num_rows($res)>0){
+    //Course found. Get the course code.
+    $row = Database::fetch_array($res);
+    $course_code = $row['code'];
+    //Check user permissions
+    $sql = "SELECT * FROM $course_user 
+    	WHERE course_code = '$course_code' 
+	AND user_id = '$user_id'";
+    $res = api_sql_query($sql);
+    if(Database::num_rows($res)>0){
+      //User permission found, go further and check there is a status
+      $row = Database::fetch_array($res);
+      $rel = $row['status'];
+      //if(!empty($rel)){
+        //Status found (we may later check this further to refine permissions)
+		//Sometimes for now it appears that the status can be 0, though.
+      	return true;
+      //}
+      //Status not found, problem, return false.
+      //return false;
+    }else{
+      //No course-user relation found, return false
+      return false;
+    }
+  }else{
+    //No course found, return false
+    return false;
+  }
+}
+/**
+ * Check course URL to get a course code and check it against user permissions
+ *
+ * Make this function always return true when no check is to be done
+ * @param	string	URL to check
+ * @return	boolean	True on user having access to the course or course not found, false otherwise
+ 
+ */
+function access_check($url,$default=true){
+  $matches = array(); 
+  $match1 = preg_match('/courses\/([^\/]*)\//',$url,$matches);
+  if(!$match1){
+    $match2 = preg_match('/cidReq=([^&]*)/',$url,$matches); 
+  }
+  if($match1 or $match2){
+    $has_access = get_boolean_user_access_to_course_dir($_SESSION['_user']['user_id'],$matches[1]);
+    if(!$has_access){
+      //user has no access to this course, skip it
+      return false;
+    }//else grant access
+    else
+    {
+      return true;
+    }
+  }
+  return $default;
+}
+/**
+ * Translates a course code into a course name into a string
+ * 
+ * This function should only be used if needed by a funny course-name rule
+ * @param	string	The string to transform
+ * @result	string	The transformed string
+ */
+function subst_course_code($string){
+  $matches = array();
+  if(preg_match('/(PORTAL_[0-9]{1,4})/',$string,$matches)){
+    $course      = Database::get_main_table(TABLE_MAIN_COURSE);
+    //Get the course code
+    $sql = "SELECT title FROM $course WHERE code = '".$matches[1]."'";
+    $res = api_sql_query($sql);
+    if(Database::num_rows($res)>0){
+      $row = Database::fetch_array($res);
+      $string = preg_replace('/(.*)\?cidReq=('.$matches[1].')(.*)/',' '.$row['title'].' - \1 \3',$string);
+      $string = preg_replace('/'.$matches[1].'/',$row['title'],$string);
+    }
+  }
+  return $string;
+}
+?>

+ 27 - 0
plugin/search/client/search.css

@@ -0,0 +1,27 @@
+.search_info{
+	background-color: #F0F0F0;
+	font-style: smaller;
+	padding: 5px;
+}
+.result{
+	/*border: 1px dotted black;*/
+	margin: 20px;
+	padding: 10px;
+}
+.result .title{
+	font-size: bigger;
+	margin-top: -20px;
+	background-color: white;
+	margin-right: 100px;
+	margin-left: -10px;
+	margin-bottom: 5px;
+}
+.result .description{
+	font-decoration: none;
+	width: 90%;
+}
+.result .highlight{
+	display: inline;
+	background-color: lightblue;
+	margin-right: 2px;
+}

+ 99 - 0
plugin/search/client/searchit.php

@@ -0,0 +1,99 @@
+<?php //$id: $
+/**
+ * This script is the main client script. It calls the search server to get an XML document that
+ * represents the list of results to the term searched.
+ * It parses the XML document, checks user permissions and displays a set of results in a nice
+ * format.
+ * @package dokeos.search
+ * @author Yannick Warnier <yannick.warnier@dokeos.com>
+ */
+/**
+ * Variables
+ */
+require_once('../../../main/inc/global.inc.php');
+require ('filter_user.lib.php');
+require ('client.conf.php');
+api_block_anonymous_users();
+$htmlHeadXtra[] = '<link rel="stylesheet" type="text/css" href="search.css" />';
+
+$start_time = time();
+$xml_file = $server_url.'?'.$_SERVER['QUERY_STRING'];
+//if(!$doc = xmldocfile($xml_file)){
+$results = simplexml_load_file($xml_file);
+if($results === false)
+{
+	$res = array();
+}
+else
+{
+	//$doc->load($xml_file);
+	$subTotals = array();
+	$lasttag = '';
+	$myindex = 0;
+	$level = 0;
+	//$root = $doc->root();
+	//$root = $doc->documentElement;
+	$my_query = $results->query;
+	$my_search_info = $results->search_info;
+	$my_search_term = $results->search_term;
+	$my_num_found = $results->num_found;
+	$my_search_time = $results->search_time;
+	$elementCount = 1;
+}
+/**
+ * This function is just a display helper.
+ * @param	integer	Result ID
+ * @param	string	Result title
+ * @param	string	Result URL
+ * @param	string	Short excerpt of the result document
+ * @param	
+ */
+function result_output($id,$title,$url='',$excerpt='',$date='',$rating=''){
+	if(empty($id) OR empty($title)){return false;}
+	$title = urldecode($title);
+	$title = preg_replace('/\?cidReq=.*$/','',$title);
+        $excerpt = preg_replace('/<hl>\s*(<hl>)?/','<div class="highlight">',$excerpt);
+        $excerpt = preg_replace('/<\/hl>\s*(<\/hl>)?/','</div> ',$excerpt);
+        $excerpt = stripslashes($excerpt);
+	$string = "<div class='result'>\n" .
+			"<div class='title'>$id. <a href='$url'>$title</a> - $date - $rating</div>\n" .
+			"<div class='description'>$excerpt</div>\n" .
+			"</div>\n";
+	//$string = "$id. <a href='$url'>$title</a> - $date<br/><i>$excerpt</i><br/><br/>";
+	return $string;
+}
+
+include('../../../main/inc/header.inc.php');
+?>
+
+<form method="get" action="<?php echo $search_url; ?>"><input 
+type="hidden" name="ps" value="1000"/><input 
+type="hidden" name="o" value="0"/><input 
+type="hidden" name="m" value="any"/><input 
+type="hidden" name="wm" value="sub"/><input 
+type="hidden" name="wf" value="2221"/><input 
+type="hidden" name="s" value="RDP"/><input 
+type="hidden" name="sy" value="1"/><input 
+type="text" name="q" value="<?php echo urldecode($my_query);?>" size="10" style="margin: 4px 6px; border: 1px solid #B6BB8C; color:#4D4F3A; height: 15px;padding:0px;"><input 
+type="submit" name="submit" value="<?php echo $lang_search_button; ?>" style="margin: 4px 6px; border: 1px solid #B6BB8C; color:#4D4F3A; height:17px;vertical-align:top;padding:0px"></form>
+<?php
+$i = 1;
+$to_print = '';
+foreach($results->result as $res){
+	if(access_check($res->result_du)){
+		$to_print .= result_output($i,mb_convert_encoding(urldecode($res->result_dt),$charset,'utf-8'),$res->result_du,html_entity_decode(urldecode($res->result_de)),htmlentities(urldecode($res->result_dm)),$res->result_dr);
+		$i++;
+	}
+}
+//TODO check if a time and number of results is defined
+$i--;
+if($to_print != ''){
+	//$time = $res['search_time'] + (time() - $start_time);
+	//echo "<div class='search_info'>".$i.' '.$lang_search_found.' '.$time." $lang_seconds</div><br/>\n";
+	echo "<div class='search_info'>".$i.' '.$lang_search_found."</div><br/>\n";
+	echo $to_print;
+}else{
+	echo "<div class='search_info'>".$lang_no_result_found."</div><br/>\n"; 
+}
+include('../../../main/inc/footer.inc.php');
+?>

+ 47 - 0
plugin/search/client/www/indexer_login.php

@@ -0,0 +1,47 @@
+<?php
+/**
+ * This file has to be placed at the root level of your Dokeos portal and has
+ * to be referenced inside the indexer.conf file on your indexing server, as the
+ * first URL to index on your portal.
+ */
+//the ip_address_of_search_server is the IP address from which your search
+// (or indexing) server will connect to your portal to index it
+$ip_address_of_search_server = '192.168.1.1';
+//the domain_name_of_search_server is the domain name from which your search
+// (or indexing) server will connect to your portal to index it
+$domain_name_of_search_server = 'your.domain.com';
+// indexing_user_id is the database ID of the user you created to be used by
+// the indexing server to crawl your portal
+$indexing_user_id = 'xxx';
+
+if($_SERVER['REMOTE_ADDR']==$ip_address_of_search_server 
+	or $_SERVER['REMOTE_HOST'] == $domain_name_of_search_server){
+  
+  //make sure we don't display errors if the authentication does not work
+  ini_set('display_errors','Off');
+  require_once('main/inc/global.inc.php');
+  
+  $id = $indexing_user_id;
+  //subscribe user to all courses
+  $course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
+  $course = Database::get_main_table(TABLE_MAIN_COURSE);
+  $sql = "DELETE FROM $course_rel_user WHERE user_id = $id";
+  $res = @api_sql_query($sql,__FILE__,__LINE__);
+  $sql = "SELECT code FROM $course";
+  $res = @api_sql_query($sql,__FILE__,__LINE__);
+  if(Database::num_rows($res)>0)
+  {
+    while ($row = Database::fetch_array($res))
+    {
+      $sql2 = "INSERT INTO $course_rel_user (course_code,user_id,status)VALUES('".$row['code']."',$id,5)";
+      $res2 = @api_sql_query($sql2,__FILE__,__LINE__);
+    }
+  }
+  //now login the user to the platform (put everything needed inside the 
+  // session) and then redirect the search engine to the courses list 
+  $_SESSION['_user']['user_id'] = $id;
+  define('DOKEOS_HOMEPAGE', true);
+  require('main/inc/global.inc.php');
+  require('user_portal.php');
+}
+?>

+ 23 - 0
plugin/search/index.php

@@ -0,0 +1,23 @@
+<?php //$id: $
+/**
+ * This script is used as the entrance to the search plugin page. Due to its short form,
+ * it can be included as a plugin in the Dokeos menu bar.
+ * No process is operated here. Just displaying the HTML form. 
+ * @package dokeos.search
+ * @author Yannick Warnier <yannick.warnier@dokeos.com>
+ */
+/**
+ * Variables
+ */
+include('client/client.conf.php');
+?>
+<form method="get" style='margin:0px;padding:0px;width:70px;background-color:transparent;height:20px;display:inline;margin-left: 20px;' action="<?php echo $search_url; ?>"><input 
+type="hidden" name="ps" value="1000"/><input 
+type="hidden" name="o" value="0"/><input 
+type="hidden" name="m" value="any"/><input 
+type="hidden" name="wm" value="sub"/><input 
+type="hidden" name="wf" value="2221"/><input 
+type="hidden" name="s" value="RDP"/><input 
+type="hidden" name="sy" value="1"/><input 
+type="text" name="q" value="<?php echo $lang_search_button; ?>..." size="10" style="margin: 0px; border: 1px solid #B6BB8C; color:#4D4F3A; height: 15px;padding:0px;" onclick="javascript:this.value='';"><!--input 
+type="submit" name="submit" value="<?php echo $lang_search_button; ?>" style="margin: 4px 6px; border: 1px solid #B6BB8C; color:#4D4F3A; height:17px;vertical-align:top;padding:0px"--></form>

+ 24 - 0
plugin/search/plugin.php

@@ -0,0 +1,24 @@
+<?php //$id: $
+/**
+ * This script is a configuration file for the search plugin. 
+ * You can use it as a master for other plugins.
+ * These settings will be used in the administration interface for 
+ * plugins (Dokeos configuration settings->Plugins)
+ * Make sure your read the README.txt file to understand how to use this plugin!
+ * @package dokeos.plugin 
+ * @author Yannick Warnier <yannick.warnier@dokeos.com>
+ */
+/**
+ * Plugin details (must be present) 
+ */
+//the plugin title
+$plugin_info['title']='Search';
+//the comments that go with the plugin
+$plugin_info['comment']="Full-text search engine";
+//the locations where this plugin can be shown
+$plugin_info['location']=array('mycourses_main', 'mycourses_menu', 'header', 'footer');
+//the plugin version
+$plugin_info['version']='1.0';
+//the plugin author
+$plugin_info['author']='Yannick Warnier';
+?>

+ 1 - 0
plugin/search/server/cron.d/dokeos-indexer

@@ -0,0 +1 @@
+0 5 * * * root /usr/sbin/indexer -N 2 /etc/mnogosearch/indexer.conf &>/dev/null

+ 1048 - 0
plugin/search/server/etc/indexer.conf

@@ -0,0 +1,1048 @@
+#!/usr/sbin/indexer -d
+
+###########################################################################
+# This is a sample indexer config file.
+# To start using it please edit and rename to indexer.conf.
+# You can also make this file executable and run it directly.
+# You may want to keep the original indexer.conf-dist for future references.
+# Use '#' to comment out lines.
+# All command names are case insensitive (DBAddr=DBADDR=dbaddr).
+# You may use '\' character to prolong current command to next line
+# when it is required.
+#
+# You may include another configuration file in any place of the indexer.conf
+# using "Include <filename>" command.
+# Absolute path if <filename> starts with "/":
+#Include /etc/mnogosearch/inc1.conf
+# Relative path else:
+#Include inc1.conf
+###########################################################################
+
+
+
+###########################################################################
+#  Section 1.
+#  Global parameters.
+
+
+###########################################################################
+# DBAddr <URL-style database description>
+# Options (type, host, database name, port, user and password) 
+# to connect to SQL database.
+# Should be used before any other commands.
+# Has global effect for whole config file.
+# Format:
+#DBAddr <DBType>:[//[DBUser[:DBPass]@]DBHost[:DBPort]]/DBName/[?dbmode=mode]
+#
+# ODBC notes:
+#	Use DBName to specify ODBC data source name (DSN)
+#	DBHost does not matter, use "localhost".
+#
+# Currently supported DBType values are 
+# mysql, pgsql, mssql, oracle, ibase, db2, mimer, sqlite.
+# 
+# MySQL users can specify path to Unix socket when connecting to localhost:
+# mysql://foo:bar@localhost/mnogosearch/?socket=/tmp/mysql.sock
+#
+# If you are using PostgreSQL and do not specify hostname,
+#	e.g. pgsql://user:password@/dbname/
+# then PostgreSQL will not work via TCP, but will use Unix socket.
+#
+# You may also select database mode of word storage.
+# When "single" is specified, all words are stored in the same table.
+# If "multi" is selected, words will be located in different tables.
+# "multi" mode is usually faster but requires more tables.
+# Default mode is "single".
+
+DBAddr  mysql://db_user:db_password@db_host/db_name/?dbmode=single
+
+######################################################################
+# VarDir /var/lib/mnogosearch
+# You may choose alternative working directory for 
+# search results cache:
+#
+#VarDir /var/lib/mnogosearch
+
+
+
+######################################################################
+# NewsExtensions yes/no
+# Whether to enable news extensions.
+# Default value is no.
+#NewsExtensions no
+
+
+#######################################################################
+#SyslogFacility <facility>
+# This is used if indexer was compiled with syslog support and if you
+# don't like the default value. Argument is the same as used in syslog.conf
+# file. For list of possible facilities see syslog.conf(5)
+#SyslogFacility local7
+
+
+#######################################################################
+# LocalCharset <charset>
+# Defines the charset which will be used to store data in the database.
+# All other character sets will be converted into the given charset.
+# Take a look into mnoGoSearch documentation for detailed explanation 
+# how to choose a LocalCharset depending on languages used on your site(s).
+# This command should be used once and takes global effect for the config file.
+# Only most popular charsets used in Internet are written here.
+# Take a look into the documentation to check the whole list of
+# supported charsets.
+# Default LocalCharset is iso-8859-1 (latin1).
+#
+# Western Europe: German, Finnish, French, Swedish
+LocalCharset iso-8859-1
+#LocalCharset windows-1252
+
+# Central Europe: Czech, Slovenian, Slovak, Hungarian, Polish
+#LocalCharset iso-8859-2
+#LocalCharset windows-1250
+
+# Baltic: Lithuanian, Estonian, Latvian
+#LocalCharset iso-8859-4
+#LocalCharset iso-8859-13
+#LocalCharset windows-1257
+
+# Cyrillic: Russian, Serbian, Ukrainian, Belarussian, Macedonian, Bulgarian
+#LocalCharset koi8-r
+#LocalCharset iso-8859-5
+#LocalCharset x-mac-cyrillic
+#LocalCharset windows-1251
+
+# Arabic
+#LocalCharset iso-8859-6
+#LocalCharset windows-1256
+
+# Greek
+#LocalCharset iso-8859-7
+#LocalCharset windows-1253
+
+# Hebrew
+#LocalCharset iso-8859-8
+#LocalCharset windows-1255
+
+# Turkish
+#LocalCharset iso-8859-9
+#LocalCharset windows-1254
+
+# Vietnamese
+#LocalCharset viscii
+#LocalCharset windows-1258
+
+# Chinese
+#LocalCharset gb2312
+#LocalCharset BIG5
+
+# Korean
+#LocalCharset EUC-KR
+
+# Japanese
+#LocalCharset Shift-JIS
+
+# Full UNICODE
+#LocalCharset UTF-8
+#LocalCharset iso-8859-1
+#LocalCharset windows-1252
+
+#######################################################################
+#ForceIISCharset1251 yes/no
+#This option is useful for users which deals with Cyrillic content and broken
+#(or misconfigured?) Microsoft IIS web servers, which tends to not report
+#charset correctly. This is really dirty hack, but if this option is turned on
+#it is assumed that all servers which reports as 'Microsoft' or 'IIS' have
+#content in Windows-1251 charset.
+#This command should be used only once in configuration file and takes global
+#effect.
+#Default: no
+#ForceIISCharset1251 no
+
+
+###########################################################################
+#CrossWords yes/no
+# Whether to build CrossWords index
+# Default value is no
+#CrossWords no
+CrossWords yes
+
+
+###########################################################################
+# StopwordFile <filename>
+# Load stop words from the given text file. You may specify either absolute 
+# file name or a name relative to mnoGoSearch /etc directory. You may use
+# several StopwordFile commands.
+#
+#StopwordFile stopwords/en.sl
+
+Include stopwords.conf
+
+
+###########################################################################
+# LangMapFile <filename>
+# Load language map for charset and language guesser from the given file. 
+# You may specify either an absolute file name or a name relative 
+# to mnoGoSearch /etc directory. You may use several LangMapFile commands.
+#
+#LangMapFile langmap/en.ascii.lm
+
+Include langmap.conf
+
+
+#######################################################################
+# Word lengths. You may change default length range of words
+# stored in the database. By default, words with the length in the
+# range from 1 to 32 are stored.
+#
+#MinWordLength 1
+#MaxWordLength 32
+
+#######################################################################
+# MaxDocSize bytes
+# Default value 1048576 (1 Mb)
+# Takes global effect for whole config file
+MaxDocSize 10485760
+
+#######################################################################
+# URLSelectCacheSize num
+# Default value 128
+# Select <num> targets to index at once. 
+#URLSelectCacheSize 1024
+
+#######################################################################
+# WordCacheSize bytes
+# Default value 8388608 (8 Mb)
+# Defines maximal in-memory words cache size.
+# Note: cache is allocated for every DBAddr, so if you have 3 DBAddr
+# commands and WordCacheSize is 10Mb, it can take up to 30Mb of memory.
+#WordCacheSize 8388608
+
+#######################################################################
+# HTTPHeader <header>
+# You may add your desired headers in indexer HTTP request.
+# You should not use "If-Modified-Since","Accept-Charset" headers,
+# these headers are composed by indexer itself.
+# "User-Agent: mnoGoSearch/version" is sent too, but you may override it.
+# Command has global effect for all configuration file.
+#
+#HTTPHeader "User-Agent: My_Own_Agent"
+#HTTPHeader "Accept-Language: ru, en"
+HTTPHeader "Accept-Language: fr, nl, en, de, es"
+#HTTPHeader "From: webmaster@mysite.com"
+
+
+# flush server.active to inactive for all server table records
+# before loading new
+#FlushServerTable
+
+#######################################################################
+# ServerTable <table_addr>
+# Load servers with all their parameters from the table specified in argument.
+# Check an example of tables server and srvinfo structure in
+# create/(your_database)/create.txt
+#
+#ServerTable mysql://user:pass@host/dbname/tablename
+
+##########################################################################
+# LoadChineseList <charset> <dictionaryfilename>
+# Load Chinese word frequency list. 
+# By default GB2312 charset and mandarin.freq dictionary is used.
+#LoadChineseList
+
+########################################################################## 
+# LoadThaiList <charset> <dictionaryfilename>
+# Load Thai word frequency list
+# By default tis-620 and thai.freq dictionary is used.
+#LoadThaiList
+
+##########################################################################
+# Section 2.
+# URL control configuration.
+
+
+##########################################################################
+#Allow [Match|NoMatch] [NoCase|Case] [String|Regex] <arg> [<arg> ... ]
+# Use this to allow URLs that match (doesn't match) the given argument.
+# First three optional parameters describe the type of comparison.
+# Default values are Match, NoCase, String.
+# Use "NoCase" or "Case" values to choose case insensitive or case sensitive
+# comparison.
+# Use "Regex" to choose regular expression comparison. 
+# Use "String" to choose string with wildcards comparison.
+# Wildcards are '*' for any number of characters and '?' for one character.
+# Note that '?' and '*' have special meaning in "String" match type. Please use
+# "Regex" to describe documents with '?' and '*' signs in URL.
+# "String" match is much faster than "Regex". Use "String" where it 
+# is possible.
+# You may use several arguments for one 'Allow' command.
+# You may use this command any times.
+# Takes global effect for config file.
+# Note that mnoGoSearch automatically adds one "Allow regex .*"
+# command after reading config file. It means that allowed everything
+# that is not disallowed.
+# Examples
+#  Allow everything:
+#Allow *
+#  Allow everything but .php .cgi .pl extensions case insensitively using regex:
+#Allow NoMatch Regex \.php$|\.cgi$|\.pl$
+#  Allow .HTM extension case sensitively:
+#Allow Case *.HTM
+
+
+##########################################################################
+#Disallow [Match|NoMatch] [NoCase|Case] [String|Regex] <arg> [<arg> ... ]
+# Use this to disallow URLs that match (doesn't match) given argument.
+# The meaning of first three optional parameters is exactly the same 
+# with "Allow" command.
+# You can use several arguments for one 'Disallow' command.
+# Takes global effect for config file.
+#
+# Examples:
+# Disallow URLs that are not in udm.net domains using "string" match:
+#Disallow NoMatch *.udm.net/*
+# Disallow any except known extensions and directory index using "regex" match:
+#Disallow NoMatch Regex \/$|\.htm$|\.html$|\.shtml$|\.phtml$|\.php$|\.txt$
+# Exclude cgi-bin and non-parsed-headers using "string" match:
+#Disallow */cgi-bin/* *.cgi */nph-*
+# Exclude anything with '?' sign in URL. Note that '?' sign has a 
+# special meaning in "string" match, so we have to use "regex" match here:
+#Disallow Regex  \?
+
+Disallow Match *whoisonline*
+Disallow Match *myagenda*
+Disallow Match *&rand=*
+Disallow Match */chat/*
+Disallow Match */auth/*
+Disallow Match */online/*
+Disallow Match */user/*
+Disallow Match */admin/*
+Disallow Match */group/*
+Disallow Match *delete*
+Disallow Match *del*
+Disallow Match *remove*
+Disallow Match *example_document.html*
+
+
+# Exclude some known extensions using fast "String" match:
+Disallow *.b    *.sh   *.md5  *.rpm
+Disallow *.arj  *.tar  *.zip  *.tgz  *.gz   *.z     *.bz2 
+Disallow *.lha  *.lzh  *.rar  *.zoo  *.ha   *.tar.Z
+Disallow *.gif  *.jpg  *.jpeg *.bmp  *.tiff *.tif   *.xpm  *.xbm *.pcx
+Disallow *.vdo  *.mpeg *.mpe  *.mpg  *.avi  *.movie *.mov  *.wmv
+Disallow *.mid  *.mp3  *.rm   *.ram  *.wav  *.aiff  *.ra
+Disallow *.vrml *.wrl  *.png  *.ico  *.psd  *.dat
+Disallow *.exe  *.com  *.cab  *.dll  *.bin  *.class *.ex_
+#Disallow *.xls *.doc
+Disallow *.tex  *.texi *.texinfo
+# Disallow *.rtf  *.pdf  *.ps *.eps
+Disallow *.cdf
+Disallow *.ai   *.ppt  *.hqx
+Disallow *.cpt  *.bms  *.oda  *.tcl
+Disallow *.o    *.a    *.la   *.so 
+Disallow *.pat  *.pm   *.m4   *.am   *.css
+Disallow *.map  *.aif  *.sit  *.sea
+Disallow *.m3u  *.qt
+
+# Exclude Apache directory list in different sort order using "string" match:
+Disallow *D=A *D=D *M=A *M=D *N=A *N=D *S=A *S=D
+
+# More complicated case. RAR .r00-.r99, ARJ a00-a99 files 
+# and UNIX shared libraries. We use "Regex" match type here:
+Disallow Regex \.r[0-9][0-9]$ \.a[0-9][0-9]$ \.so\.[0-9]$
+
+
+##########################################################################
+#CheckOnly [Match|NoMatch] [NoCase|Case] [String|Regex] <arg> [<arg> ... ]
+# The meaning of first three optional parameters is exactly the same 
+# with "Allow" command.
+# Indexer will use HEAD instead of GET HTTP method for URLs that
+# match/do not match given regular expressions. It means that the file 
+# will be checked only for being existing and will not be downloaded. 
+# Useful for zip,exe,arj and other binary files.
+# Note that you can disallow those files with commands given below.
+# You may use several arguments for one "CheckOnly" commands.
+# Useful for example for searching through the URL names rather than
+# the contents (a la FTP-search).
+# Takes global effect for config file.
+#
+# Check some known non-text extensions using "string" match:
+#CheckOnly *.b	  *.sh   *.md5
+#CheckOnly *.arj  *.tar  *.zip  *.tgz  *.gz
+#CheckOnly *.lha  *.lzh  *.rar  *.zoo  *.tar*.Z
+#CheckOnly *.gif  *.jpg  *.jpeg *.bmp  *.tiff 
+#CheckOnly *.vdo  *.mpeg *.mpe  *.mpg  *.avi  *.movie
+#CheckOnly *.mid  *.mp3  *.rm   *.ram  *.wav  *.aiff
+#CheckOnly *.vrml *.wrl  *.png
+#CheckOnly *.exe  *.cab  *.dll  *.bin  *.class
+#CheckOnly *.tex  *.texi *.xls  *.doc  *.texinfo
+#CheckOnly *.rtf  *.pdf  *.cdf  *.ps
+#CheckOnly *.ai   *.eps  *.ppt  *.hqx
+#CheckOnly *.cpt  *.bms  *.oda  *.tcl
+#CheckOnly *.rpm  *.m3u  *.qt   *.mov
+#CheckOnly *.map  *.aif  *.sit  *.sea
+#
+# or check ANY except known text extensions using "regex" match:
+#CheckOnly NoMatch Regex \/$|\.html$|\.shtml$|\.phtml$|\.php$|\.txt$
+#CheckOnly NoMatch Regex &rand=[0-9][0-9][0-9][0-9]$|myagenda\.php.*$|whoisonline\.php.*$
+
+
+##########################################################################
+#HrefOnly [Match|NoMatch] [NoCase|Case] [String|Regex] <arg> [<arg> ... ]
+# The meaning of first three optional parameters is exactly the same 
+# with "Allow" command.
+#
+# Use this to scan a HTML page for "href" tags but not to index the contents
+# of the page with an URLs that match (doesn't match) given argument.
+# Commands have global effect for all configuration file.
+#
+# When indexing large mail list archives for example, the index and thread
+# index pages (like mail.10.html, thread.21.html, etc.) should be scanned 
+# for links but shouldn't be indexed:
+#
+#HrefOnly */mail*.html */thread*.html
+HrefOnly Match *dk_sid=*
+HrefOnly Match *indexer_login.php*
+HrefOnly Match */your.domain.com/index.php*
+HrefOnly Match */document.php*
+HrefOnly Match */courses/*/index.php
+HrefOnly Match */courses/*/
+HrefOnly Match */document/headerpage.php*
+HrefOnly Match */document/slideshow.php*
+
+
+##########################################################################
+#CheckMp3 [Match|NoMatch] [NoCase|Case] [String|Regex] <arg> [<arg> ...]
+# The meaning of first three optional parameters is exactly the same 
+# with "Allow" command.
+# If an URL matches given rules, indexer will download only a little part
+# of the document and try to find MP3 tags in it. On success, indexer
+# will parse MP3 tags, else it will download whole document then parse
+# it as usual.
+# Notes:
+# This works only with those servers which support HTTP/1.1 protocol.
+# It is used "Range: bytes" header to download mp3 tag.
+#CheckMp3 *.bin *.mp3
+
+
+#######################################################################
+#CheckMP3Only [Match|NoMatch] [NoCase|Case] [String|Regex] <arg> [<arg> ...]
+# The meaning of first three optional parameters is exactly the same 
+# with "Allow" command.
+# If an URL matches given rules, indexer, like in the case CheckMP3 command,
+# will download only a little part of the document and try to find MP3 tags.
+# On success, indexer will parse MP3 tags, else it will NOT download whole 
+# document.
+#CheckMP3Only *.bin *.mp3
+
+
+# How to combine Allow, Disallow, CheckOnly, HrefOnly commands.
+#
+# indexer compares URLs against all these command arguments in the 
+# order of their appearance in indexer.conf file. 
+# If indexer finds that URL matches some rule, it will make a decision of what 
+# to do with this URL, allow it, disallow it or use HEAD instead 
+# of the GET method. So, you may use different Allow, Disallow,
+# CheckOnly, HrefOnly commands order.
+# If no one of these commands are given, mnoGoSearch will allow everything 
+# by default.
+#
+# There are many possible combinations. Samples of two of them are here:
+#
+# Sample of first useful combination.
+# Disallow known non-text extensions (zip,wav etc),
+# then allow everything else. This sample is uncommented above (note that
+# there is actually no "Allow *" command, it is added automatically after
+# indexer.conf loading).
+#
+# Sample of second combination.
+# Allow some known text extensions (html, txt) and directory index ( / ), 
+# then disallow everything else:
+#
+#Allow .html .txt */
+#Disallow *
+
+# HoldBadHrefs <time>
+# Default valie is 0.
+# How much time to hold URLs with erroneous status before deleting them
+# from the database. For example, if host is down, indexer will not delete
+# pages from this site immediately and search will use previous content
+# of these pages.. However if site doesn't respond for a month, probably 
+# it's time to remove these pages from the database.
+# For <time> format see description of Period command.
+#HoldBadHrefs 30d
+
+
+################################################################
+# Section 3.
+# Mime types and external parsers.
+
+
+################################################################
+#UseRemoteContentType yes/no
+# Default value is yes.
+# This command specifies if the indexer should get content type
+# from HTTP server headers (yes) or from it's AddType settings (no).
+# If set to 'no' and the indexer could not determine content-type
+# by using its AddType settings, then it will use HTTP header.
+# Default: yes
+#UseRemoteContentType yes
+
+
+################################################################
+#AddType [String|Regex] [Case|NoCase] <mime type> <arg> [<arg>...]
+# This command associates filename extensions (for services
+# that don't automatically include them) with their mime types.
+# Currently "file:" protocol uses these commands.
+# Use optional first two parameter to choose comparison type.
+# Default type is "String" "NoCase" (case sensitive string match with
+# '?' and '*' wildcards for one and several characters correspondingly).
+#
+AddType image/x-xpixmap	*.xpm
+AddType image/x-xbitmap	*.xbm
+AddType image/gif	*.gif
+
+AddType	text/plain			*.txt  *.pl *.js *.h *.c *.pm *.e
+AddType	text/html			*.html *.htm
+
+AddType text/rtf			*.rtf
+AddType application/pdf			*.pdf
+AddType application/msword		*.doc
+AddType application/vnd.ms-excel	*.xls
+AddType text/x-postscript		*.ps
+
+
+# You may also use quotes in mime type definition
+# for example to specify charset. e.g. Russian webmasters 
+# often use *.htm extension for windows-1251 documents and
+# *.html for UNIX koi8-r documents:
+#
+#AddType "text/html; charset=koi8-r"       *.html
+#AddType "text/html; charset=windows-1251" *.htm
+#
+# More complicated example for rar .r00-r.99 using "Regex" match:
+#AddType Regex application/rar  \.r[0-9][0-9]$
+#
+# Default unknown type for other extensions:
+AddType	application/unknown *.*
+
+
+# Mime <from_mime> <to_mime> <command line>
+#
+# This is used to add support for parsing documents with mime types other
+# than text/plain and text/html. It can be done via external parser (which
+# must provide output in plain or html text) or just by substituting mime
+# type so indexer will understand it.
+#
+# <from_mime> and <to_mime> are standard mime types
+# <to_mime> is either text/plain or text/html
+#
+# Optional charset parameter used to change charset if needed
+#
+# Command line may have $1 parameter which stands for temporary file name. 
+# Some parsers can not operate on stdin, so indexer creates temporary file 
+# for parser and it's name passed instead of $1. Take a look into documentation
+# for other parser types and parsers usage explanation.
+# Examples:
+#
+#       from_mime                to_mime[charset]             [command line [$1]]
+#
+Mime application/msword      "text/plain; charset=utf-8" "catdoc -a -dutf-8 $1"
+#Mime application/x-troff-man  text/plain                 "deroff"
+Mime text/x-postscript        text/plain                 "ps2ascii"
+Mime application/pdf          text/plain                 "pdftotext $1 -"
+Mime application/vnd.ms-excel text/plain                 "xls2csv $1"
+Mime "text/rtf*"              text/html                  "unrtf --html $1"
+Mime application/rtf          text/html                  "unrtf --html $1"
+
+# Use ParserTimeOut to specify amount of time for parser execution
+# to avoid possible indexer hang.
+ParserTimeOut 300
+
+
+#########################################################################
+# Section 4.
+# Aliases configuration.
+
+
+#########################################################################
+#Alias <master> <mirror>
+# You can use this command for example to organize search through 
+# master site by indexing a mirror site. It is also useful to
+# index your site from local file system.
+# mnoGoSearch will display URLs from <master> while searching
+# but go to the <mirror> while indexing.
+# This command has global indexer.conf file effect. 
+# You may use several aliases in one indexer.conf.
+#Alias http://www.mysql.com/ http://mysql.udm.net/
+#Alias http://www.site.com/  file:///usr/local/apache/htdocs/
+
+
+#########################################################################
+#AliasProg <command line>
+# AliasProg is an external program that can be called, that takes a URL,
+# and returns the appropriate alias to stdout. Use $1 to pass a URL. This
+# command has global effect for whole indexer.conf.
+# Example:
+#AliasProg "echo $1 | /usr/bin/replace http://localhost/ file:///home/httpd/"
+
+
+#######################################################################
+# Section 5.
+# Servers configuration.
+
+
+#######################################################################
+#Period <time>
+# Default value is 7d (i.e. 7days).
+# Set reindex period.
+# <time> is in the form 'xxxA[yyyB[zzzC]]'                                   
+# (Spaces are allowed between xxx and A and yyy and so on)                     
+#   there xxx, yyy, zzz are numbers (can be negative!)                         
+#         A, B, C can be one of the following:                                 
+#		s - second                                                      
+#		M - minute                                                      
+#		h - hour                                                        
+#		d - day                                                         
+#		m - month                                                       
+#		y - year                                                        
+#      (these letters are the same as in strptime/strftime functions)                   
+#                                                                              
+# Examples:
+# 15s - 15 seconds
+# 4h30M - 4 hours and 30 minutes
+# 1y6m-15d - 1 year and six month minus 15 days
+# 1h-10M+1s - 1 hour minus 10 minutes plus 1 second
+#
+# If you specify only number without any character, it is assumed
+# that time is given in seconds.
+#
+# Can be set many times before "Server" command and
+# takes effect till the end of config file or till next Period command.
+#Period 7d
+
+
+#######################################################################
+#Tag <string>
+# Use this field for your own purposes. For example for grouping
+# some servers into one group, etc... During search you'll be able to
+# limit URLs to be searched through by their tags.
+# Can be set multiple times before "Server" command and
+# takes effect till the end of config file or till next Tag command.
+# Default values is an empty sting
+
+
+#######################################################################
+#Category <string>
+#You may distribute documents between nested categories. Category
+#is a string in hex number notation. You may have up to 6 levels with
+#256 members per level. Empty category means the root of category tree.
+#Take a look into doc/categories.xml for more information.
+#This command means a category on first level:
+#Category AA
+#This command means a category on 5th level:
+#Category FFAABBCCDD
+
+
+#######################################################################
+#DefaultLang <string>
+#Default language for server. Can be used if you need language
+#restriction while doing search.
+#Default value is empty.
+#DefaultLang en
+DefaultLang fr
+
+
+#######################################################################
+#VaryLang <string>
+#Default value is empty, i.e. don't vary language.
+#Specify languages list for multilingual servers indexing
+#VaryLang "ru en fr de" 
+VaryLang "fr nl en de es"
+
+#######################################################################
+#MaxHops <number>
+# Maximum way in "mouse clicks" from start url.
+# Default value is 256.
+# Can be set multiple times before "Server" command and
+# takes effect till the end of config file or till next MaxHops command.
+#MaxHops 256
+
+
+#######################################################################
+#MaxNetErrors <number>
+# Maximum network errors for each server.
+# Default value is 16. Use 0 for unlimited errors number.
+# If there too many network errors on some server 
+# (server is down, host unreachable, etc) indexer will try to do 
+# not more then 'number' attempts to connect to this server.
+# Takes effect till the end of config file or till next MaxNetErrors command.
+#MaxNetErrors 16
+
+
+#######################################################################
+#ReadTimeOut <time>
+# Connect timeout and stalled connections timeout.
+# For <time> format see description of Period above.
+# Default value is 30 seconds.
+# Can be set any times before "Server" command and
+# takes effect till the end of config file or till next ReadTimeOut command.
+#ReadTimeOut 30s
+
+
+#######################################################################
+#DocTimeOut <time>
+# Maximum amount of time indexer spends for one document downloading.
+# For <time> format see description of Period above.
+# Default value is 90 seconds.
+# Can be set any times before "Server" command and
+# takes effect till the end of config file or till next DocTimeOut command.
+DocTimeOut 600s
+
+
+########################################################################
+#NetErrorDelayTime <time>
+# Specify document processing delay time if network error has occurred.
+# For <time> format see description of Period above.
+# Default value is one day
+#NetErrorDelayTime 1d
+
+
+#######################################################################
+#Robots yes/no
+# Allows/disallows using robots.txt and <META NAME="robots">
+# exclusions. Use "no", for example for link validation of your server(s).
+# Command may be used several times before "Server" command and
+# takes effect till the end of config file or till next Robots command.
+# Default value is "yes".
+#Robots yes
+
+
+#######################################################################
+#DetectClones yes/no
+# Allow/disallow clone detection and eliminating. If allowed, indexer will 
+# detect the same documents under different location, such as
+# mirrors, and will index only one document from the group of
+# such equal documents. "DetectClones yes" also allows to reduce space usage.
+# Default value is "yes".
+DetectClones yes
+
+
+#######################################################################
+# Document sections.
+#
+# Format is:
+#
+#   Section <string> <number> <maxlen> [clone] [sep] [{expr} {repl}]
+#
+# where <string> is a section name and <number> is section ID
+# between 0 and 255. Use 0 if you don't want to index some of 
+# these sections. It is better to use different sections IDs
+# for different documents parts. In this case during search 
+# time you'll be able to give different weight to each part
+# or even disallow some sections at a search time.
+# <maxlen> argument contains a maximum length of section
+# which will be stored in database.
+# "clone" is an optional parameter describing whether this
+# section should affect clone detection. It can 
+# be "DetectClone" or "cdon", or "NoDetectClone" or "cdoff".
+# By default, url.* section values are not taken in account
+# for clone detection, while any other sections take part
+# in clone detection.
+# "sep" is an optional argument to specify a separator between
+# parts of the same section. It is a space character by default.
+# "expr" and "repl" can be used to extract user defined sections,
+# for example pieces of text between the given tags. "expr" is
+# a regular expression, "repl" is a replacement with $1, $2, etc
+# meta-characters designating matches "expr" matches.
+
+# Standard HTML sections: body, title
+
+Section	body			1	256
+Section title			2	128
+
+# META tags
+# For example <META NAME="KEYWORDS" CONTENT="xxxx">
+#
+
+Section meta.keywords		3	128
+Section	meta.description	4	128
+
+# HTTP headers example, let's store "Server" HTTP header
+#
+#
+#Section header.server		5	64
+
+
+# Document's URL parts
+
+Section url.file		6	0
+Section url.path		7	0
+Section	url.host		8	0
+Section url.proto		9	0
+
+# CrossWords
+
+Section crosswords		10	0
+
+#
+# If you use CachedCopy for smart excerpts (see below), 
+# please keep Charset section active.
+#
+Section Charset 		11 	32
+
+Section Content-Type		12	64
+Section Content-Language	13	16
+
+# Uncomment the following lines if you want tag attributes
+# to be indexed
+
+#Section attribute.alt		14	128
+#Section attribute.label	15	128
+#Section attribute.summary	16	128
+#Section attribute.title	17	128
+#Section attribute.face		27	0
+
+# Uncomment the following lines if you want use NewsExtensions
+# You may add any Newsgroups header to be indexed and stored in urlinfo table
+
+#Section References		18	0
+#Section Message-ID		19	0
+#Section Parent-ID		20	0
+
+# Uncomment the following lines if you want index MP3 tags.
+#Section MP3.Song           	21    128
+#Section MP3.Album          	22    128
+#Section MP3.Artist         	23    128
+#Section MP3.Year           	24    128
+
+# Comment this line out if you don't want to store "cached copies"
+# to generate smart excerpts at search time.
+# Don't forget to keep "Charset" section active if you use cached copies.
+# NOTE: 3.2.18 has limits for CachedCopy size, 32000 for Ibase and
+# 15000 for Mimer. Other databases do not have limits.
+# If indexer fails with 'string too long' error message then reduce
+# this number. This will be fixed in the future versions.
+#
+Section CachedCopy		25 64000
+
+# A user defined section example.
+# Extract text between <h1> and </h1> tags:
+#Section h1			26 128 "<h1>(.*)</h1>" $1
+
+##########################################################################
+#<IndexIf|NoIndexIf> [Match|NoMatch] [NoCase|Case] [String|Regex] <Section> <arg> [<arg> ... ]
+# Use this to allow documents, which sections match given argument,
+# to be indexed (IndexIf) or not indexed (NoIndexIf).
+# First three optional parameters describe the type of comparison.
+# Default values are Match, NoCase, String.
+# See also Allow/Disallow.
+# You may use several arguments for one 'IndexIf/NoIndexIf' commands.
+# You may use this command any times.
+# Takes global effect for config file.
+# Example1: Don't index a document if its Body section contains "porno"
+#NoIndexIf Body *porno*
+#
+# Example2: Index only those documents with Title section containing "reference"
+#IndexIf Title *reference*
+#NoIndexIf Title *
+
+#######################################################################
+#Index yes/no
+# Prevent indexer from storing words into database.
+# Useful for example for link validation.
+# Can be set multiple times before "Server" command and
+# takes effect till the end of config file or till next Index command.
+# Default value is "yes".
+#Index yes
+
+
+########################################################################
+#RemoteCharset <charset>
+#<RemoteCharset> is default character set for the server in next "Server" 
+# command(s).
+# This is required only for "bad" servers that do not send information
+# about charset in header: "Content-type: text/html; charset=some_charset"
+# and do not have <META NAME="Content" Content="text/html; charset="some_charset">
+# Can be set before every "Server" command and
+# takes effect till the end of config file or till next RemoteCharset command.
+# Default value is iso-8859-1 (latin1).
+RemoteCharset iso-8859-1
+
+
+#########################################################################
+#ProxyAuthBasic login:passwd
+# Use HTTP proxy basic authorization 
+# Can be used before every "Server" command and
+# takes effect only for next one "Server" command!
+# It should be also before "Proxy" command.
+# Examples:
+#ProxyAuthBasic somebody:something  
+
+
+#########################################################################
+#Proxy your.proxy.host[:port]
+# Use proxy rather then connect directly
+#One can index ftp servers when using proxy
+#Default port value if not specified is 3128 (Squid)
+#If proxy host is not specified direct connect will be used.
+#Can be set before every "Server" command and
+# takes effect till the end of config file or till next Proxy command.
+#If no one "Proxy" command specified indexer will use direct connect.
+#
+#           Examples:
+#           Proxy on atoll.anywhere.com, port 3128:
+#Proxy atoll.anywhere.com
+#
+#           Proxy on lota.anywhere.com, port 8090:
+#Proxy lota.anywhere.com:8090
+#
+#           Disable proxy (direct connect):
+#Proxy
+
+
+#########################################################################
+#AuthBasic login:passwd
+# Use basic HTTP authorization 
+# Can be set before every "Server" command and
+# takes effect only for next one Server command!
+# Examples:
+#AuthBasic somebody:something  
+#
+# If you have password protected directory(ies), but whole server is open,use:
+#AuthBasic login1:passwd1
+#Server http://my.server.com/my/secure/directory1/
+#AuthBasic login2:passwd2
+#Server http://my.server.com/my/secure/directory2/
+#Server http://my.server.com/
+
+
+##############################################################
+# Mirroring parameters commands.
+#
+# You may specify a path to root directory to enable sites mirroring
+#MirrorRoot /path/to/mirror
+#
+# You may specify as well root directory of mirrored document's headers
+# indexer will store HTTP headers to local disk too.
+#MirrorHeadersRoot /path/to/headers
+#
+# MirrorPeriod <time>
+# You may specify period during which earlier mirrored files 
+# will be used while indexing instead of real downloading.
+# It is very useful when you do some experiments with mnoGoSearch
+# indexing the same hosts and do not want much traffic from/to Internet.
+# If MirrorHeadersRoot is not specified and headers are not stored
+# to local disk then default Content-Type's given in AddType commands
+# will be used.
+# Default value of the MirrorPeriod is -1, which means
+# "do not use mirrored files".
+#
+# For <time> format see Period command description above.
+#
+# The command below will force using local copies for one day:
+#MirrorPeriod 1d
+
+
+#########################################################################
+#ServerWeight <number>
+# Server weight for Popularity Rank calculation.
+# Default value is 1.
+#ServerWeight 1
+
+
+#########################################################################
+#PopRankSkipSameSite yes|no
+# Skip links from same site for Popularity Rank calculation.
+# Default value is "no".
+#PopRankSkipSameSite yes
+
+
+#########################################################################
+#PopRankFeedBack yes|no
+# Calculate sites wights before Popularity Rank calculation.
+# Default value is "no".
+#PopRankSkipSameSite yes
+
+
+#########################################################################
+#Server [Method] [SubSection] <URL> [alias]
+# This is the main command of the indexer.conf file. It's used 
+# to describe web-space you want to index. It also inserts
+# given URL into database to use it as a start point.
+# You may use "Server" command as many times as a number of different
+# servers or their parts you want to index.
+#
+# "Method" is an optional parameter which can take on of the following values:
+# Allow, Disallow, CheckOnly, HrefOnly, CheckMP3, CheckMP3Only, Skip.
+#
+# "SubSection" is an optional parameter to specify server's subsection, 
+# i.e. a part of Server command argument. 
+# It can take the following values:
+# "page" describes web space which consists of one page with address <URL>.
+# "path" describes all documents which are under the same path with <URL>.
+# "site" describes all documents from the same host with <URL>.
+# "world" means "any document".
+# Default value is "path".
+#
+# To index whole server "localhost":
+#Server http://localhost/
+#
+# You can also specify some path to index subdirectory only:
+#Server http://localhost/subdir/
+#
+# To specify the only one page:
+#Server page http://localhost/path/main.html
+#
+# To index whole server but giving non-root page as a start point:
+#Server site http://localhost/path/main.html
+#
+#
+# You can also specify optional parameter "alias". This example will
+# index server "http://www.mnogosearch.org/" directly from disk instead of
+# fetching from HTTP server:
+#Server http://www.mnogosearch.org/  file:///home/httpd/www.mnogosearch.org/
+#
+Server http://your.domain.com/indexer_login.php
+
+
+
+#########################################################################
+#Realm [Method] [CmpType] [Match|NoMatch] <arg> [alias]
+# It works almost like "Server" command but takes a regular expression or 
+# a string wildcards as it's argument and do not insert any URL into
+# database for indexing. To insert URLs into database use URL command (see
+# below).
+#
+# "Method" is an optional parameter which can take one of the following
+# values: Allow, Disallow, CheckOnly, HrefOnly, CheckMP3, CheckMP3Only
+# with Allow as a default value.
+#
+# "CmpType" is an optional parameter to specify comparison type and can
+# take either String or RegExp value with String as a default value.
+#
+# For example, if you want to index all HTTP sites in ".ru" domain, use:
+#Realm http://*.ru/*
+# The same using "Regex" match:
+#Realm Regex ^http://.*\.ru/
+# Another example. Use this command to index everything without .com domain:
+#Realm NoMatch http://*.com/*
+#
+# Optional "alias" argument allows to provide very complicated URL rewrite
+# more powerful than other aliasing mechanism. Take a look into alias.txt
+# for "alias" argument usage explanation.
+
+
+#########################################################################
+#URL http://localhost/path/to/page.html
+# This command inserts given URL into database. This is useful to add
+# several entry points to one server. Has no effect if an URL is already
+# in the database. When inserting indexer does not executes any checks
+# and this URL may be deleted at first indexing attempt if URL has no 
+# correspondent Server command or is disallowed by rules given in 
+# Allow/Disallow commands. 
+#
+#This command will add /main/index.html page:
+#URL http://localhost/main/index.html
+
+UseCookie yes
+

+ 176 - 0
plugin/search/server/www/common.inc

@@ -0,0 +1,176 @@
+<?php
+/**
+ * Library for the common formatting functions
+ */
+/**
+ * Exit, dropping the temporary tables just before that
+ * @param	integer	Whether to print an error message (passed to drop_temp_table())
+ */
+function exit_local($print_err = 1) {
+    drop_temp_table($print_err);
+    exit;
+}
+
+/**
+ * Prints the error and the template bottom, then exit
+ * @param	string	The error message
+ */
+function print_error_local($str){
+    global $error;
+    
+    $error=$str;
+
+    print_template('error');
+    print_template('bottom');
+    
+    exit;
+}
+
+/**
+ * Gets the number of documents from the udm object
+ * @return	mixed	An integer or "Unknown" if not found
+ */
+function get_doc_count() {
+    global $udm_agent;
+
+    if (udm_api_version() >= 30111) {
+		return(udm_get_doc_count($udm_agent));
+    } else {
+    	return "Unknown";
+    } 
+} 
+
+
+/**
+ * Format last modified date
+ * @param	integer	UNIX Timestamp?
+ * @return	string	Formatted date
+ */
+function format_lastmod($lastmod) {
+	$temp=$lastmod;
+	if (!$temp) $temp = 'undefined';
+	elseif (udm_api_version() < 30204) $temp = strftime('%a, %d %b %Y %H:%M:%S %Z',$temp);
+
+	return $temp;
+}
+
+/**
+ * Format date in seconds from a source in s,M,h,d,m,y
+ * @param	string	Date
+ * @return	integer	Date in seconds
+ */
+function format_dp($dp) {
+	$result=0;
+
+	while ($dp != '') {
+		$param = array();
+		if (preg_match('/^([\-\+]?\d+)([sMhdmy]?)/',$dp,$param)) {			
+			switch ($param[2]) {
+				case 's':  $multiplier=1; break;
+                case 'M':  $multiplier=60; break;
+                case 'h':  $multiplier=3600; break;
+                case 'd':  $multiplier=3600*24; break;
+                case 'm':  $multiplier=3600*24*31; break;
+                case 'y':  $multiplier=3600*24*365; break;
+				default: $multiplier=1;
+			}
+
+			$result += $param[1]*$multiplier;
+                        $dp=preg_replace("/^[\-\+]?\d+$param[2]/",'',$dp);
+		} else {
+			return 0;
+		}
+	}
+
+	return $result;
+}
+
+/**
+ * Formats the date using the user's settings as defined in search.html
+ * @param	string	Date
+ * @return	string	Formatted date
+ */
+function format_userdate($date) {
+	$result=0;
+
+	$param = array();
+	if (preg_match('/^(\d+)\/(\d+)\/(\d+)$/',$date,$param)) {
+		$day=$param[1];
+		$mon=$param[2];
+		$year=$param[3];
+
+		$result=mktime(0,0,0,$mon,$day,$year);
+	}
+
+	return $result;
+}
+
+/**
+ * Parses the given text for the words searched and highlight the words, the returns the string
+ * @param	string	Resulting document excerpt
+ * @return	string	Same string but with highlight tags (as defined in search.html)
+ */
+function ParseDocText($text){
+    global $all_words;
+    global $hlbeg, $hlend;
+       
+    $str=$text;
+
+    if (udm_api_version() < 30200) {
+    	for ($i=0; $i<count($all_words); $i+=1) {
+	    $word=$all_words[$i];
+	    $str = preg_replace("/([\s\t\r\n\~\!\@\#\$\%\^\&\*\(\)\-\_\=\+\\\|\{\}\[\]\;\:\'\"\<\>\?\/\,\.]+)($word)/i","\\1$hlbeg\\2$hlend",$str);
+	    $str = preg_replace("/^($word)/i","$hlbeg\\1$hlend",$str);
+    	}
+    } else {
+    	$str = str_replace("\2",$hlbeg,$str);
+    	$str = str_replace("\3",$hlend,$str);
+	while (substr_count($str,$hlbeg) > substr_count($str,$hlend)) {
+	    $str.=$hlend;
+	}
+    }
+
+    return $str;
+}
+
+/**
+ * Parses the global variable $QUERY_STRING
+ */
+function ParseQString() {
+    global $QUERY_STRING;
+    global $ul, $ul_arr;
+    global $tag, $tag_arr;
+    global $cat, $cat_arr;
+    global $lang, $lang_arr;
+    global $type, $type_arr;
+	
+    $pairs = explode("&", $QUERY_STRING);
+    $ul_arr = array();
+    $tag_arr = array();
+    $cat_arr = array();
+    $lang_arr = array();
+    $type_arr = array();
+	
+    for($i=0; $i<count($pairs); $i+=1) {
+	$pairs[$i]=str_replace('+',' ',$pairs[$i]);
+	list($name, $value) = explode("=",$pairs[$i]);
+	if ($name=='ul') {
+	    $ul_arr[]=urldecode($value);
+	    if (!count($ul_arr)) $ul=urldecode($value);
+	} elseif ($name=='tag') {
+	    $tag_arr[]=urldecode($value);
+	    if (!count($tag_arr)) $tag=urldecode($value);
+	} elseif ($name=='cat') {
+	    $cat_arr[]=urldecode($value);
+	    if (!count($cat_arr)) $cat=urldecode($value);
+	} elseif ($name=='lang') {
+	    $lang_arr[]=urldecode($value);
+	    if (!count($lang_arr)) $lang=urldecode($value);
+	} elseif ($name=='type') {
+	    $type_arr[]=urldecode($value);
+	    if (!count($type_arr)) $type=urldecode($value);
+	} else continue;
+    }
+}
+
+?>

+ 21 - 0
plugin/search/server/www/config.inc

@@ -0,0 +1,21 @@
+<?php
+
+// maximal page number to view
+$MAX_NP=1;
+
+// maximum results per page
+$MAX_PS=1000;
+
+// (optional) Enable autowild feature for url limits
+// 'yes' - default value, can be 'yes' or 'no'
+// $auto_wild='yes';
+
+// (optional) Enable language content negotiation
+// 'no' - default value, can be 'yes' or 'no'
+// $lang_content_negotiation='no';
+
+// (optional) Enable language url translation (file.en.ext -> file)
+// 'no' - default value, can be 'yes' or 'no'
+// $lang_url_translation='no';
+
+?>

+ 544 - 0
plugin/search/server/www/init.inc

@@ -0,0 +1,544 @@
+<?php
+
+/**
+ * Initialisation code + library of functions to process to the initialisation in
+ * a varied set of ways.
+ * This script is a modified version that can only be used with the php extension >= 3.2.32
+ * and PHP version 4.2 or higher
+ */
+/**
+ * Faking the register_globals code - very bad thing - should escape all vars
+ */
+if (isset ($HTTP_GET_VARS)) {
+	while (list ($var, $val) = each($HTTP_GET_VARS)) {
+		$$var = $val;
+	}
+}
+if (isset ($HTTP_POST_VARS)) {
+	while (list ($var, $val) = each($HTTP_POST_VARS)) {
+		$$var = $val;
+	}
+}
+if (isset ($HTTP_COOKIE_VARS)) {
+	while (list ($var, $val) = each($HTTP_COOKIE_VARS)) {
+		$$var = $val;
+	}
+}
+if (isset ($HTTP_SERVER_VARS)) {
+	while (list ($var, $val) = each($HTTP_SERVER_VARS)) {
+		$$var = $val;
+	}
+}
+
+$self = $PHP_SELF;
+
+/**
+ * Setting default values for variables that will be used globally
+ */
+if ($ps == "")
+	$ps = 20;
+if ($np == "")
+	$np = 0;
+if ($o == "")
+	$o = 0;
+if ($resultslimit <= 0)
+	$resultslimit = 0;
+
+if ($excerptsize == "")
+	$excerptsize = 256;
+if ($excerptpadding == "")
+	$excerptsize = 40;
+
+if (($dt != 'back') && ($dt != 'er') && ($dt != 'range'))
+	$dt = '';
+if ($dp == "")
+	$dp = 0;
+if (($dx != 0) && ($dx != -1) && ($dx != 1))
+	$dx = 0;
+if ($dy < 1970)
+	$dy = 1970;
+if (($dm < 0) || ($dm > 11))
+	$dm = 0;
+if (($dd <= 0) || ($dd > 31))
+	$dd = "01";
+
+$db = urldecode($db);
+$de = urldecode($de);
+$type = urldecode($type);
+
+$url = urldecode($url);
+
+if ($db == "")
+	$db = '01/01/1970';
+if ($de == "")
+	$de = '31/12/2020';
+
+if ($hlbeg == "")
+	$hlbeg = '<b>';
+if ($hlend == "")
+	$hlend = '</b>';
+
+if ($storedocurl == "")
+	$storedocurl = '/cgi-bin/storedoc.cgi';
+
+if (isset ($q)) {
+	$q = urldecode($q);
+	$have_query_flag = 1;
+} else {
+	$have_query_flag = 0;
+}
+
+$query_orig = $q;
+
+if (isset ($CHARSET_SAVED_QUERY_STRING)) {
+	$q_local = urldecode($CHARSET_SAVED_QUERY_STRING);
+	if (preg_match('/q=([^&]*)\&/', $q_local, $param)) {
+		$q_local = urlencode($param[1]);
+	}
+	elseif (preg_match('/q=(.*)$/', $q_local, $param)) {
+		$q_local = urlencode($param[1]);
+	} else {
+		$q_local = urlencode($q);
+	}
+	$q_string = $CHARSET_SAVED_QUERY_STRING;
+} else {
+	$q_local = urlencode(stripslashes($q));
+	$q_string = $QUERY_STRING;
+}
+
+$db_local = urlencode($db);
+$de_local = urlencode($de);
+$type_local = urlencode($type);
+
+$url_local = urlencode($url);
+
+if (($MAX_NP > 0) && ($np > $MAX_NP))
+	$np = $MAX_NP;
+if (($MAX_PS > 0) && ($ps > $MAX_PS))
+	$ps = $MAX_PS;
+
+/**
+ * Initialisation function. Gets the global variables defined all over and prepares
+ * the udm agent accordingly.
+ * 
+ */
+function init() {
+	global $q, $q_string, $query_orig, $have_query_flag, $have_spell_flag, $auto_wild;
+	global $tag, $tag_arr, $cat, $cat_arr, $np, $ps, $lang, $lang_arr, $wm, $wf, $ul, $m;
+	global $dt, $dp, $dx, $dm, $dd, $dy, $db, $de, $s, $resultslimit;
+	global $trackquery, $localcharset, $browsercharset, $stopwordtable_arr, $stopwordfile_arr;
+	global $minwordlength, $maxwordlength, $phrase, $cache;
+	global $ispelluseprefixes, $crosswords, $ispellmode, $spell_host;
+	global $affix_file, $spell_file, $vardir, $datadir, $sp, $sy;
+	global $dbaddr, $dbmode, $udm_agent, $hlbeg, $hlend, $detectclones;
+	global $phpver, $synonym_arr, $searchd_arr, $ul_arr;
+	global $REMOTE_ADDR, $storedaddr, $type_arr, $type, $groupbysite, $site;
+	global $excerptsize, $excerptpadding, $dateformat, $suggest;
+	global $XMLOutput;
+
+	ParseQString();
+
+	/*
+	   if (preg_match("/^(\d+)\.(\d+)\.(\d+)/",phpversion(),$param)) {
+		$phpver=$param[1];
+	   	if ($param[2] < 9) {
+	   		$phpver .= "0$param[2]";
+	   	} else {
+	   		$phpver .= "$param[2]";
+	   	}
+	        if ($param[3] < 9) {
+	   		$phpver .= "0$param[3]";
+	   	} else {
+	   		$phpver .= "$param[3]";
+	   	}
+	   } else {
+	   	print "Cannot determine php version: <b>".phpversion()."</b>\n";
+	   	exit;
+	   }
+	*/
+	$have_spell_flag = 0;
+
+	$stopwordtable_arr = array ();
+	$stopwordfile_arr = array ();
+	$synonym_arr = array ();
+	$searchd_arr = array ();
+
+	read_template();
+
+	if ($sp == '')
+		$sp = 0;
+	if ($sy == '')
+		$sy = 0;
+
+	$udm_agent = udm_alloc_agent_array($dbaddr);
+	udm_set_agent_param($udm_agent, UDM_PARAM_PAGE_SIZE, $ps);
+	udm_set_agent_param($udm_agent, UDM_PARAM_PAGE_NUM, $np);
+
+	$trackquery = strtolower($trackquery);
+	if ($trackquery == 'yes') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_TRACK_MODE, UDM_ENABLED);
+	} else {
+		udm_set_agent_param($udm_agent, UDM_PARAM_TRACK_MODE, UDM_DISABLED);
+	}
+
+	$cache = strtolower($cache);
+	if ($cache == 'yes') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_CACHE_MODE, UDM_ENABLED);
+	} else {
+		udm_set_agent_param($udm_agent, UDM_PARAM_CACHE_MODE, UDM_DISABLED);
+	}
+
+	$ispelluseprefixes = strtolower($ispelluseprefixes);
+	if ($ispelluseprefixes == 'yes') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_ISPELL_PREFIXES, UDM_ENABLED);
+	} else {
+		udm_set_agent_param($udm_agent, UDM_PARAM_ISPELL_PREFIXES, UDM_DISABLED);
+	}
+
+	$crosswords = strtolower($crosswords);
+	if ($crosswords == 'yes') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_CROSS_WORDS, UDM_ENABLED);
+	} else {
+		udm_set_agent_param($udm_agent, UDM_PARAM_CROSS_WORDS, UDM_DISABLED);
+	}
+
+	if ($localcharset != '') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_CHARSET, $localcharset);
+		if (!udm_check_charset($udm_agent, $localcharset)) {
+			print_template('top');
+			flush();
+			print_error_local("Incorrect localcharset $localcharset");
+		}
+	}
+
+	if ($localcharset == '')
+		udm_set_agent_param($udm_agent, UDM_PARAM_CHARSET, 'utf-8');
+	if ($browsercharset != '') {
+		if (!udm_check_charset($udm_agent, $browsercharset)) {
+			print_template('top');
+			flush();
+			print_error_local("Incorrect browsercharset $browsercharset");
+		}
+		udm_set_agent_param($udm_agent, UDM_PARAM_BROWSER_CHARSET, $browsercharset);
+		if($XMLOutput != 1){
+			header("Content-Type: text/html; charset=$browsercharset");
+		}else{
+			header("Content-Type: text/xml");
+			echo "<?xml version='1.0' encoding=\"$browsercharset\" ?>\n";
+		}
+	} else {
+		udm_set_agent_param($udm_agent, UDM_PARAM_BROWSER_CHARSET, 'utf-8');
+		if($XMLOutput != 1){
+			header("Content-Type: text/html; charset=utf-8");
+		}else{
+			header("Content-Type: text/xml");
+			echo "<?xml version='1.0' encoding=\"utf-8\" ?>\n";
+		}
+	}
+	if ($hlbeg == '')
+		$hlbeg = '<font color="000088"><b>';
+	udm_set_agent_param($udm_agent, UDM_PARAM_HLBEG, $hlbeg);
+
+	if ($hlend == '')
+		$hlend = '</b></font>';
+	udm_set_agent_param($udm_agent, UDM_PARAM_HLEND, $hlend);
+
+	for ($i = 0; $i < count($stopwordfile_arr); $i += 1) {
+		if ($stopwordfile_arr[$i] != '') {
+			udm_set_agent_param($udm_agent, UDM_PARAM_STOPFILE, $stopwordfile_arr[$i]);
+		}
+	}
+
+	if ($sy) {
+		for ($i = 0; $i < count($synonym_arr); $i += 1) {
+			if ($synonym_arr[$i] != '') {
+				udm_set_agent_param($udm_agent, UDM_PARAM_SYNONYM, $synonym_arr[$i]);
+			}
+		}
+	}
+
+	udm_set_agent_param($udm_agent, UDM_PARAM_QSTRING, $q_string);
+	udm_set_agent_param($udm_agent, UDM_PARAM_REMOTE_ADDR, $REMOTE_ADDR);
+
+	if ($have_query_flag)
+		udm_set_agent_param($udm_agent, UDM_PARAM_QUERY, $query_orig);
+	if ($storedaddr != '')
+		udm_set_agent_param($udm_agent, UDM_PARAM_STORED, $storedaddr);
+
+	$groupbysite = strtolower($groupbysite);
+	if ($groupbysite == 'yes') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_GROUPBYSITE, UDM_ENABLED);
+	} else {
+		udm_set_agent_param($udm_agent, UDM_PARAM_GROUPBYSITE, UDM_DISABLED);
+	}
+	if ($site)
+		udm_set_agent_param($udm_agent, UDM_PARAM_SITEID, $site);
+	$detectclones = strtolower($detectclones);
+	if ($detectclones == 'yes') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_DETECT_CLONES, UDM_ENABLED);
+	} else {
+		udm_set_agent_param($udm_agent, UDM_PARAM_DETECT_CLONES, UDM_DISABLED);
+	}
+
+	if ($m == 'any') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_SEARCH_MODE, UDM_MODE_ANY);
+	}
+	elseif ($m == 'all') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_SEARCH_MODE, UDM_MODE_ALL);
+	}
+	elseif ($m == 'bool') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_SEARCH_MODE, UDM_MODE_BOOL);
+	}
+	elseif ($m == 'phrase') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_SEARCH_MODE, UDM_MODE_PHRASE);
+	} else {
+		udm_set_agent_param($udm_agent, UDM_PARAM_SEARCH_MODE, UDM_MODE_ALL);
+	}
+
+	if ($wm == 'wrd') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_WORD_MATCH, UDM_MATCH_WORD);
+	}
+	elseif ($wm == 'beg') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_WORD_MATCH, UDM_MATCH_BEGIN);
+	}
+	elseif ($wm == 'end') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_WORD_MATCH, UDM_MATCH_END);
+	}
+	elseif ($wm == 'sub') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_WORD_MATCH, UDM_MATCH_SUBSTR);
+	} else {
+		udm_set_agent_param($udm_agent, UDM_PARAM_WORD_MATCH, UDM_MATCH_WORD);
+	}
+
+	if ($minwordlength > 0) {
+		udm_set_agent_param($udm_agent, UDM_PARAM_MIN_WORD_LEN, $minwordlength);
+	} else {
+		udm_set_agent_param($udm_agent, UDM_PARAM_MIN_WORD_LEN, 1);
+	}
+
+	if ($maxwordlength > 0) {
+		udm_set_agent_param($udm_agent, UDM_PARAM_MAX_WORD_LEN, $maxwordlength);
+	} else {
+		udm_set_agent_param($udm_agent, UDM_PARAM_MAX_WORD_LEN, 32);
+	}
+
+	if ($vardir != '')
+		udm_set_agent_param($udm_agent, UDM_PARAM_VARDIR, $vardir);
+	if ($datadir != '')
+		udm_set_agent_param($udm_agent, UDM_PARAM_VARDIR, $datadir);
+
+	if ($wf != '') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_WEIGHT_FACTOR, $wf);
+	}
+
+	for ($i = 0; $i < count($ul_arr); $i += 1) {
+		$temp_ul = $ul_arr[$i];
+		if ($temp_ul != '') {
+			$auto_wild = strtolower($auto_wild);
+			if (($auto_wild == 'yes') || ($auto_wild == '')) {
+				if ((substr($temp_ul, 0, 7) == 'http://') || (substr($temp_ul, 0, 8) == 'https://') || (substr($temp_ul, 0, 7) == 'news://') || (substr($temp_ul, 0, 6) == 'ftp://')) {
+					udm_add_search_limit($udm_agent, UDM_LIMIT_URL, "$temp_ul%");
+				} else {
+					udm_add_search_limit($udm_agent, UDM_LIMIT_URL, "%$temp_ul%");
+				}
+			} else {
+				udm_add_search_limit($udm_agent, UDM_LIMIT_URL, $temp_ul);
+			}
+		}
+	}
+
+	for ($i = 0; $i < count($tag_arr); $i += 1) {
+		$temp_tag = $tag_arr[$i];
+		if ($temp_tag != '')
+			udm_add_search_limit($udm_agent, UDM_LIMIT_TAG, $temp_tag);
+	}
+
+	for ($i = 0; $i < count($type_arr); $i += 1) {
+		$temp_type = $type_arr[$i];
+		if ($temp_type != '')
+			udm_add_search_limit($udm_agent, UDM_LIMIT_TYPE, $temp_type);
+	}
+
+	for ($i = 0; $i < count($cat_arr); $i += 1) {
+		$temp_cat = $cat_arr[$i];
+		if ($temp_cat != '')
+			udm_add_search_limit($udm_agent, UDM_LIMIT_CAT, $temp_cat);
+	}
+
+	for ($i = 0; $i < count($lang_arr); $i += 1) {
+		$temp_lang = $lang_arr[$i];
+		if ($temp_lang != '')
+			udm_add_search_limit($udm_agent, UDM_LIMIT_LANG, $temp_lang);
+	}
+
+	if (function_exists('udm_set_agent_param_ex')) {
+		if ($excerptsize > 0)
+			udm_set_agent_param_ex($udm_agent, 'ExcerptSize', $excerptsize);
+		if ($excerptpadding > 0)
+			udm_set_agent_param_ex($udm_agent, 'ExcerptPadding', $excerptpadding);
+		if ($dateformat != '')
+			udm_set_agent_param_ex($udm_agent, 'DateFormat', $dateformat);
+
+		if ($s != '')
+			udm_set_agent_param_ex($udm_agent, 's', $s);
+		if ($resultslimit > 0)
+			udm_set_agent_param_ex($udm_agent, 'resultslimit', $resultslimit);
+
+		if (($dt == 'back') || ($dt == 'er') || ($dt == 'range')) {
+			udm_set_agent_param_ex($udm_agent, 'dt', $dt);
+			udm_set_agent_param_ex($udm_agent, 'dx', $dx);
+			udm_set_agent_param_ex($udm_agent, 'dm', $dm);
+			udm_set_agent_param_ex($udm_agent, 'dy', $dy);
+			udm_set_agent_param_ex($udm_agent, 'dd', $dd);
+			udm_set_agent_param_ex($udm_agent, 'dp', $dp);
+			udm_set_agent_param_ex($udm_agent, 'db', $db);
+			udm_set_agent_param_ex($udm_agent, 'de', $de);
+		}
+
+		$suggest = strtolower($suggest);
+		if ($suggest == 'yes')
+			udm_set_agent_param_ex($udm_agent, 'suggest', 'yes');
+	}
+
+	if (($dt == 'back') && ($dp != '0')) {
+		$recent_time = format_dp($dp);
+		if ($recent_time != 0) {
+			$dl = time() - $recent_time;
+			udm_add_search_limit($udm_agent, UDM_LIMIT_DATE, ">$dl");
+		}
+	}
+	elseif ($dt == 'er') {
+		$recent_time = mktime(0, 0, 0, ($dm +1), $dd, $dy);
+		if ($dx == -1) {
+			udm_add_search_limit($udm_agent, UDM_LIMIT_DATE, "<$recent_time");
+		}
+		elseif ($dx == 1) {
+			udm_add_search_limit($udm_agent, UDM_LIMIT_DATE, ">$recent_time");
+		}
+	}
+	elseif ($dt == 'range') {
+		$begin_time = format_userdate($db);
+		if ($begin_time)
+			udm_add_search_limit($udm_agent, UDM_LIMIT_DATE, ">$begin_time");
+
+		$end_time = format_userdate($de);
+		if ($end_time)
+			udm_add_search_limit($udm_agent, UDM_LIMIT_DATE, "<$end_time");
+	}
+
+	print_template('top');
+	flush();
+
+	$ispellmode = strtolower($ispellmode);
+	if ($ispellmode == 'db') {
+		if (!udm_load_ispell_data($udm_agent, UDM_ISPELL_TYPE_DB, '', '', 1)) {
+			print_error_local(udm_error($udm_agent));
+		} else
+			$have_spell_flag = 1;
+	}
+	elseif ($ispellmode == 'server') {
+		if (!udm_load_ispell_data($udm_agent, UDM_ISPELL_TYPE_SERVER, $spell_host, '', 1)) {
+			print_error_local("Error loading ispell data from server $spell_host");
+		} else
+			$have_spell_flag = 1;
+	}
+	elseif (($ispellmode == 'text') && ($sp)) {
+		reset($affix_file);
+		while (list ($t_lang, $file) = each($affix_file)) {
+			$param = array();
+			if (preg_match("/(.+)\;(.+)/", $file, $param)) {
+				$t_charset = trim($param[1]);
+				$t_file = trim($param[2]);
+				if (!udm_load_ispell_data($udm_agent, UDM_ISPELL_TYPE_AFFIX, $t_lang, $t_charset, $t_file, 0)) {
+					print_error_local("Error loading ispell data from file");
+				} else
+					$have_spell_flag = 1;
+			}
+
+			$temp = $spell_file[$t_lang];
+			for ($i = 0; $i < count($temp); $i += 1) {
+				if (preg_match("/(.+)\;(.+)/", $temp[$i], $param)) {
+					$t_charset = trim($param[1]);
+					$t_file = trim($param[2]);
+					if (!udm_load_ispell_data($udm_agent, UDM_ISPELL_TYPE_SPELL, $t_lang, $t_charset, $t_file, 1)) {
+						print_error_local("Error loading ispell data from file");
+					} else
+						$have_spell_flag = 1;
+				}
+			}
+		}
+	}
+
+	udm_parse_query_string($udm_agent, $q_string);
+}
+
+/**
+ * Some variation of the init function?
+ * 
+ */
+function init_cc() {
+	global $q, $q_string, $query_orig, $have_query_flag, $have_spell_flag, $auto_wild;
+	global $tag, $tag_arr, $cat, $cat_arr, $np, $ps, $lang, $lang_arr, $wm, $wf, $ul, $m;
+	global $dt, $dp, $dx, $dm, $dd, $dy, $db, $de, $s, $resultslimit;
+	global $trackquery, $localcharset, $browsercharset, $stopwordtable_arr, $stopwordfile_arr;
+	global $minwordlength, $maxwordlength, $phrase, $cache;
+	global $ispelluseprefixes, $crosswords, $ispellmode, $spell_host;
+	global $affix_file, $spell_file, $vardir, $datadir, $sp, $sy;
+	global $dbaddr, $dbmode, $udm_agent, $hlbeg, $hlend, $detectclones;
+	global $phpver, $synonym_arr, $searchd_arr, $ul_arr;
+	global $REMOTE_ADDR, $storedaddr, $type_arr, $type, $groupbysite, $site;
+	global $excerptsize, $excerptpadding, $dateformat, $suggest;
+
+	//parse the $QUERY_STRING global variable and puts pieces into corresponding arrays
+	ParseQString();
+
+	//read the template file
+	read_template();
+
+	$udm_agent = udm_alloc_agent_array($dbaddr);
+
+	if ($localcharset != '') {
+		udm_set_agent_param($udm_agent, UDM_PARAM_CHARSET, $localcharset);
+		if (!udm_check_charset($udm_agent, $localcharset)) {
+			print_template('top');
+			flush();
+			print_error_local("Incorrect localcharset $localcharset");
+		}
+	}
+
+	if ($localcharset == '')
+		udm_set_agent_param($udm_agent, UDM_PARAM_CHARSET, 'utf-8');
+	if ($browsercharset != '') {
+		if (!udm_check_charset($udm_agent, $browsercharset)) {
+			print_template('top');
+			flush();
+			print_error_local("Incorrect browsercharset $browsercharset");
+		}
+		udm_set_agent_param($udm_agent, UDM_PARAM_BROWSER_CHARSET, $browsercharset);
+		header("Content-Type: text/html; charset=$browsercharset");
+	} else {
+		udm_set_agent_param($udm_agent, UDM_PARAM_BROWSER_CHARSET, 'utf-8');
+		header("Content-Type: text/html; charset=utf-8");
+	}
+	if ($hlbeg == '')
+		$hlbeg = '<font color="000088"><b>';
+	udm_set_agent_param($udm_agent, UDM_PARAM_HLBEG, $hlbeg);
+
+	if ($hlend == '')
+		$hlend = '</b></font>';
+	udm_set_agent_param($udm_agent, UDM_PARAM_HLEND, $hlend);
+
+	udm_set_agent_param($udm_agent, UDM_PARAM_QSTRING, $q_string);
+	udm_set_agent_param($udm_agent, UDM_PARAM_REMOTE_ADDR, $REMOTE_ADDR);
+
+	if ($have_query_flag)
+		udm_set_agent_param($udm_agent, UDM_PARAM_QUERY, $query_orig);
+
+	if (function_exists('udm_set_agent_param_ex')) {
+		if ($dateformat != '')
+			udm_set_agent_param_ex($udm_agent, 'DateFormat', $dateformat);
+	}
+
+	udm_parse_query_string($udm_agent, $q_string);
+}
+?>

+ 269 - 0
plugin/search/server/www/search.php

@@ -0,0 +1,269 @@
+<?php
+
+/*   mnoGoSearch-php v.3.2.10
+ *   for mnoGoSearch ( formely known as UdmSearch ) free web search engine
+ *   (C) 2001 by Sergey Kartashoff <gluke@mail.ru>,
+ *               mnoGoSearch Developers Team <devel@mnogosearch.org>
+ */
+
+if (!extension_loaded('mnogosearch')) {
+	print "<b>This script requires PHP4.3.0+ with mnoGoSearch extension</b>";
+	exit;
+}
+
+define("UDM_ENABLED", 1);
+define("UDM_DISABLED", 0);
+
+require ('./config.inc');
+require ('./common.inc');
+require ('./template.inc');
+
+require ('./init.inc');
+//api_block_anonymous_users();
+//require ('filter_user.functions.php');
+
+if ($lang_content_negotiation == 'yes') {
+	// path to template file ($lang_content_negotiation = 'yes')
+	// please refer to docs on this feature before using it.
+	$template_file = preg_replace("/\.php\.*/", ".xml.php", basename($SCRIPT_FILENAME));
+	$template_file = "./".$template_file;
+} else {
+	// path to template file ($lang_content_negotiation = 'no')
+	$template_file = './search.xml.php';
+}
+
+// -----------------------------------------------
+//  M A I N 
+// -----------------------------------------------
+
+if (!$cc) {
+	$XMLOutput = 1;
+	init();
+
+	if (!$have_query_flag) {
+		print_template('bottom');
+		return;
+	}
+	elseif ($have_query_flag && ($q == '')) {
+		print_template('noquery');
+		print_template('bottom');
+		return;
+	}
+
+	$res = udm_find($udm_agent, $q);
+
+	if (!$res) {
+		print_error_local(udm_error($udm_agent));
+	} else {
+		$found = udm_get_res_param($res, UDM_PARAM_FOUND);
+		$rows = udm_get_res_param($res, UDM_PARAM_NUM_ROWS);
+		//YW commented out because broke everything
+		//if (udm_api_version() >= 30231) {
+		//    $wordinfo=Udm_Get_Agent_Param_Ex($udm_agent,'W');
+		//} else {
+		$wordinfo = udm_get_res_param($res, UDM_PARAM_WORDINFO_ALL);
+		//}
+		$searchtime = udm_get_res_param($res, UDM_PARAM_SEARCHTIME);
+		$first_doc = udm_get_res_param($res, UDM_PARAM_FIRST_DOC);
+		$last_doc = udm_get_res_param($res, UDM_PARAM_LAST_DOC);
+
+		if (!$found) {
+			$ws = '';
+			if ((udm_api_version() >= 30233) && ($suggest == 'yes')) {
+				$ws = udm_get_agent_param_ex($udm_agent, 'WS');
+			}
+
+			print_template('notfound');
+			print_template('bottom');
+			return;
+		}
+
+		$from = IntVal($np) * IntVal($ps);
+		$to = IntVal($np +1) * IntVal($ps);
+
+		if ($to > $found)
+			$to = $found;
+		if (($from + $ps) < $found)
+			$isnext = 1;
+		$nav = make_nav($query_orig);
+
+		print_template('restop');
+
+		$global_doc_res = $res;
+		$my_skip = 0;
+
+		for ($i = 0; $i < $rows; $i += 1) {
+			$excerpt_flag = 0;
+			$clonestr = '';
+
+			$rec_id = udm_get_res_field($res, $i, UDM_FIELD_URLID);
+
+			$global_res_position = $i;
+
+			if (udm_api_version() >= 30207) {
+				$origin_id = udm_get_res_field($res, $i, UDM_FIELD_ORIGINID);
+				if ($origin_id)
+					continue;
+				else {
+					for ($j = 0; $j < $rows; $j += 1) {
+						$cl_origin_id = udm_get_res_field($res, $j, UDM_FIELD_ORIGINID);
+						if (($cl_origin_id) && ($cl_origin_id == $rec_id)) {
+							$url = udm_get_res_field($res, $j, UDM_FIELD_URL);
+							//YW
+							
+							/*if (!access_check($url)) {
+								$my_skip ++;
+								continue;
+							}*/
+							//YW
+							$contype = udm_get_res_field($res, $j, UDM_FIELD_CONTENT);
+							$docsize = udm_get_res_field($res, $j, UDM_FIELD_SIZE);
+							$lastmod = format_lastmod(udm_get_res_field($res, $j, UDM_FIELD_MODIFIED));
+							if (udm_api_version() >= 30207) {
+								$pop_rank = udm_get_res_field($res, $i, UDM_FIELD_POP_RANK);
+							} else
+								$pop_rank = '';
+							$clonestr .= print_template('clone', 0)."\n";
+						}
+					}
+				}
+			}
+
+			if (udm_api_version() >= 30204) {
+				$excerpt_flag = udm_make_excerpt($udm_agent, $res, $i);
+			}
+			//YW
+			/*
+			$ndoc = udm_get_res_field($res, $i, UDM_FIELD_ORDER) - $my_skip;
+			*/
+			//YW
+			$rating = udm_get_res_field($res, $i, UDM_FIELD_RATING);
+			$url = udm_get_res_field($res, $i, UDM_FIELD_URL);
+			//YW
+			/*
+			if (!access_check($url)) {
+				$my_skip ++;
+				continue;
+			}*/
+			//YW
+
+			$contype = udm_get_res_field($res, $i, UDM_FIELD_CONTENT);
+			$docsize = udm_get_res_field($res, $i, UDM_FIELD_SIZE);
+			$lastmod = format_lastmod(udm_get_res_field($res, $i, UDM_FIELD_MODIFIED));
+
+			$title = udm_get_res_field($res, $i, UDM_FIELD_TITLE);
+			$title = ($title) ? htmlspecialchars($title) : basename($url);
+
+			$title = ParseDocText($title);
+			$text = ParseDocText(htmlspecialchars(udm_get_res_field($res, $i, UDM_FIELD_TEXT)));
+			//$text=ParseDocText(htmlspecialchars(udm_get_res_field_ex($res,$i,"Body")));
+			$keyw = ParseDocText(htmlspecialchars(udm_get_res_field($res, $i, UDM_FIELD_KEYWORDS)));
+			$desc = ParseDocText(htmlspecialchars(udm_get_res_field($res, $i, UDM_FIELD_DESC)));
+
+			$crc = udm_get_res_field($res, $i, UDM_FIELD_CRC);
+
+			if (udm_api_version() >= 30203) {
+				$doclang = udm_get_res_field($res, $i, UDM_FIELD_LANG);
+				$doccharset = udm_get_res_field($res, $i, UDM_FIELD_CHARSET);
+			}
+
+			if ($phpver >= 40006) {
+				$category = udm_get_res_field($res, $i, UDM_FIELD_CATEGORY);
+			} else {
+				$category = '';
+			}
+
+			reset($alias_arr);
+			$save_url = $url;
+			while (list ($t_alias, $t_url) = each($alias_arr)) {
+				$url = str_replace($t_alias, $t_url, $url);
+			}
+
+			if (udm_api_version() <= 30223) {
+				if (udm_api_version() >= 30204) {
+					if ($excerpt_flag) {
+						if (udm_api_version() >= 30216) {
+							if (udm_get_res_field_ex($res, $i, "CachedCopy") != '') {
+								$stored_href = "$self?cc=1"."&url=".urlencode($save_url)."&q=".urlencode($query_orig);
+							}
+						}
+						elseif (udm_api_version() >= 30211) {
+							$stored_href = "$storedocurl?rec_id=".udm_hash32($udm_agent, $save_url)."&DM=".urlencode($lastmod)."&DS=$docsize"."&L=$doclang"."&CS=$doccharset"."&DU=".urlencode($save_url)."&CT=".urlencode($contype)."&q=".urlencode($query_orig);
+						} else {
+							$stored_href = "$storedocurl?rec_id=".udm_CRC32($udm_agent, $save_url)."&DM=".urlencode($lastmod)."&DS=$docsize"."&L=$doclang"."&CS=$doccharset"."&DU=".urlencode($save_url)."&CT=".urlencode($contype)."&q=".urlencode($query_orig);
+						}
+						if ($stored_href != '')
+							$storedstr = print_template('stored', 0);
+					} else
+						$storedstr = '';
+				} else
+					$storedstr = '';
+			} else {
+				if (udm_get_res_field_ex($res, $i, "CachedCopy") != '') {
+					if (udm_get_res_field_ex($res, $i, "dbnum") == '') {
+						$stored_href = "$self?cc=1"."&url=".urlencode($save_url)."&q=".urlencode($query_orig);
+					} else {
+						$stored_href = "$self?cc=1"."&dbnum=".udm_get_res_field_ex($res, $i, "dbnum")."&url=".urlencode($save_url)."&q=".urlencode($query_orig);
+					}
+					$storedstr = print_template('stored', 0);
+				}
+			}
+
+			$sitelimitstr = $persite = '';
+			if ((udm_api_version() >= 30207) && ($groupbysite == 'yes')) {
+				if (!$site) {
+					$sitelimit_href = "$PHP_SELF?$QUERY_STRING";
+					$sitelimit_href = preg_replace("/\&np=\d*/", '', $sitelimit_href);
+					$sitelimit_href .= "&np=0&site=".udm_get_res_field($res, $i, UDM_FIELD_SITEID);
+					$persite = udm_get_res_field_ex($res, $i, "PerSite");
+					$sitelimitstr = print_template('site_limit', 0);
+				}
+			}
+
+			if (udm_api_version() >= 30207) {
+				$pop_rank = udm_get_res_field($res, $i, UDM_FIELD_POP_RANK);
+			} else
+				$pop_rank = '';
+
+			if ((substr($url, 0, 6) == "ftp://") && ($templates['ftpres'][0] != '')) {
+				print_template('ftpres');
+			}
+			elseif (((substr($url, 0, 7) == "http://") || (substr($url, 0, 8) == "https://")) && ($templates['httpres'][0] != '')) {
+				print_template('httpres');
+			} else {
+				print_template('res');
+			}
+		}
+		$global_doc_res = '';
+
+		print_template('resbot');
+		print_template('bottom');
+
+		// Free result
+		udm_free_res($res);
+	}
+} else {
+	/* show cached copy */
+	init_cc();
+	$res = udm_store_doc_cgi($udm_agent);
+
+	$id = udm_get_agent_param_ex($udm_agent, 'ID');
+	$last_modified = udm_get_agent_param_ex($udm_agent, 'Last-Modified');
+	$content = udm_get_agent_param_ex($udm_agent, 'Content-Type');
+	$length = udm_get_agent_param_ex($udm_agent, 'Content-Length');
+	$charset = udm_get_agent_param_ex($udm_agent, 'Charset');
+
+	Header("Content-Type: text/html; charset=$charset");
+
+	print_template('storedoc_top');
+
+	if ($res) {
+		$document = ParseDocText(udm_get_agent_param_ex($udm_agent, 'document'));
+		print_template('storedoc');
+	}
+
+	print_template('storedoc_bottom');
+}
+
+udm_free_agent($udm_agent);
+?>

+ 383 - 0
plugin/search/server/www/search.xml.php

@@ -0,0 +1,383 @@
+<?php
+if(preg_match('/.*search\.htm/',$_SERVER['PHP_SELF'])){
+  header('location:searchit.php');
+}
+?>
+<!--
+
+    This is default template file for mnoGoSearch 3.2
+    (C) 1999-2002, mnoGoSearch developers team <devel@mnogosearch.org>
+
+    Please rename to search.htm and edit as desired.
+    See doc/README.templates for detailed information.
+    You may want to keep the original file for future reference.
+
+    WARNING: Use proper chmod to protect your passwords!
+-->
+
+<!--variables
+# Database parameters are to be used with SQL backend
+# and do not matter for built-in text files support
+# Format (for mnogo-3.2.4 and below): <DBType>:[//[DBUser[:DBPass]@]DBHost[:DBPort]]/DBName/
+# Format (for mnogo-3.2.5+): <DBType>:[//[DBUser[:DBPass]@]DBHost[:DBPort]]/DBName/[?dbmode=mode]
+DBAddr  mysql://db_user:db_pass@db_host/db_name/?dbmode=single
+
+# Uncomment this line to enable search result cache
+#Cache yes
+
+# Uncomment this line if you want to detect and show clones
+#DetectClones yes
+
+# Use proper local and browser charsets
+# Examples:
+
+LocalCharset	iso-8859-1
+BrowserCharset	iso-8859-1
+
+#LocalCharset	utf-8
+#BrowserCharset	utf-8
+
+#LocalCharset   koi8-r
+#BrowserCharset koi8-r
+
+# For cache mode and built-in database 
+# you may choose alternative working directory
+#VarDir /usr/local/mnogosearch/var
+
+# Load stopwords file.  File name is either absolute
+# or relative to /etc directory of mnoGoSearch installation.
+#
+#StopwordFile stopwords/en.sl
+#StopwordFile stopwords/ru.sl
+#
+
+#IspellUsePrefixes yes/no
+
+# a newer mnogosearch-3.2.x ispell affix commands
+#Affix en us-ascii /opt/udm/ispell/en.aff
+#Affix ru koi8-r /opt/udm/ispell/ru.aff
+#Spell en us-ascii /opt/udm/ispell/en.dict
+#Spell ru koi8-r /opt/udm/ispell/ru.dict
+
+# Word lengths
+MinWordLength 1
+MaxWordLength 32
+
+#
+# How to hilight searched words.
+#
+#HlBeg	<font color="000088"><b>
+#HlEnd	</b></font>
+HlBeg <hl> 
+HlEnd </hl>
+
+# Load synonyms file.  File name is either absolute
+# or relative to /etc directory of mnoGoSearch installation.
+#
+#Synonym /opt/udm/synonym/english.syn
+#Synonym /opt/udm/synonym/russian.syn
+#Synonym /opt/udm/synonym/francais.syn
+
+#Alias <find-prefix> <replace-prefix>
+#Alias http://localhost/ http://server.domain/
+
+# Grouping results by site (requires mnogosearch-3.2.7+)
+# GroupBySite yes
+
+# Uncoment this line to change default maximal excerpt size. Default value is 256
+# (requires mnogosearch-3.2.16+)
+ExcerptSize 512
+#                                                                               
+
+# Uncomment this line to change number of characters before and after search words
+# in excerpts. Default value is 40. 
+# (requires mnogosearch-3.2.16+)
+ExcerptPadding 128
+#
+                                                                                
+# Uncomment this line to change Last-Modified format output                     
+# Use strftime function meta variables                                          
+#DateFormat %d %b %Y %X %Z                                                      
+
+# Uncomment to limit maximum number of results
+ResultsLimit 1000
+
+# Uncomment this line if you want to generate misspelled
+# search word suggestions. You need to run "indexer -Ewrdstat"
+# before using this feature.
+#
+#Suggest yes
+
+#-------------------------------------------------
+# obsolete (mnogosearch-3.1.x or 3.2 old versions specific parameters)
+
+# Choose storage mode (for mnogosearch-3.2.4 or earlier):
+#DBMode  single
+#DBMode  multi
+#DBMode  crc
+#DBMode  crc-multi
+#DBMode  cache
+
+# Uncomment this line to enable query tracking facility
+# Use trackquery parameter in DBAddr command if using with mnogosearch-3.2.13+
+#TrackQuery yes
+
+#IspellMode text
+
+# Uncomment if index was built with phrase support
+#Phrase yes
+
+# Load stopwords from SQL table
+#StopwordTable stopword
+
+# old mnogosearch-3.1.x ispell affix commands
+#Affix en /opt/udm/ispell/en.aff
+#Affix ru /opt/udm/ispell/ru.aff
+#Spell en /opt/udm/ispell/en.dict
+#Spell ru /opt/udm/ispell/ru.dict
+
+# Searchd address - only for mnogosearch - 3.2.3 or earlier ! 
+#SearchdAddr localhost
+
+# Uncomment this line to enable document presence check at stored
+# (not used with mnogosearch-3.2.16+)
+#StoredAddr localhost
+
+# URL basis for storedoc.cgi
+# (not used with mnogosearch-3.2.16+)
+#StoredocURL     /cgi-bin/storedoc.cgi
+
+-->
+
+<!--top-->
+<results>
+<!--/top-->
+
+<!--stored-->
+<cached>
+	<cached_href>$(storef_href)</cached_href>
+</cached>
+<!--/stored-->
+
+<!--site_limit-->
+<more_results_from_this_site>$(sitelimit_href)</more_results_from_this_site>
+<limit_per_site>$(PerSite)</limit_per_site>
+<!--/site_limit-->
+
+<!--clone-->
+<clone>
+	<clone_du>$DU</clone_du>
+	<clone_dc>$DC</clone_dc>
+	<clone_dm>$DM</clone_dm>
+	<clone_ds_byte>$DS</clone_ds_byte>
+</clone>
+<!--/clone-->
+
+<!--restop-->
+<search_info>$W</search_info>
+<search_term>$(WS)</search_term>
+<query>$Q</query>
+<num_found>$t</num_found>
+<search_time>$SearchTime</search_time>
+<!--/restop-->
+
+<!--res-->
+<result>
+	<result_dn>$DN</result_dn>
+	<result_du>$DU</result_du>
+	<result_dt>$DT</result_dt>
+	<result_dr>$DR</result_dr>
+	<result_pop_rank>$(Pop_Rank)</result_pop_rank>
+	<result_de>$DE</result_de>
+	<result_dx>$DX</result_dx>
+	<result_dud>$DUD</result_dud>
+	<result_dc>($DC)</result_dc>
+	<result_dm>$DM</result_dm>
+	<result_ds>$DS</result_ds>
+	<result_cl>$CL</result_cl>
+	<result_stored>$(STORED)</result_stored>
+	<result_sitelimit>$(SITELIMIT)</result_sitelimit>
+</result>	
+<!--/res-->
+
+<!--ftpres-->
+<result>
+	<result_dn>$DN</result_dn>
+	<result_du>$DU</result_du>
+	<result_dt>$DT</result_dt>
+	<result_dr>$DR</result_dr>
+	<result_pop_rank>$(Pop_Rank)</result_pop_rank>
+	<result_de>$DE</result_de>
+	<result_dx>$DX</result_dx>
+	<result_dud>$DUD</result_dud>
+	<result_dc>($DC)</result_dc>
+	<result_dm>$DM</result_dm>
+	<result_ds>$DS</result_ds>
+	<result_cl>$CL</result_cl>
+	<result_stored>$(STORED)</result_stored>
+	<result_sitelimit>$(SITELIMIT)</result_sitelimit>
+</result>	
+<!--/ftpres-->
+
+<!--resbot-->
+<result_v>$V</result_v>
+<!--/resbot-->
+
+
+
+
+
+<!--restop-->
+<search_info>$W</search_info>
+<search_term>$(WS)</search_term>
+<query>$Q</query>
+<num_found>$t</num_found>
+<search_time>$SearchTime</search_time>
+<!--/restop-->
+<!--res-->
+<result>
+	<result_dn>$DN</result_dn>
+	<result_du>$DU</result_du>
+	<result_dt>$DT</result_dt>
+	<result_dr>$DR</result_dr>
+	<result_pop_rank>$(Pop_Rank)</result_pop_rank>
+	<result_de>$DE</result_de>
+	<result_dx>$DX</result_dx>
+	<result_dud>$DUD</result_dud>
+	<result_dc>($DC)</result_dc>
+	<result_dm>$DM</result_dm>
+	<result_ds>$DS</result_ds>
+	<result_cl>$CL</result_cl>
+	<result_stored>$(STORED)</result_stored>
+	<result_sitelimit>$(SITELIMIT)</result_sitelimit>
+</result>	
+<!--/res-->
+<!--resbot-->
+<result_v>$V</result_v>
+<!--/resbot-->
+
+
+
+<!--restop-->
+<search_info>$W</search_info>
+<search_term>$(WS)</search_term>
+<query>$Q</query>
+<num_found>$t</num_found>
+<search_time>$SearchTime</search_time>
+<!--/restop-->
+<!--res-->
+<result>
+	<result_dn>$DN</result_dn>
+	<result_du>$DU</result_du>
+	<result_dt>$DT</result_dt>
+	<result_dr>$DR</result_dr>
+	<result_pop_rank>$(Pop_Rank)</result_pop_rank>
+	<result_de>$DE</result_de>
+	<result_dx>$DX</result_dx>
+	<result_dud>$DUD</result_dud>
+	<result_dc>($DC)</result_dc>
+	<result_dm>$DM</result_dm>
+	<result_ds>$DS</result_ds>
+	<result_cl>$CL</result_cl>
+	<result_stored>$(STORED)</result_stored>
+	<result_sitelimit>$(SITELIMIT)</result_sitelimit>
+</result>	
+<!--/res-->
+<!--resbot-->
+<result_v>$V</result_v>
+<!--/resbot-->
+
+
+
+
+<!--clone-->
+<clone>
+	<clone_du>$DU</clone_du>
+	<clone_dud>$DUD</clone_dud>
+	<clone_dc>$DC</clone_dc>
+	<clone_dm>$DM</clone_dm>
+	<clone_ds_byte>$DS</clone_ds_byte>
+</clone>
+<!--/clone-->
+
+<!--navigator-->
+<navigator>
+	<navigator_nl>$NL</navigator_nl>
+	<navigator_nb>$NB</navigator_nb>
+	<navigator_nr>$NR</navigator_nr>
+</navigator>
+<!--/navigator-->
+
+<!--navleft-->
+<navleft>
+	<navleft_nh>$NH</navleft_nh>
+</navleft>
+<!--/navleft-->
+
+<!--navleft_nop-->
+<!--/navleft_nop-->
+
+<!--navbar1-->
+<navbar1>
+	<navbar1_nh>$NH</navbar1_nh>
+	<navbar1_np>$NP</navbar1_np>
+</navbar1>
+<!--/navbar1-->
+
+<!--navbar0-->
+<navbar0>
+	<navbar0_np>$NP</navbar0_np>
+</navbar0>
+<!--/navbar0-->
+
+<!--navright-->
+<navright>
+	<navright_nh>$NH</navright_nh>
+</navright>
+<!--/navright-->
+
+<!--navright_nop-->
+<!--/navright_nop-->
+
+
+<!--notfound-->
+<notfound>
+	<notfound_search_time>$SearchTime</notfound_search_time>
+</notfound>
+<!--/notfound-->
+
+<!--error-->
+<error>
+	<error_msg>$E</error_msg>
+</error>
+<!--/error-->
+
+
+<!--noquery-->
+<noquery>
+	<noquery_msg>No search query</noquery_msg>
+</noquery>
+<!--/noquery-->
+
+
+<!--bottom-->
+</results>
+<!--/bottom-->
+
+<!--storedoc_top-->
+<storedoc>
+	<storedoc_url>$(URL)</storedoc_url>
+	<storedoc_document_id>$(ID)</storedoc_document_id>
+	<storedoc_last_modified>$(Last-Modified)</storedoc_last_modified>
+	<storedoc_language>$(Content-Language)</storedoc_language>
+	<storedoc_charset>$(Charset)</storedoc_charset>
+	<storedoc_size_bytes>$(Content_Length)</storedoc_size_bytes>
+<!--/storedoc_top-->
+
+<!--storedoc-->
+	<storedoc_content>$(document)</storedoc_content>
+<!--/storedoc-->
+
+<!--storedoc_bottom-->
+</storedoc>
+<!--/storedoc_bottom-->

+ 657 - 0
plugin/search/server/www/template.inc

@@ -0,0 +1,657 @@
+<?php
+/**
+ * This is a library of functions to act on the template HTML file.
+ * The functions declared here mainly read the template and write the
+ * result output using this template.
+ * Modified version - the PHP extension must be higher than 3.2.32 and PHP must be higher than 4.2
+ */
+/**
+ * Initialise arrays
+ */
+$templates=array();
+
+/**
+ * Reads the template file given and returns a string. 
+ * Similar to the file_get_contents() function but using a loop to read by chunks
+ * of 1024 bytes.
+ * @param	string	Filename
+ * @return	string	File contents 
+ */
+function load_file($file){
+    if (!($fp=fopen($file, 'r'))){
+		echo "Can't open template file $template_file";
+		exit_local(1);
+    } 
+    
+    while(!feof($fp)) {
+		$str.=fgets($fp, 1024);
+    }
+    
+    fclose($fp);
+
+    return $str;
+}
+
+/**
+ * Build the navigation bar
+ * @param	string	Original query ? - not used anyway
+ * @return	string	Navigation bar string
+ */
+function make_nav($query_orig=''){
+   global $found,$np,$isnext,$ps,$tag,$ul,$ul_arr,$self,$o,$m,$cat,$cat_arr;
+   global $dt, $dp, $dx, $dm, $dy, $dd, $db, $de, $lang, $wm, $wf, $site, $sp, $sy;
+   global $q_local,$db_local,$de_local,$lang_arr, $tag, $tag_arr, $type, $type_arr;
+   
+   $temp_ul='';
+   for($i=0; $i<count($ul_arr); $i++) {
+	$temp_ul.="&ul=".urlencode($ul_arr[$i]);
+   }	
+   $temp_tag='';
+   for($i=0; $i<count($tag_arr); $i++) {
+	$temp_tag.="&tag=".urlencode($tag_arr[$i]);
+   }	
+   $temp_lang='';
+   for($i=0; $i<count($lang_arr); $i++) {
+	$temp_lang.="&lang=".urlencode($lang_arr[$i]);
+   }	
+   $temp_cat='';
+   for($i=0; $i<count($cat_arr); $i++) {
+	$temp_cat.="&cat=".urlencode($cat_arr[$i]);
+   }	
+   $temp_type='';
+   for($i=0; $i<count($type_arr); $i++) {
+	$temp_type.="&type=".urlencode($type_arr[$i]);
+   }	
+
+   if($np>0){
+     $prevp=$np-1;
+     $prev_href="$self?q=$q_local&np=$prevp&m=$m".
+                ($ps==20?'':"&ps=$ps").
+                $temp_tag.
+                $temp_ul.
+                $temp_cat.
+                $temp_lang.
+                ($site==''?'':"&site=$site").
+		($wm==''?'':"&wm=$wm").
+		($wf==''?'':"&wf=$wf").
+                (!$o?'':"&o=$o").
+                ($dt=='back'?'':"&dt=$dt").
+                (!$dp?'':"&dp=$dp").
+                (!$dx?'':"&dx=$dx").
+                ($dd=='01'?'':"&dd=$dd").
+                (!$dm?'':"&dm=$dm").
+                ($dy=='1970'?'':"&dy=$dy").
+                ($db=='01/01/1970'?'':"&db=$db_local").
+                ($de=='31/12/2020'?'':"&de=$de_local").
+                ($sp==''?'':"&sp=$sp").
+                ($sy==''?'':"&sy=$sy");
+
+     $nav_left=print_template('navleft',0);
+     $nav_left=ereg_replace('\$NH',"$prev_href",$nav_left);
+   } elseif ($np==0) {
+     $nav_left=print_template('navleft_nop',0);
+   }
+
+   if($isnext==1) {
+     $nextp=$np+1;
+     $next_href="$self?q=$q_local&np=$nextp&m=$m".
+     		($ps==20?'':"&ps=$ps").
+                $temp_tag.
+		$temp_ul.
+                $temp_cat.
+                $temp_lang.
+                ($site==''?'':"&site=$site").
+		($wm==''?'':"&wm=$wm").
+		($wf==''?'':"&wf=$wf").
+                (!$o?'':"&o=$o").
+                ($dt=='back'?'':"&dt=$dt").
+                (!$dp?'':"&dp=$dp").
+                (!$dx?'':"&dx=$dx").
+                ($dd=='01'?'':"&dd=$dd").
+                (!$dm?'':"&dm=$dm").
+                ($dy=='1970'?'':"&dy=$dy").
+                ($db=='01/01/1970'?'':"&db=$db_local").
+                ($de=='31/12/2020'?'':"&de=$de_local").
+                ($sp==''?'':"&sp=$sp").
+                ($sy==''?'':"&sy=$sy");
+
+     $nav_right=print_template('navright',0);
+     $nav_right=ereg_replace('\$NH',"$next_href",$nav_right);
+   } else {
+     $nav_right=print_template('navright_nop',0);
+   }
+
+   $nav_bar0=print_template('navbar0',0);
+   $nav_bar1=print_template('navbar1',0);
+
+   $tp=ceil($found/$ps);
+
+   $cp=$np+1;
+
+   if ($cp>5) {
+      $lp=$cp-5;
+   } else {
+      $lp=1;
+   }
+
+   $rp=$lp+10-1;
+   if ($rp>$tp) {
+      $rp=$tp;
+      $lp=$rp-10+1;
+      if ($lp<1) $lp=1;
+   }
+
+
+   if ($lp!=$rp) {
+      for ($i=$lp; $i<=$rp;$i++) {
+         $realp=$i-1;
+   
+         if ($i==$cp) {
+            $nav_bar=$nav_bar.$nav_bar0;
+         } else {
+            $nav_bar=$nav_bar.$nav_bar1;
+         }
+         
+         $href="$self?q=$q_local&np=$realp&m=$m".
+               	($ps==20?'':"&ps=$ps").
+                $temp_tag.
+		$temp_ul.
+                $temp_cat.
+                $temp_lang.
+                ($site==''?'':"&site=$site").
+		($wm==''?'':"&wm=$wm").
+		($wf==''?'':"&wf=$wf").
+                (!$o?'':"&o=$o").
+                ($dt=='back'?'':"&dt=$dt").
+                (!$dp?'':"&dp=$dp").
+                (!$dx?'':"&dx=$dx").
+                ($dd=='01'?'':"&dd=$dd").
+                (!$dm?'':"&dm=$dm").
+                ($dy=='1970'?'':"&dy=$dy").
+                ($db=='01/01/1970'?'':"&db=$db_local").
+                ($de=='31/12/2020'?'':"&de=$de_local").
+                ($sp==''?'':"&sp=$sp").
+                ($sy==''?'':"&sy=$sy");
+
+         $nav_bar=ereg_replace('\$NP',"$i",$nav_bar);
+         $nav_bar=ereg_replace('\$NH',"$href",$nav_bar);
+      }
+   
+      $nav=print_template('navigator',0);
+      $nav=ereg_replace('\$NL',"$nav_left",$nav);
+      $nav=ereg_replace('\$NR',"$nav_right",$nav);
+      $nav=ereg_replace('\$NB',"$nav_bar",$nav);
+
+   } elseif ($found) {
+      $nav=print_template('navigator',0);
+      $nav=ereg_replace('\$NL',"$nav_left",$nav);
+      $nav=ereg_replace('\$NR',"$nav_right",$nav);
+      $nav=ereg_replace('\$NB',"",$nav);
+   }
+
+   return $nav;
+}
+/**
+ * Prints the template on screen after substituting a lot of variables
+ * from the global scope
+ * @param	string	Index of the part of the template we want to use (storedoc_top, storedoc, ...)
+ * @param	boolean	Whether to echo the results on screen or just return the string
+ * @return	mixed	Nothing if $echo=1, the resulting string if $echo=false
+ */
+function print_template($t,$echo=1){
+    global $templates, $udm_agent;
+    global $first_doc, $last_doc, $found, $query_orig, $error, $self;
+    global $nav, $wordinfo, $ws, $doclang, $doccharset, $storedocurl;
+    global $url, $ue, $o, $cat, $storedstr, $stored_href;
+    global $clonestr, $searchtime, $persite;
+    global $title, $rating, $desc, $contype, $lastmod, $docsize, $ndoc;
+    global $keyw, $text, $category, $pop_rank;
+    global $crc, $Randoms, $rec_id, $DEBUG, $id;
+    global $lang_url_translation, $phpver, $sitelimit_href, $sitelimitstr;
+    global $global_doc_res, $global_res_position;
+    global $last_modified, $content, $charset, $length, $document, $url;
+ 
+    $str=$templates["$t"][$o];
+    if ($str == '') $str=$templates["$t"][0];
+    
+    //variables as returned by the udm_search() function and defined in search.php
+    $str=ereg_replace('\$f', "$first_doc", $str);
+    $str=ereg_replace('\$l', "$last_doc", $str);
+    $str=ereg_replace('\$t', "$found", $str);
+    $str=ereg_replace('\$A', $self, $str);
+
+    $str=ereg_replace('\$Q', urlencode(stripslashes($query_orig)), $str);
+    $str=ereg_replace('\$q', urlencode($query_orig), $str);
+    $str=eregi_replace('\$UE', $ue, $str);
+
+    $str=ereg_replace('\$E', $error, $str);
+    $str=ereg_replace('\$W', htmlspecialchars($wordinfo), $str);
+    $str=ereg_replace('\$\(WS\)', htmlspecialchars($ws), $str);
+
+    $str=ereg_replace('\$V', $nav, $str);
+
+    if ($lang_url_translation == 'yes') {
+    	$nolangurl = ereg_replace("\.[a-z]{2}\.[a-z]{2,4}$", "", $url);
+        $str=ereg_replace('\$DU', htmlspecialchars($nolangurl), $str);
+    } else {
+    	$str=ereg_replace('\$DU', htmlspecialchars($url), $str);
+    }
+
+    $str=ereg_replace('\$\(stored_href\)', htmlspecialchars($stored_href), $str);
+    $str=ereg_replace('\$\(sitelimit_href\)', htmlspecialchars($sitelimit_href), $str);
+
+    //require_once('filter_user.functions.php');
+    //$title = subst_course_code(urldecode(html_entity_decode($title)));
+    $str=ereg_replace('\$DT', htmlspecialchars($title), $str);
+    $str=ereg_replace('\$DR', htmlspecialchars("$rating"), $str);
+    //$text = subst_course_code(html_entity_decode($text));
+    //Comment out temporarily because breaking XML file (excerpt of Word document with unknown character)
+    $str=ereg_replace('\$DX', htmlspecialchars(urlencode($text)), $str);
+    $str=ereg_replace('\$DE', ($desc != '')?htmlspecialchars(urlencode($desc)):htmlspecialchars(urlencode($text)), $str);
+    $str=ereg_replace('\$DC', $contype, $str);
+    $str=ereg_replace('\$DM', $lastmod, $str);
+    $str=ereg_replace('\$DS', "$docsize", $str);
+    $str=ereg_replace('\$DN', "$ndoc", $str);
+    $str=ereg_replace('\$DD', htmlspecialchars($desc), $str);
+    $str=ereg_replace('\$DK', htmlspecialchars($keyw), $str);
+    $str=ereg_replace('\$SearchTime', "$searchtime", $str);
+    $str=ereg_replace('\$\(STORED\)', htmlspecialchars("$storedstr"), $str);
+    $str=ereg_replace('\$\(SITELIMIT\)', htmlspecialchars("$sitelimitstr"), $str);
+    $str=ereg_replace('\$\(Pop_Rank\)', "$pop_rank", $str);
+    $str=ereg_replace('\$CL', "$clonestr", $str);
+    $str=ereg_replace('\$\(PerSite\)', "$persite", $str);
+    
+	//information on each link (header for one item)
+    if ($t == 'storedoc_top') {
+        $str=ereg_replace('\$\(ID\)', htmlspecialchars("$id"), $str);
+        $str=ereg_replace('\$\(Last-Modified\)', htmlspecialchars("$last_modified"), $str);
+        $str=ereg_replace('\$\(Content-Language\)', htmlspecialchars("$content"), $str);
+		$str=ereg_replace('\$\(Charset\)', htmlspecialchars("$charset"), $str);
+		$str=ereg_replace('\$\(Content-Length\)', "$length", $str);
+		$str=ereg_replace('\$\(URL\)', htmlspecialchars("$url"), $str);
+    }
+    //link to the document
+    if ($t == 'storedoc') {
+		$str=ereg_replace('\$\(document\)', htmlspecialchars("$document"), $str);
+    }
+
+	//Categories	
+	if (ereg('\$CP',$str)) {
+		if ($temp_cp_arr=udm_cat_path($udm_agent,$cat)) {
+    		reset($temp_cp_arr);
+        	$temp_cp='';
+        	for ($i=0; $i<count($temp_cp_arr); $i+=2) {
+        		$cp_path=$temp_cp_arr[$i];
+        		$cp_name=$temp_cp_arr[$i+1];
+        		$temp_cp .= " &gt; <a href=\"$PHP_SELF?cat=$cp_path\">$cp_name</a> ";
+        	}
+        	$str=ereg_replace('\$CP', $temp_cp, $str);
+	} else $str=ereg_replace('\$CP', '', $str);
+    }    	
+
+	//Categories
+    if (ereg('\$CS',$str)) {
+    	if ($temp_cp_arr=udm_cat_list($udm_agent,$cat)) {
+        	reset($temp_cp_arr);
+        	$temp_cp='';
+            for ($i=0; $i<count($temp_cp_arr); $i+=2) {
+        		$cp_path=$temp_cp_arr[$i];
+        		$cp_name=$temp_cp_arr[$i+1];
+        		$temp_cp .= "<a href=\"$PHP_SELF?cat=$cp_path\">$cp_name</a><br>";
+        	}
+                $str=ereg_replace('\$CS', $temp_cp, $str);
+	} else $str=ereg_replace('\$CS', '', $str);
+    }    	
+	
+	//Categories
+    if (ereg('\$DY',$str)) {
+    	if ($temp_cp_arr=udm_cat_path($udm_agent,$category)) {
+        	reset($temp_cp_arr);
+        	$temp_cp='';
+            for ($i=0; $i<count($temp_cp_arr); $i+=2) {
+        		$cp_path=$temp_cp_arr[$i];
+        		$cp_name=$temp_cp_arr[$i+1];
+        		$temp_cp .= " &gt; <a href=\"$PHP_SELF?cat=$cp_path\">$cp_name</a> ";
+        	}
+            $str=ereg_replace('\$DY', $temp_cp, $str);
+		} else $str=ereg_replace('\$DY', '', $str);
+    }
+
+	//Number of documents
+    if (eregi('\$ndocs*',$str)) {
+    	$str=preg_replace('/\$ndocs?/', get_doc_count(), $str);
+    }
+	//document link?
+    if ($global_doc_res) {
+		$str=preg_replace_callback('/\$\(([\w\.\_\-\:]+)\)/', 'res_field_callback', $str);
+    }
+    
+    //Random?
+    $sub=$str;
+    while($sub=strstr($sub,'$r')){
+		$sub=substr($sub,2);
+		$pos=0;
+		$num='';
+		
+		while(($sub[$pos]>='0')&&($sub[$pos]<='9')){
+			$num.=$sub[$pos++];
+		}
+		
+		$str=ereg_replace('\$r'.$num, ''.$Randoms[$num], $str);
+    }
+    
+    if($echo) echo $str; else return $str;
+}
+
+/**
+ * Reads the template file.
+ * @param	none	All the parameters are taken as globals, which is very bad.
+ * @return	void	No return value everything is left in global scope
+ */
+function read_template(){
+    global $Randoms;
+    global $template_file; //uri of the file to open
+    global $templates,$dbaddr;
+    global $ps, $np, $ul, $ul_arr, $o, $tag, $tag_arr, $m, $cat, $cat_arr, $wm, $wf;
+    global $dt, $dp, $dx, $dm, $dy, $dd, $db, $de;
+    global $clones,$lang,$lang_arr, $sp, $sy, $s, $resultslimit;
+    global $affix_file, $spell_file, $spell_host;
+    global $stopwordtable_arr, $stopwordfile_arr;
+    global $synonym_arr, $searchd_arr;
+    global $alias_arr,$type, $type_arr;
+    
+    $affix_file=array();
+    $spell_file=array();
+    $alias_arr=array();
+
+	$dbaddr=array();
+
+    $names=array('top', 'bottom', 'restop', 'resbot', 'navigator',
+				 'res', 'ftpres', 'httpres', 'notfound', 'error', 'variables', 
+				 'clone', 'navleft_nop', 'navright_nop', 'navleft', 
+				 'navbar1', 'navbar0', 'navright', 'noquery', 'site_limit', 
+				 'storedoc_top','storedoc_bottom','storedoc','stored');
+
+    $where='';
+    
+    //First check that the template file is available
+    if (!($fp=fopen($template_file, 'r'))){
+		echo "Can't open template file $template_file";
+		exit_local(1);
+    } do {
+    	//The template file is there, read it 
+		$str=fgets($fp, 1024);
+
+		$param = array();
+        if (preg_match('/value="(.*)"[\s\t]+selected="\$ps"/i',$str,$param)) {
+      		if (($param[1]) == $ps) {
+          		$str=preg_replace('/selected="\$ps"/i',"selected",$str);
+      		} else {
+          		$str=preg_replace('/selected="\$ps"/i',"",$str);
+      		}
+  		} elseif (preg_match('/value="(.*)"[\s\t]+selected="\$ul"/i',$str,$param)) {
+  			$found_param=0;
+  			for($i=0; $i<count($ul_arr); $i++) {
+				$temp_ul=$ul_arr[$i];
+      			if (($param[1]) == $temp_ul) {
+          			$str=preg_replace('/selected="\$ul"/i',"selected",$str);
+          			$found_param=1;
+          			break;
+          		}
+      		} 
+      		if (!$found_param) $str=preg_replace('/selected="\$ul"/i',"",$str);
+  		} elseif (preg_match('/value="(.*)"[\s\t]+selected="\$type"/i',$str,$param)) {
+  			$found_param=0;
+  			for($i=0; $i<count($type_arr); $i++) {
+				$temp_type=$type_arr[$i];
+      			if (($param[1]) == $temp_type) {
+          			$str=preg_replace('/selected="\$type"/i',"selected",$str);
+          			$found_param=1;
+          			break;
+          		}
+      		} 
+      		if (!$found_param) $str=preg_replace('/selected="\$type"/i',"",$str);
+        } elseif (preg_match('/value="(.*)"[\s\t]+selected="\$lang"/i',$str,$param)) {
+	  		$found_param=0;
+	  		for($i=0; $i<count($lang_arr); $i++) {
+				$temp_lang=$lang_arr[$i];
+      			if (($param[1]) == $temp_lang) {
+          			$str=preg_replace('/selected="\$lang"/i',"selected",$str);
+          			$found_param=1;
+          			break;
+          		}
+      		} 
+      		if (!$found_param) $str=preg_replace('/selected="\$lang"/i',"",$str);
+  		} elseif (preg_match('/value="(.*)"[\s\t]+selected="\$o"/i',$str,$param)) {
+      		if (($param[1]) == $o) {
+          		$str=preg_replace('/selected="\$o"/i',"selected",$str);
+      		} else {
+          		$str=preg_replace('/selected="\$o"/i',"",$str);
+      		}
+  		} elseif (preg_match('/value="(.*)"[\s\t]+selected="\$m"/i',$str,$param)) {
+      		if (($param[1]) == $m) {
+          		$str=preg_replace('/selected="\$m"/i',"selected",$str);
+      		} else {
+          		$str=preg_replace('/selected="\$m"/i',"",$str);
+      		}
+        } elseif (preg_match('/value="(.*)"[\s\t]+selected="\$wm"/i',$str,$param)) {
+      		if (($param[1]) == $wm) {
+          		$str=preg_replace('/selected="\$wm"/i',"selected",$str);
+      		} else {
+          		$str=preg_replace('/selected="\$wm"/i',"",$str);
+      		}
+        } elseif (preg_match('/value="(.*)"[\s\t]+selected="\$s"/i',$str,$param)) {
+      		if ($param[1] == $s) {
+          		$str=preg_replace('/selected="\$s"/i',"selected",$str);
+      		} else {
+          		$str=preg_replace('/selected="\$s"/i',"",$str);
+      		}
+        } elseif (preg_match('/value="(.*)"[\s\t]+selected="\$sp"/i',$str,$param)) {
+      		if ($param[1] == $sp) {
+          		$str=preg_replace('/selected="\$sp"/i',"selected",$str);
+      		} else {
+          		$str=preg_replace('/selected="\$sp"/i',"",$str);
+      		}
+        } elseif (preg_match('/value="(.*)"[\s\t]+selected="\$sy"/i',$str,$param)) {
+      		if ($param[1] == $sy) {
+          		$str=preg_replace('/selected="\$sy"/i',"selected",$str);
+      		} else {
+          		$str=preg_replace('/selected="\$sy"/i',"",$str);
+      		}
+        } elseif (preg_match('/value="(.*)"[\s\t]+selected="\$wf"/i',$str,$param)) {
+      		if (($param[1]) == $wf) {
+          		$str=preg_replace('/selected="\$wf"/i',"selected",$str);
+      		} else {
+          		$str=preg_replace('/selected="\$wf"/i',"",$str);
+      		}
+  		} elseif (preg_match('/value="(.*)"[\s\t]+selected="\$tag"/i',$str,$param)) {
+      		$found_param=0;
+			for($i=0; $i<count($tag_arr); $i++) {
+				$temp_tag=$tag_arr[$i];
+      			if (($param[1]) == $temp_tag) {
+          			$str=preg_replace('/selected="\$tag"/i',"selected",$str);
+          			$found_param=1;
+          			break;
+          		}
+      		} 
+      		if (!$found_param) $str=preg_replace('/selected="\$tag"/i',"",$str);
+  			} elseif (preg_match('/type=radio[\s\t]+name="dt"[\s\t]+value="(.*)"/i',$str,$param)) {
+      		if (($param[1]) == $dt) {
+          		$str=preg_replace("/value=\"$dt\"/i","value=\"$dt\" checked",$str);
+      		} else {                                
+          		$str=preg_replace('/checked/i',"",$str);
+      		}
+ 	 	} elseif (preg_match('/value="(.*)"[\s\t]+selected="\$dp"/i',$str,$param)) {
+      		if (($param[1]) == $dp) {
+          		$str=preg_replace('/selected="\$dp"/i',"selected",$str);
+      		} else {                                
+          		$str=preg_replace('/selected="\$dp"/i',"",$str);
+      		}
+  		} elseif (preg_match('/value="(.*)"[\s\t]+selected="\$dx"/i',$str,$param)) {
+      		if (($param[1]) == $dx) {
+          		$str=preg_replace('/selected="\$dx"/i',"selected",$str);
+      		} else {                                
+          		$str=preg_replace('/selected="\$dx"/i',"",$str);
+      		}
+  		} elseif (preg_match('/value="(.*)"[\s\t]+selected="\$dm"/i',$str,$param)) {
+      		if (($param[1]) == $dm) {
+          		$str=preg_replace('/selected="\$dm"/i',"selected",$str);
+      		} else {                                
+          		$str=preg_replace('/selected="\$dm"/i',"",$str);
+      		}
+  		} elseif (preg_match('/value="(.*)"[\s\t]+selected="\$dy"/i',$str,$param)) {
+      		if (($param[1]) == $dy) {
+          		$str=preg_replace('/selected="\$dy"/i',"selected",$str);
+      		} else {                                
+          		$str=preg_replace('/selected="\$dy"/i',"",$str);
+      		}
+  		}
+
+		if (preg_match('/\$g\((\d*)\)/i',$str,$param)) {	    	    
+		    $str=str_replace("\$g($param[1])",substr($tag,0,strlen($tag)-$param[1]),$str);
+		}
+	
+		//Replace date attributes
+        $str=str_replace("\$dd",$dd,$str);
+        $str=str_replace("\$dy",$dy,$str);
+        $str=str_replace("\$dm",$dm,$str);
+        $str=str_replace("\$db",$db,$str);
+        $str=str_replace("\$de",$de,$str);
+
+		//Replace page numbering
+        $str=str_replace("\$ps",$ps,$str);
+		$str=str_replace("\$pn",$ps*$np,$str);
+        $str=str_replace("\$cat",$cat,$str);
+
+		
+        if (preg_match('/\$IF\s?\((.+)\)/i',$str,$param)) {
+		    $param[1]=trim($param[1]);
+		    $str=preg_replace('/\$IF\s?\((.+)\)/i',load_file($param[1]),$str);	    
+        }
+
+		$comment_flag=0;
+		
+		//If found comment tag, add empty field to the $templates array for the corresponding tag 
+		if (substr($str, 0, 4) == "<!--") {
+			reset($names);
+			while ($name=current($names)){
+			    if (strstr($str, "<!--$name")){
+					$where=$name;
+		
+					$templates["$where"][] = '';
+					
+					$comment_flag=1;
+					break;
+			    } elseif (strstr($str, "/$name-->")) {
+					$where='';
+					$comment_flag=1;
+					break;
+			    }
+			    next($names);
+			}
+		}
+	
+		//if found a comment on this line, skip to the next line (do{...})
+		if ($comment_flag) continue;
+
+		//if the previous line was a comment and contained 'variables'
+		//'variables' is the section of the template where the configuration is
+		//Once this section is over, the HTML template really begins
+		if ($where=='variables') {
+			//if the line starts with a #, it's a comment so skip to next line
+		    if (ereg("^#",$str)) continue;
+
+			//look for some characters not space or tab starting a line, 
+			//followed by spaces or tabs, followed by any chars (basically any var..value couple)
+		    if (preg_match("/^([^\s\t]+)[\s\t]+(.+)/",$str,$param)) {
+	            $var=$param[1];
+			    $value=$param[2];
+			    $var=strtolower($var);
+	
+			    $var=trim($var);
+			    $value=trim($value);                 
+
+			    //assign each value to the corresponding array, for reuse later
+			    if ($var=='affix') {
+			    	if ($sp=='') $sp=1;
+			    	$GLOBALS["ispellmode"]="text";
+		       		if (preg_match("/([^\s\t]+)[\s\t]+([^\s\t]+)[\s\t]+(.+)/",$value,$param)) {
+		          		$t_lang=trim($param[1]);
+                        $t_charset=trim($param[2]);
+		          		$file=trim($param[3]);
+
+		          		$affix_file[$t_lang]="$t_charset;$file";
+		          	} else {
+		          		print "Unsupported Affix command: Affix $value\n<br>";
+		          		exit;
+		        	}
+			    } elseif ($var=='spell') {
+                       if ($sp=='') $sp=1;
+                       $GLOBALS["ispellmode"]="text";
+       	           		if (preg_match("/([^\s\t]+)[\s\t]+([^\s\t]+)[\s\t]+(.+)/",$value,$param)) {
+			          		$t_lang=trim($param[1]);
+                            $t_charset=trim($param[2]);
+			          		$file=trim($param[3]);
+	
+			          		$spell_file[$t_lang][]="$t_charset;$file";
+			       		} else {
+			          		print "Unsupported Spell command: Spell $value\n<br>";
+			          		exit;
+			       		}
+				} elseif ($var=='ispellmode') {
+                       if (preg_match("/^server[\s\t]+(.+)/i",$value,$param)) {
+				          $spell_host=trim($param[1]);
+                          $GLOBALS["ispellmode"]="server";
+		    		   } else {
+		   	 		   	  $GLOBALS["$var"]="$value";
+		   			    }
+		   		} elseif ($var=='alias') {
+                       if (preg_match("/^([^\s]+)\s+(.+)$/i",$value,$param)) {
+                       	  $alias_arr[trim($param[1])]=trim($param[2]);
+		       			} else {
+		       			  $GLOBALS["$var"]="$value";
+		       			}
+	            } elseif ($var=='stopwordtable') {
+	               $stopwordtable_arr[]=$value;
+	            } elseif ($var=='stopwordfile') {
+	               $stopwordfile_arr[]=$value;
+	            } elseif ($var=='synonym') {
+	               if ($sy=='') $sy=1;
+	               $synonym_arr[]=$value;
+	            } elseif ($var=='searchdaddr') {
+	                   $searchd_arr[]=$value;
+			    } elseif ($var=='r') {
+			       $rand=0+substr($var,1);
+			       $frand=rand();
+			       $frand=$frand/getrandmax()*$value;
+			       $Randoms[$rand]=floor($frand);
+			    } elseif ($var=='dbaddr') {
+		    		$dbaddr[]=$value;
+			    } else {
+			       $GLOBALS["$var"]="$value";
+			    }
+	    }
+	}
+	else
+	if ($where!=''){
+	    $templates["$where"][count($templates["$where"])-1] .= $str;
+	}
+	
+    } while (!feof($fp));//do this big loop until we reach the end of the file
+
+    fclose($fp);
+}
+/**
+ * Calls back the udm_get_res_field_ex() function whith the second element of
+ * the given array...!?
+ * @param	array	Array which second element is sent to udm_get_res_field_ex()
+ * @return	string	A string
+ */
+function res_field_callback($expr) {
+    global $global_doc_res, $global_res_position;
+
+    return 	ParseDocText(htmlspecialchars(udm_get_res_field_ex($global_doc_res,$global_res_position,$expr[1])));
+}
+
+
+?>