GIF89a;
| Direktori : /home/serb/www/chat/install_files/temp_dir/bot/programe/src/botinst/ |
| Current File : /home/serb/www/chat/install_files/temp_dir/bot/programe/src/botinst/botloaderfuncs.php |
<?php
/*
Program E
Copyright 2002, Paul Rydell
Portions by Jay Myers
This file is part of Program E.
Program E is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Program E is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Program E; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* AIML loading functions
*
* Contains contains the functions for the actual loading of AIML.
* @author Paul Rydell
* @copyright 2002
* @version 0.0.8
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @package Loader
*/
/**
* The general preferences and database details.
*/
if( ! defined('THIS_DIR') ) define('THIS_DIR', dirname(__FILE__) . '/');
require_once THIS_DIR . "dbprefs.php";
global $selectbot, $annesID, $is_single;
/**
* Deletes everything about a bot.
*
* Empties the tables, bot, patterns, templates, bots and gmcache
*
* @param integer $bot The bot's ID
*
* @return void
*/
function deletebot($bot)
{
$q="delete from {$GLOBALS['fc_config']['db']['pref']}bot where bot=$bot";
$e = mysql_query($q);
if ($e){
}
$q="delete from {$GLOBALS['fc_config']['db']['pref']}patterns where bot=$bot";
$e = mysql_query($q);
if ($e){
}
$q="delete from {$GLOBALS['fc_config']['db']['pref']}templates where bot=$bot";
$e = mysql_query($q);
if ($e){
}
$q="delete from {$GLOBALS['fc_config']['db']['pref']}bots where id=$bot";
$e = mysql_query($q);
if ($e){
}
$q="delete from {$GLOBALS['fc_config']['db']['pref']}gmcache";
$e = mysql_query($q);
if ($e){
}
}
/**
* Deletes information about a bot in the cache and bot tables.
*
* Used by the incremental bot loader program so it doesn't wipe out the whole
* bot on each aiml file load. Deletes everything in bot, bots and gmcache tables.
*
* @param integer $bot The bot's ID.
*
* @return void
*/
//
//
function deletejustbot($bot){
$q="delete from {$GLOBALS['fc_config']['db']['pref']}bots where id=$bot";
$e = mysql_query($q);
if ($e){
}
$q="delete from {$GLOBALS['fc_config']['db']['pref']}bot where bot=$bot";
$e = mysql_query($q);
if ($e){
}
$q="delete from {$GLOBALS['fc_config']['db']['pref']}gmcache";
$e = mysql_query($q);
if ($e){
}
}
/**
* Deletes the gmcache table.
*
* This needs to be called whenever the patterns or templates table is updated.
*
* @return void
*/
function flushcache()
{
$q="delete from {$GLOBALS['fc_config']['db']['pref']}gmcache";
$e = mysql_query($q);
if ($e){
}
}
/**
* Makes the keys of an array uppercase.
*
* Makes the keys of an array uppercase.
*
* @param array $testa The array where the keys need to be changed into uppercase.
*
* @return array An array with only uppercase keys.
*/
if(!function_exists('upperkeysarray'))
{
function upperkeysarray($testa)
{
$newtesta=array();
$newkeys=array_keys($testa);
for ($x=0;$x<sizeof($newkeys);$x++){
$newtesta[strtoupper($newkeys[$x])]=$testa[$newkeys[$x]];
}
return $newtesta;
}
}
/**
* Write the substitution include file
*
* Write the substitution arrays back into the subs.inc
*
* @global object The opened subs.inc file, ready to write to.
*
* @param string $string most likely an array or all arrays turned into a big file.
*
* @return void
*/
function addtosubs($string)
{
global $fp;
if( $fp ) fwrite($fp,$string);
}
/**
* Create the object for writing the substitution include file
*
* Creates the object, which is then used by addtosubs() to write to
*
* @see addtosubs()
* @see makesubscode()
* @global object
*
* @return void
*/
function createsubfile()
{
global $fp;
$fp = @fopen ("subs.inc", "w+");
}
/**
* Find a word in the patterns table given the word and the parent.
*
* The AIML patterns are stored in the MySQL table in a binary tree format.
* This function retrieves the next word details based upon the previous' word's ID.
* If this word doesn't exist it returns 0, else it returns it's details.
*
* @uses setnotend()
*
* @param string $word The word that is to be searched
* @param integer $parent The ID of the parent word
*
* @return integer The ID of the word that was searched
*/
function findwordid($word,$parent)
{
$word=addslashes($word);
$query="select id,isend from {$GLOBALS['fc_config']['db']['pref']}patterns where word='$word' and parent=$parent";
$selectcode = mysql_query($query);
if ($selectcode){
if(!mysql_numrows($selectcode)){
return 0;
}
else{
while ($q = mysql_fetch_array($selectcode)){
if ($q[1]==1){
setnotend($q[0]);
}
return $q[0];
}
}
}
}
/**
* Find a wildcard in the patterns table given the word and the parent.
*
* Similar as findwordid() but this will retrieve the ID if there is a wildcard that fits.
*
* @uses setnotend()
*
* @param string $word The word that is to be searched, either _ or *
* @param integer $parent The ID of the parent word
*
* @return integer The ID of the word that was searched
*/
function findwordidstar($word,$parent)
{
if ($word=="*"){
$val=3;
}
elseif ($word=="_"){
$val=1;
}
$query="select id,isend from {$GLOBALS['fc_config']['db']['pref']}patterns where parent=$parent and word is null and ordera=$val";
$selectcode = mysql_query($query);
if ($selectcode){
if(!mysql_numrows($selectcode)){
return 0;
}
else{
while ($q = mysql_fetch_array($selectcode)){
if ($q[1]==1){
setnotend($q[0]);
}
return $q[0];
}
}
}
}
/**
* Set an entry in the patterns table to not be flagged as the last word in its context.
*
* Update a record in the patterns table, change isend column from 1 to 0. Given a particular word ID.
*
* @param integer $wordid
*
* @return void
*/
function setnotend($wordid)
{
$query="update {$GLOBALS['fc_config']['db']['pref']}patterns set isend=0 where id=$wordid";
$q=mysql_query($query);
if ($q){
}
}
/**
* Inserts the pattern into the patterns table.
*
* inserts the pattern, that and topic as individual words in binary tree format into the patterns table
*
* @uses findwordid()
* @uses insertwordpattern()
* @uses findwordidstar()
*
* @global string
* @global integer
*
* @param string $mybigsentence Contains the pattern, that and topic in the following format <input>word word<that>word word<topic>word word.
*/
function insertmysentence($mybigsentence)
{
global $selectbot, $annesID;
$sentencepart="";
$newstarted=0;
if($annesID != ""){
$parent = $annesID;
} else {
$parent=-$selectbot;
}
//Parse into invidividual words
//Use split
$allwords=explode(" ",$mybigsentence);
$qadd="";
for ($x=0;$x<sizeof($allwords)+1;$x++){
// Last word in context
$lwic=0;
if ($x==sizeof($allwords)){
$word="";
}
else {
$word=$allwords[$x];
}
if (strtoupper($word)=="<INPUT>"){
$sentencepart="INPUT";
} elseif (strtoupper($word)=="<THAT>"){
$sentencepart="THAT";
} elseif (strtoupper($word)=="<TOPIC>"){
$sentencepart="TOPIC";
}
// Find out if it is the last word in its context
if ($x==(sizeof($allwords)-1)){
$lwic=1;
}
// Prevent some warnings by checking this first.
elseif (($x+1) >= (sizeof($allwords))){
}
elseif ((strtoupper($allwords[$x+1])=="<THAT>") || (strtoupper($allwords[$x+1])=="<TOPIC>")){
$lwic=1;
}
if (($word!="*")&&($word!="_")){
if ($newstarted!=1){
$wordid=findwordid($word,$parent);
}
if (($wordid!=0) && ($newstarted!=1)){
$parent=$wordid;
}
else {
$newstarted=1;
$sword=addslashes($word);
$qadd="($selectbot, null,'$sword',2,$parent,$lwic)";
$parent = insertwordpattern($qadd);
}
}
elseif (($word=="*")||($word=="_")){
if ($newstarted!=1){
$wordid=findwordidstar($word,$parent);
}
if (($wordid!=0) && ($newstarted!=1)){
$parent=$wordid;
}
else {
$newstarted=1;
if ($word=="*"){
$val=3;
}
elseif ($word=="_"){
$val=1;
}
$qadd="($selectbot, null,null,$val,$parent,$lwic)";
$parent = insertwordpattern($qadd);
}
}
}
return $parent;
}
/**
* Inserts an entry into the patterns table. Returns the ID of the new row inserted.
*
* insert a word into the patterns table, returns the id of the record so it can be
* used as the parent ID of the next word that's to be inserted.
*
* @param string $qadd The word of the pattern to be inserted
*
* @return integer The record ID of the inserted word.
*/
function insertwordpattern($qadd)
{
$query="insert into {$GLOBALS['fc_config']['db']['pref']}patterns(bot,id,word,ordera,parent,isend) values $qadd";
$qcode=mysql_query($query);
if ($qcode){
return mysql_insert_id();
}
}
/**
* Inserts a template into the template table.
*
* Insert the template into the template database. <br/>
* This version has been adapted to also insert the pattern, that and topic into the additionally added columns
*
* @uses templateexists()
*
* @global integer
* @global integer The ID of the record in the patterns table that links to this table
* @global string The pattern, including variables like _ and *.
* @global string the topic, including variable like _ and *
* @global string the that, including variables like _ and *
*
* @param integer $idused The ID of the record in the patterns table that links to the template table.
* @param string $template The contents inbetween <template/> tags.
*
* @return void
*/
$templBuf = array();
function insertmytemplate($idused,$template, $flushlast=false)
{
global $selectbot,$templatesinserted, $pattern, $topic, $that, $templBuf, $is_single;
//if (!templateexists($idused))
{
$templatesinserted++;
$template=addslashes($template);
$pattern=addslashes($pattern);
$templBuf[] = "($selectbot, $idused,'$template','$pattern','$that','$topic')";
if( sizeof($templBuf) >= 400 || $is_single)
{
$query="insert IGNORE into {$GLOBALS['fc_config']['db']['pref']}templates (bot,id,template,pattern,that,topic) values " . implode(',', $templBuf) ;
$qcode=mysql_query($query);
if ($qcode)
{
}
//unset($templBuf);
$templBuf = array();
}
}
}
/**
* Checks if a template exists for a given pattern
*
* Does a query on the database to see if an ID is used by a template in the templates table.
*
* @param integer $idused The ID number that corresponds to the number in the ID column, if it exists.
*
* @return boolean true/false
*/
$templBuf2 = array();
function templateexists($idused)
{
/*
return true;
global $templBuf2;
if( isset($templBuf2[$idused]) ) return true;
else { $templBuf2[$idused]=1; return false;} */
return false;
/*
$query="select id from {$GLOBALS['fc_config']['db']['pref']}templates where id=$idused";
$qcode=mysql_query($query);
if ($qcode){
if(!mysql_numrows($qcode)){
return false;
}
}
return true;
*/
}
/**
* Called by the XML parser that is parsing the startup.xml file.
*
* startS and endS are two functions that cooperate. startS looks for the start of an XML tag, endS for the end tag.
* It fills the global variabls with info to be processed further on. Inserts the bots into the bots table, inserts the bot predicates into its respective table.
*
* @todo Find out what Global $areinc does
*
* @uses upperkeysarray()
* @uses botexists()
* @uses getbotid()
* @uses deletebot()
*
* @global integer
* @global string
* @global array
* @global array contains the splitter characters which are used to split the sentences. For example period, comma, semi-colon, exclamation mark, question mark.
* @global array contains the input, split into sentences
* @global array contains the gender words or phrases.
* @global array contains the person words or phrases
* @global array contains the person2 words or phrases
* @global array contains the names of all the bots, or their ID's
* @global array contains something unknown
*
* @param resource $parser SAX XML resource handler
* @param string $name name of the encountered tag.
* @param array $attrs contains the additional attribues of a tag, like value, id, find.
*
* @return void
*/
function startS($parser,$name,$attrs)
{
global $selectbot, $whaton, $startupwhich, $splitterarray,
$inputarray, $genderarray, $personarray, $person2array, $allbots, $areinc;
$attrs=upperkeysarray($attrs);
if (strtoupper($name)=='LEARN') {
$whaton = 'LEARN';
}
if (strtoupper($name)=="GENDER"){
$startupwhich="GENDER";
}
elseif (strtoupper($name)=="INPUT"){
$startupwhich="INPUT";
}
elseif (strtoupper($name)=="PERSON"){
$startupwhich="PERSON";
}
elseif (strtoupper($name)=="PERSON2"){
$startupwhich="PERSON2";
}
if (strtoupper($name)=="PROPERTY"){
$q="insert into {$GLOBALS['fc_config']['db']['pref']}bot (bot,name,value) values ($selectbot,'" . addslashes($attrs["NAME"]) . "','" . addslashes($attrs["VALUE"]) . "')";
$qcode=mysql_query($q);
if ($qcode){
}
}
elseif (strtoupper($name)=="BOT") {
$bot = $attrs["ID"];
if (botexists($bot)){
$existbotid = getbotid($bot);
if ($areinc==1){
deletebot($existbotid);
}
}
$asbot=addslashes($bot);
$q="insert into {$GLOBALS['fc_config']['db']['pref']}bots (id,botname) values (null,'$asbot')";
$qcode=mysql_query($q);
if ($areinc==1){
if ($qcode){
}
$newbotid=mysql_insert_id();
}
else {
$newbotid=$existbotid;
}
$selectbot=$newbotid;
$allbots[]=$selectbot;
#print "<b>Loading bot: $bot ($selectbot)<BR></b>\n";
flush();
}
elseif (strtoupper($name)=="SPLITTER"){
$splitterarray[]=$attrs["VALUE"];
}
elseif (strtoupper($name)=="SUBSTITUTE"){
if (trim($attrs["FIND"])!=""){
if ($startupwhich=="INPUT"){
$inputarray[]=array($attrs["FIND"],$attrs["REPLACE"]);
}
elseif ($startupwhich=="GENDER"){
$genderarray[]=array($attrs["FIND"],$attrs["REPLACE"]);
}
elseif ($startupwhich=="PERSON"){
$personarray[]=array($attrs["FIND"],$attrs["REPLACE"]);
}
elseif ($startupwhich=="PERSON2"){
$person2array[]=array($attrs["FIND"],$attrs["REPLACE"]);
}
}
}
}
/**
* Called by the XML parser that is parsing the startup.xml file.
*
* @global string Which start tag was processed last
*
* @param resource $parser SAX XML resource handler
* @param string $name name of the encountered tag.
*
* @return void
*/
function endS($parser,$name)
{
global $whaton;
if (strtoupper($name)=='LEARN') {
$whaton = '';
}
}
/**
* Process contents <learn> tag in startup.xml
*
* Called by the XML parser that is parsing the startup.xml file. * -> all files in directory, or single file.
*
* @todo When using * it should process AIML in subdirectories too. This is currently only supported by using multiple <learn> tag entries for every folder containing AIML files.
*
* @uses learnallfiles()
*
* @global string
* @global array contains the AIML files to learn.
* @global integer
*
* @param resource $parser SAX XML resource handler
* @param string $data assuming it contains the path to the file.
*/
function handlemeS($parser, $data)
{
global $whaton, $learnfiles, $selectbot;
if (strtoupper($whaton)=="LEARN"){
if (trim($data)=="*"){
learnallfiles($selectbot);
}
else {
$learnfiles[$selectbot][]=trim($data);
}
}
}
/**
* Checks if a bot already exists.
*
* Does a check to see if a bot with a particular name already exists. The reliance on unique names if crucial for the bot to work.
*
* @param string $name the name of the bot that is checked.
*
* @return boolean true/false
*/
function botexists($name){
// search to get existing id
$name=addslashes($name);
$q="select id from {$GLOBALS['fc_config']['db']['pref']}bots where botname='$name'";
$selectcode = mysql_query($q);
if ($selectcode) {
while ($q = mysql_fetch_array($selectcode)){
return true;
}
}
return false;
}
/**
* Gets a bot's property value.
*
* Retrieves the value of a particular bot predicate. If the predicate isn't set, then it will return the value 'default'. This has been hardcoded
*
*
* @global integer
*
* @param string $name the name of the bot predicate to be retrieved.
*
* @return string the value of the bot predicate.
*/
function getbotvalue($name)
{
global $selectbot;
$q="select value from {$GLOBALS['fc_config']['db']['pref']}bot where name=" . addslashes($name) . " and bot=$selectbot";
$selectcode = mysql_query($q);
if ($selectcode){
if(!mysql_numrows($selectcode)){
return DEFAULTPREDICATEVALUE;
}
else{
while ($q = mysql_fetch_array($selectcode)){
return $q["value"];
}
}
}
}
/**
* Gets the ID of a bot given its name.
*
* Gets the ID of a bot given its name
*
* @todo move this function to a common include file shared by both the Loader and the Interpreter.
*
* @param string $name The name of the bot
*
* @ return integer The bot's ID.
*/
function getbotid ($name)
{
// search to get existing id
$name=addslashes($name);
$q="select id from {$GLOBALS['fc_config']['db']['pref']}bots where botname='$name'";
$selectcode = mysql_query($q);
if ($selectcode) {
while ($q = mysql_fetch_array($selectcode)){
return $q["id"];
}
}
}
/**
* Used by the AIML XML parser
*
* Looks for the start tag used in AIML files for category, template, that, topic.
*
* @uses upperkeysarray()
* @uses getbotvalue()
*
* @global string which tag is being processed
* @global string
* @global string
* @global integer to indicate if recursion is allowed
* @global string the topic at hand in the AIML file
*
* @param resource $parser SAX XML resource handler
* @param string $name name of the encountered tag.
* @param array $attrs contains the additional attribues of a tag, like value, id, find.
*
* @return void
*/
function startElement($parser, $name, $attrs)
{
global $whaton,$template,$pattern,$recursive,$topic;
if (strtoupper($name)=="CATEGORY"){
$whaton="CATEGORY";
}
elseif (strtoupper($name)=="TEMPLATE"){
$whaton="TEMPLATE";
$template="";
$recursive=0;
}
elseif (strtoupper($name)=="PATTERN"){
$whaton="PATTERN";
}
elseif ((strtoupper($name)=="THAT")&&(strtoupper($whaton)!="TEMPLATE")){
$whaton="THAT";
}
elseif (strtoupper($name)=="TOPIC"){
$whaton="TOPIC";
}
if ((strtoupper($whaton)=="PATTERN")&&(strtoupper($name)!="PATTERN")){
if (strtoupper($name)=="BOT"){
$attrs = upperkeysarray($attrs);
$pattern .= getbotvalue($attrs["NAME"]);
}
else{
$pattern .= "<$name";
while (list ($key, $val) = each ($attrs)) {
$pattern .= " $key=\"$val\" ";
}
$pattern .= ">";
}
}
elseif ((strtoupper($whaton)=="TEMPLATE")&&(strtoupper($name)!="TEMPLATE")){
$template .="<$name";
while (list ($key, $val) = each ($attrs)) {
$template .= " $key=\"$val\" ";
}
$template .=">";
}
elseif (strtoupper($whaton)=="TOPIC"){
$attrs = upperkeysarray($attrs);
$topic=$attrs["NAME"];
}
}
/**
* Used by the AIML XML parser
*
* Looks for the end tags of 'topic' and 'category'.
*
* @uses insertmysentence()
* @uses insertmytemplate()
*
* @global string which tag is being processed
* @global string
* @global string
* @global integer to indicate if recursion is allowed
* @global string the topic at hand in the AIML file
* @global string the that of the category.
*
* @param resource $parser SAX XML resource handler
* @param string $name name of the encountered tag.
*
* @return void
*/
function endElement($parser, $name)
{
global $whaton,$pattern,$template,$recursive,$topic,$that;
if (strtoupper($name)=="TOPIC"){
$topic="";
}
if (strtoupper($name)=="CATEGORY"){
$template=trim($template);
$topic=trim($topic);
$that=trim($that);
$pattern=trim($pattern);
if ($that==""){
$that="*";
}
if ($topic==""){
$topic="*";
}
if ($pattern==""){
$pattern="*";
}
$mybigsentence="<input> $pattern <that> $that <topic> $topic";
$idused=insertmysentence($mybigsentence);
insertmytemplate($idused,$template);
// IIS doesn't flush properly unless it has a bunch of characters in it. This fills it with spaces.
print " ";
flush();
$pattern="";
$template="";
$that="";
}
else {
if ((strtoupper($whaton)=="PATTERN")&&(strtoupper($name)!="PATTERN")){
if (strtoupper($name)!="BOT"){
$pattern .="</$name>";
}
}
elseif ((strtoupper($whaton)=="TEMPLATE")&&(strtoupper($name)!="TEMPLATE")){
$template .="</$name>";
}
}
}
/**
* Part of the AIML XML parser.
*
* Checks for start tags of pattern, topic, that, template and CDATA
*
* @global string
* @global string
* @global string
* @global string
* @global string
*
* @param resource $parser SAX XML resource handler
* @param string $data containing what needs to be parsed, I guess.
*
* @return void
*/
function handleme($parser, $data)
{
global $whaton,$pattern,$template,$topic,$that;
if (strtoupper($whaton)=="PATTERN"){
$pattern .= $data;
}
elseif (strtoupper($whaton)=="TOPIC"){
$topic .= $data;
}
elseif (strtoupper($whaton)=="THAT"){
$that .= $data;
}
elseif (strtoupper($whaton)=="TEMPLATE"){
$template .= $data;
}
elseif (strtoupper($whaton)=="TEMPLATE"){
$template .= "<![CDATA[$data]]>";
}
}
/**
* Parses startup.xml if the bot is loaded incrementally - one file at a time.
*
* Parses the startup.xml if the bot id loaded incrementally. One file at a time. This is very hacky and may not work properly.
*
* @uses learn()
*
* @global string The root directory of the AIML files?
* @global array This array will hold the files to LEARN
* @global boolean
* @global array Contains all the botnames.
* @global integer contains the selected bot ID.
*
* @param integer $fileid the ID of the file to be processed.
*/
function loadstartupinc($fileid){
global $rootdir,$learnfiles,$areinc,$allbots,$selectbot;
$areinc=0;
if ($fileid==1){
$areinc=1;
}
print "Loading startup.xml<BR>\n";
$learnfiles = array(); # This array will hold the files to LEARN
$file = $rootdir . "startup.xml";
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0);
xml_set_element_handler($xml_parser, "startS", "endS");
xml_set_character_data_handler ($xml_parser, "handlemeS");
if (!($fp = fopen($file, "r"))) {
die("could not open XML input");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
xml_parser_free($xml_parser);
# For each of the bots learn all of the files
$totalcounter=1;
foreach ($allbots as $bot){
# print "<b>Loading bot: $bot<BR></b>\n";
$single_learnfiles = $learnfiles[$bot];
$single_learnfiles = array_unique($single_learnfiles);
foreach ($single_learnfiles as $file) {
$selectbot=$bot;
if ($totalcounter==$fileid){
learn($file);
return 0;
}
$totalcounter++;
}
}
return 1;
}
/**
* Parses startup.xml
*
* Loads the startup.xml in the botloading process.
* XML parses the startup.xml file.
*
* @todo Seperate the XML reading from the processing code. Perhaps making a seperate class for this.
*
* @see botloader.php
* @see botloaderinc.php
* @uses learn()
* @uses startS()
* @uses endS()
* @uses handlemeS()
*
* @global string the rootdirectory
* @global array Files to be learned
* @global array All the different bots in the startup.xml file
* @global integer ID of the selected bot
* @global boolean ????
*
* @return void prints HTML
*/
function loadstartup()
{
global $rootdir,$learnfiles,$allbots,$selectbot,$areinc;
$areinc=1;
print "Loading startup.xml<BR>\n";
$learnfiles = array(); // This array will hold the files to LEARN
$file = $rootdir . "startup.xml";
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0);
xml_set_element_handler($xml_parser, "startS", "endS");
xml_set_character_data_handler ($xml_parser, "handlemeS");
if (!($fp = fopen($file, "r"))) {
die("could not open XML input");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
xml_parser_free($xml_parser);
# For each of the bots learn all of the files
foreach ($allbots as $bot){
print "<b>Loading bot: $bot<BR></b>\n";
$single_learnfiles = $learnfiles[$bot];
if( is_array($single_learnfiles) )
{
$single_learnfiles = array_unique($single_learnfiles);
foreach ($single_learnfiles as $file)
{
echo "<!-- " . str_pad("IE bufer flush ", 400, "+", STR_PAD_RIGHT) . " -->" ;//flush buffer for IE
flush();
$selectbot=$bot;
learn($file);
echo "<!-- " . str_pad("IE bufer flush ", 400, "+", STR_PAD_RIGHT) . " -->" ;//flush buffer for IE
flush();
}
}
}
}
/**
* Learn all the files in a directory ending with ".aiml"
*
* Read all the AIML filenames into the $learnfile Array. This array is then later on used by {@link learn()} in {@link handlemeS()}
*
* @global string the rootdirectory
* @global array contains all the filenames that need to be loaded into the bot.
*
* @param integer $curbot ID of the current bot.
*
* @return void
*/
function learnallfiles($curbot)
{
global $rootdir,$learnfiles;
global $thefiles;
if( is_array($thefiles) && sizeof($thefiles) > 0 )
{
foreach($thefiles as $k => $v)
{
$learnfiles[$curbot][] = $v . '.aiml';
}
}
else
{
$dir=opendir ($rootdir);
while ($file = readdir($dir)) {
if (substr($file,strpos($file,"."))==".aiml")
{
$learnfiles[$curbot][]=$file;
}
}
closedir($dir);
}
}
/**
* Learn the AIML string.
*
* XML parse the AIML string. It seems to have a hardcoded time limit of 600, presume seconds.
*
* @uses startElement()
* @uses endElement()
* @uses handleme()
*
* @param string $xmlstring the AIML category XML string
*
* @return void
*/
function learnstring($xmlstring)
{
@set_time_limit(600);
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler ($xml_parser, "handleme");
if (!xml_parse($xml_parser, $xmlstring)) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
xml_parser_free($xml_parser);
}
/**
* Learn an AIML file.
*
* Learn a single AIML XML file. Again, the hardcoded time limit is set to 600, presumably seconds.
*
* @uses startElement()
* @uses endElement()
* @uses handleme()
*
* @global string The root directory
*
* @param string $file The AIML file name.
*/
function learn($file)
{
flush();
global $rootdir,$templBuf;
@set_time_limit(600);
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser,XML_OPTION_CASE_FOLDING,0);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler ($xml_parser, "handleme");
print "Loading data aiml file: $file<BR>\n";
flush();
if (strtoupper(substr($file,0,7))=="HTTP://"){
$file=$file;
}
else {
$file=$rootdir . $file;
}
if (!($fp = fopen($file, "r"))) {
die("could not open XML input");
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($xml_parser, $data, feof($fp))) {
die(sprintf("XML error: %s at line %d",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser)));
}
}
fclose($fp);
xml_parser_free($xml_parser);
//---
//flush to my SQL last pattern block
$query="insert IGNORE into {$GLOBALS['fc_config']['db']['pref']}templates (bot,id,template,pattern,that,topic) values " . implode(',', $templBuf) ;
$qcode=mysql_query($query);
$templBuf = array();
//---
}
/**
* Start a timer
*
* Save the start time of the to be timed script
*
* @global array ss_timing_start_times contains the start moments of the script
*
* @param string $name default value is 'default' Makes it possibe to time more than
* event in one script.
*
* @return void nothing
*/
if(!function_exists('ss_timing_start'))
{
function ss_timing_start ($name = 'default') {
global $ss_timing_start_times;
$ss_timing_start_times[$name] = explode(' ', microtime());
}
}
/**
* Stop a timer
*
* Save the stop time of the to be timed script
*
* @global array ss_timing_stop_times contains the stop moments of a script
*
* @param string $name default value is 'default' Makes it possibe to time more than
* event in one script.
*
* @return void nothing
*/
if(!function_exists('ss_timing_stop'))
{
function ss_timing_stop ($name = 'default') {
global $ss_timing_stop_times;
$ss_timing_stop_times[$name] = explode(' ', microtime());
}
}
/**
* Retrieve timer data
*
* Get the running time the timed script
*
* @global array ss_timing_start_times contains the start and finish moments of the script
* @global array ss_timing_stop_times contains the stop moments of a script
*
* @param string $name default value is 'default' Makes it possibe to time more than
* event in one script.
*
* @return string the formated running time of the timed stript.
*/
if(!function_exists('ss_timing_current'))
{
function ss_timing_current ($name = 'default') {
global $ss_timing_start_times, $ss_timing_stop_times;
if (!isset($ss_timing_start_times[$name])) {
return 0;
}
if (!isset($ss_timing_stop_times[$name])) {
$stop_time = explode(' ', microtime());
}
else {
$stop_time = $ss_timing_stop_times[$name];
}
// do the big numbers first so the small ones aren't lost
$current = $stop_time[1] - $ss_timing_start_times[$name][1];
$current += $stop_time[0] - $ss_timing_start_times[$name][0];
return $current;
}
}
/**
* Creates the PHP array code for subs.inc.
*
* Subs.inc contains PHP code written during the bot load process. This function creates the array PHP code and returns the code as a string.
*
* @uses cleanforsearch()
* @uses cleanforreplace()
*
* @param array is an array with either gender, person(2), input and splitter details
* @param string which array is being processed, is also the array namein subs.inc.
*
* @return string the array PHP code
*/
function makesrphp($inarray,$sname)
{
$myphp="\$" . $sname . "search=array(\n";
for ($x=0;$x<sizeof($inarray);$x++){
$searchvar=cleanforsearch($inarray[$x][0]);
$beginsearch="";
$endsearch="";
if (substr($searchvar,0,1)==" "){
$beginsearch="\\b";
}
if ((substr($searchvar,strlen($searchvar)-1,1))==" "){
$endsearch="\\b";
}
$myphp.="\"/$beginsearch" . trim($searchvar) . "$endsearch/ie\",\n";
}
$myphp.=");\n";
$myphp.="\$" . $sname . "replace=array(\n";
for ($x=0;$x<sizeof($inarray);$x++){
$myphp.="\"myfunc('" . cleanforreplace($inarray[$x][1]) . "')\",\n";
}
$myphp.=");\n";
return $myphp;
}
/**
* Load an AIML string. String must be valid XML.
*
* This is going to need to take bot as a parameter
*
* @uses flushcache()
* @uses learnstring()
*
* @global integer bot ID.
*
* @param string $aimlstring The AIML string to be loaded.
* @param integer $botid The bot's ID.
*
* @return void
*/
function loadaimlstring($aimlstring,$botid)
{
global $selectbot;
$selectbot=$botid;
flushcache();
learnstring($aimlstring);
}
/**
* Load an AIML string that is just a category.
*
* This is going to need to take bot as a parameter
*
* @uses flushcache()
* @uses learnstring()
*
* @global integer bot ID.
*
* @param string $aimlstring The AIML string to be loaded.
* @param integer $botid The bot's ID.
*
* @return void
*/
function loadaimlcategory($aimlstring,$botid)
{
global $selectbot;
$selectbot=$botid;
$aimlstring="<?xml version=\"1.0\" encoding=\"ISO-8859-1\"" . "?" . "><aiml version=\"1.0\">" . $aimlstring . "</aiml>";
flushcache();
learnstring($aimlstring);
}
/**
* Create the array PHP code for the sentence splitters
*
* In AIML it is custom to return a reply for every sentence the user inputs.
* This means the sentence input needs to be split into individual sentences.
* However, some people find that the semi-colon should also be added, while
* others think it should. The user will define the sentence splitters in
* startup.xml and these will then be stored in a PHP file included by the
* application.
*
* @param array $splitterarray containing the sentence splitters found in startup.xml
*
* @return string PHP array code for storing the sentence splitters
*/
function makesplitterphp($splitterarray)
{
$splitterphp="\$likeperiodsearch=array(\n";
for ($x=0;$x<sizeof($splitterarray);$x++){
$splitterphp.="\"" . $splitterarray[$x] . "\",\n";
}
$splitterphp.=");\n";
$splitterphp.="\$likeperiodreplace=array(\n";
for ($x=0;$x<sizeof($splitterarray);$x++){
$splitterphp.="\"" . "." . "\",\n";
}
$splitterphp.=");\n";
return $splitterphp;
}
/**
* Add slashes for replacement purposes
*
* Making a string safe to preform a replacement function on.
*
* @param string $input string to be cleaned.
*
* @return string cleaned string.
*/
function cleanforreplace($input)
{
$input = str_replace("\\", "\\\\", $input);
$input = str_replace("\"", "\\\"", $input);
$input = str_replace("'", "\'", $input);
return trim($input);
}
/**
* Add slashes for database query purpose
*
* Making a string safe to put the text in an SQL query.
*
* @param string $input string to be cleaned.
*
* @return string cleaned string.
*/
function cleanforsearch($input)
{
$input = str_replace("\\", "\\\\\\\\", $input);
$input = str_replace("\"", "\\\"", $input);
$input = str_replace("'", "\'", $input);
$input = str_replace("/", "\/", $input);
$input = str_replace("(", "\(", $input);
$input = str_replace(")", "\)", $input);
$input = str_replace(".", "\.", $input);
return $input;
}
/**
* Creates the subs.inc file.
*
* Creates the subs.inc file and fills it with 5 arrays that correspond to the 4 substitution sections and sentence splitters.
*
* @uses makesrphp()
* @uses makesplitterphp()
* @uses createsubfile()
* @uses addtosubs()
*
* @global array contains the gender substitutions
* @global array contains the person substitutions
* @global array contains the person2 substitutions
* @global array ?????
* @global array contains the sentence splitters
*
* @return void Writes a file.
*/
function makesubscode()
{
global $genderarray,$personarray,$person2array,$inputarray,$splitterarray;
$genderphp = makesrphp($genderarray, "gender");
$personphp = makesrphp($personarray, "firstthird");
$person2php = makesrphp($person2array, "firstsecond");
$inputphp = makesrphp($inputarray, "contract");
$splitterphp = makesplitterphp($splitterarray);
createsubfile();
addtosubs("<?\n");
addtosubs($genderphp);
addtosubs($personphp);
addtosubs($person2php);
addtosubs($inputphp);
addtosubs($splitterphp);
addtosubs("\n?>");
}
?>