/** * function clean_for_eval() * This function cleans the generated code so that it can be safely evaluated as PHP * @param string $parsed_template - this is the code which was generated by interpreting the aiml * @param int $count - this function is called twice (once by itself) this value is the number of times it has run * @return string $parsed_template (after the clean) **/ function clean_for_eval($parsed_template, $count = 0) { runDebug(__FILE__, __FUNCTION__, __LINE__, "Cleaning the generated code for evaluating (running " . ($count + 1) . " time)", 4); $new_parsed_template = ""; $end = "\r\n\r\n\$botsay = \$tmp_botsay;\r\n"; if ($count == 0) { $parsed_template = foreignchar_replace('encode', $parsed_template); $parsed_template = entity_replace("encode", $parsed_template); } $parsed_template = $parsed_template . "';\r\n"; $parsed_template = "\r\n\$tmp_botsay = \"\";\r\n" . $parsed_template . "';\r\n"; $parsed_template = preg_replace("/\r\n\\'.call_user_func/", '$tmp_botsay .= call_user_func', $parsed_template); $parsed_template = preg_replace("/\r\n(\\s|\\s+)?\\'.call_user_func/", '$tmp_botsay .= call_user_func', $parsed_template); $parsed_template = preg_replace('/\\s\\s+/', ' ', $parsed_template); $parsed_template = str_replace("';';", "';", $parsed_template); $parsed_template = str_replace(";';", "';", $parsed_template); $parsed_template = str_replace(";", ";\r\n", $parsed_template); $parsed_template = str_replace("]';", "];", $parsed_template); $parsed_template = str_replace("close_bracket. '.", 'close_bracket.', $parsed_template); $parsed_template = str_replace("',' '.", "',", $parsed_template); $parsed_template = str_replace("',' '.", "',", $parsed_template); $parsed_template = str_replace(".''close_bracket", "close_bracket", $parsed_template); $parsed_template = str_replace("close_bracket.''", "close_bracket", $parsed_template); $parsed_template = str_replace("close_bracket. 'close_bracket", "close_bracketclose_bracket", $parsed_template); $parsed_template = str_replace(".' 'close_bracket", "close_bracket", $parsed_template); $parsed_template = str_replace(".' .", ".", $parsed_template); $parsed_template = str_replace("\r\n.", "\$tmp_botsay .= ", $parsed_template); $parsed_template = str_replace("\r\n';", "\r\n", $parsed_template); $parsed_template = str_replace("\r\n ';", "\r\n", $parsed_template); $parsed_template = str_replace(">. call", ">'. call", $parsed_template); $parsed_template = str_replace("> . call", ">' . call", $parsed_template); $parsed_template = str_replace("close_bracket.';", "close_bracket;", $parsed_template); $parsed_template = str_replace("''.", "", $parsed_template); $parsed_template = str_replace("\r\n'.call", "\$tmp_botsay .= call", $parsed_template); $parsed_template = str_replace("\r\n '.call", "\$tmp_botsay .= call", $parsed_template); $parsed_template = str_replace("\r\n '.call", "\$tmp_botsay .= call", $parsed_template); $parsed_template = str_replace("\$condition = \"\"", "\r\n\$condition=\"\"", $parsed_template); $parsed_template = str_replace("\"\";\$tmp_botsay", "\"\";\r\n\$tmp_botsay", $parsed_template); $parsed_template = str_replace("\$tmp_botsay", "\r\n\$tmp_botsay", $parsed_template); $parsed_template = str_replace("close_bracket.' ;", "close_bracket;", $parsed_template); $parsed_template = str_replace('$tmp_botsay .= \' if', 'if', $parsed_template); $parsed_template = str_replace(".'. \r\n", ".'. ';\r\n", $parsed_template); $parsed_template = str_replace("close_bracket.' \r\n", "close_bracket; ", $parsed_template); $parsed_template = str_replace("close_bracket';", "close_bracket;", $parsed_template); $parsed_template = str_replace("close_bracket.\\\"';", "close_bracket.'\\\"';", $parsed_template); //TODO BE CAREFULL this might break things ... needed for learn.aiml $parsed_template = str_replace("close_bracket.'close_bracket;", "close_bracket close_bracket;", $parsed_template); $linebyline = explode("\r\n", $parsed_template); foreach ($linebyline as $index => $value) { if (trim($value) == "\$tmp_botsay .= ' ;" || trim($value) == "\$botsay =" || trim($value) == "\$tmp_botsay;" || trim($value) == "\$tmp_botsay .= '" || trim($value) == "';" || trim($value) == ";" || trim($value) == '$tmp_botsay=\' ;' || trim($value) == '$tmp_botsay=\'') { } else { runDebug(__FILE__, __FUNCTION__, __LINE__, "Balancing open/close brackets", 4); $bracketed_value = best_guess_bracket_clean($value); $new_parsed_template .= $bracketed_value . "\r\n"; } } $parsed_template = str_replace('~apos~', "\\'", $new_parsed_template); $parsed_template = str_replace("tmp_botsay=' \$tmp_botsay .= call", "tmp_botsay .= call", $parsed_template); $parsed_template = str_replace("tmp_botsay=' \$tmp_botsay .= ", "tmp_botsay .= '", $parsed_template); $parsed_template = str_replace("\r\n').' '.call", "\r\n\$tmp_botsay .= call", $parsed_template); $parsed_template .= $end; if ($count == 0) { $count++; runDebug(__FILE__, __FUNCTION__, __LINE__, "Re-Clean just in case", 4); $parsed_template = clean_for_eval($parsed_template, $count); } else { $parsed_template = replace_conflicting_htmltags($parsed_template); $parsed_template = entity_replace("decode", $parsed_template); $parsed_template = foreignchar_replace('decode', $parsed_template); } $parsed_template = clean_smilies($parsed_template); $parsed_template = preg_replace('/\\s\\s+/', ' ', $parsed_template); return $parsed_template; }
/** * function aiml_to_phpfunctions() * This function performs a big find and replace on the aiml to convert it to php code * @param array $convoArr - the existing conversation array * @return array $convoArr **/ function aiml_to_phpfunctions($convoArr) { //TODO do we need this still? global $botsay, $srai_iterations, $error_response; //TODO read from bot vars runDebug(__FILE__, __FUNCTION__, __LINE__, "Converting the AIML to PHP code", 4); //extra debug info $msg = ""; $useStoredPHP = $convoArr['conversation']['use_aiml_code']; $uac = $convoArr['conversation']['update_aiml_code']; #$uac = 0; if ($convoArr['aiml']['aiml_to_php'] == "") { $msg .= " php code does not exist,"; } else { $msg .= " php code exists,"; } if ($useStoredPHP == 1) { $msg .= " Use stored php code is set to YES({$useStoredPHP})"; } else { $msg .= " Use stored php code is set to NO({$useStoredPHP})"; } if ($uac == 1) { $msg .= " update aiml to php is set to YES({$uac})"; } else { $msg .= " update aiml to php is set to NO({$uac})"; } //THIS MAY already have the code contained in the db in which case we can skip all of this //UNLESS - update_aiml_code is set to 1 this means we want to re-write it each time if ($convoArr['aiml']['aiml_to_php'] != "" and $uac == 0 and $useStoredPHP == 1) { runDebug(__FILE__, __FUNCTION__, __LINE__, "Using existing AIML to PHP code - {$msg}", 2); $parsed_template = get_convo_var($convoArr, 'aiml', 'aiml_to_php'); } else { runDebug(__FILE__, __FUNCTION__, __LINE__, "Generating new AIML to PHP code - {$msg}", 2); //load the existing aiml template $template = get_convo_var($convoArr, 'aiml', 'template'); //make stars, apostrophes and encode foriegn chars just to make everything safe before the big replace $template = str_replace("*", "\\*", $template); $template = str_replace("'", '~apos~', $template); $template = foreignchar_replace('encode', $template); $template = entity_replace('encode', $template); $i = 0; //to do this is in the add custom tags thing //start the find and replace $template = preg_replace('#<bot name="([^"]*)"/>#ie', "\$convoArr['bot_properties']['\$1']", $template); runDebug(__FILE__, __FUNCTION__, __LINE__, "Made initial bot property replacements", 4); $find[$i] = '#</say>#i'; $replace[$i] = '\';'; $i++; $find[$i] = '#<template>(\\s)*?</template>#i'; $replace[$i] = ''; $i++; $find[$i] = '#<template/>#i'; $replace[$i] = ''; $i++; $find[$i] = '#<say>#i'; $replace[$i] = '$tmp_botsay .= \''; $i++; $find[$i] = '#<bot name="([^"]*)"/>#i'; $replace[$i] = '\'.call_user_func(\'get_convo_var\',$convoArr,\'bot_properties\',\'$1\').\''; $i++; $find[$i] = '#<date format="([^"]*)"/>#i'; $replace[$i] = '\'.call_user_func(\'get_formatted_date\',\'$1\').\''; $i++; $find[$i] = '#<bigthink></bigthink>#i'; $replace[$i] = '; $tmp_botsay = ""; '; $i++; $find[$i] = '#<pushstack>(.*)([^<]*)</pushstack>#'; $replace[$i] = '\'.call_user_func(\'push_stack\',$convoArr,\'$1\').\''; $i++; $find[$i] = '#PUSH\\s?<([^>]*)>#'; $replace[$i] = '\'.call_user_func(\'push_stack\',$convoArr,\'<$1>\').\''; $i++; $find[$i] = '#POP\\s?<([^>]*)>#'; $replace[$i] = '\'.call_user_func(\'pop_stack\',$convoArr).\''; $i++; $find[$i] = '#<popstack></popstack>#'; $replace[$i] = '\'.call_user_func(\'pop_stack\',$convoArr).\''; $i++; $find[$i] = '#<personf/>#i'; $replace[$i] = '\'.call_user_func(\'url_encode_star\',$convoArr).\''; $i++; $find[$i] = '#<topic name=\\"(A-Z0-9)\\">#i'; $replace[$i] = '\'.call_user_func(\'set_topicname\',$convoArr,\'$1\').\''; $i++; $find[$i] = '#<star index="([^"]*?)"/>#i'; $replace[$i] = '\'.call_user_func(\'get_convo_var\',$convoArr,\'star\',\'\',\'$1\').\''; $i++; $find[$i] = '#<that index="(.*?),(.*?)"/>#i'; $replace[$i] = '\'.call_user_func(\'get_convo_var\',$convoArr,\'that\',\'\',\'$1\',\'$2\').\''; $i++; $find[$i] = '#<input index="([^"]*)"/>#i'; $replace[$i] = '\'.call_user_func(\'get_convo_var\',$convoArr,\'input\',\'\',\'$1\').\''; $i++; $find[$i] = '#<thatstar index="([^"]*)"/>#i'; $replace[$i] = '\'.call_user_func(\'get_convo_var\',$convoArr,\'that_star\',\'\',\'$1\').\''; $i++; $find[$i] = '#<topicstar index="([^"]*)"/>#i'; $replace[$i] = '\'.call_user_func(\'get_convo_var\',$convoArr,\'topic_star\',\'\',\'$1\').\''; $i++; $find[$i] = '#<get name="topic"(\\s)?(/)?>#i'; $replace[$i] = '\'.call_user_func(\'get_convo_var\',$convoArr,\'topic\').\''; $i++; $find[$i] = '#<get name="([^"]*)"(/)?>#i'; $replace[$i] = '\'.call_user_func(\'get_convo_var\',$convoArr,\'client_properties\',\'$1\').\''; $i++; $find[$i] = '#<id/>#i'; $replace[$i] = '\'.call_user_func(\'get_convo_var\',$convoArr,\'client_properties\',\'id\').\''; $i++; $find[$i] = '#<uppercase>([^<]*)</uppercase>#i'; $replace[$i] = '\'.call_user_func(\'format\',\'uppercase\',\'$1\').\''; $i++; $find[$i] = '#<lowercase>([^<]*)</lowercase>#i'; $replace[$i] = '\'.call_user_func(\'format\',\'lowercase\',\'$1\').\''; $i++; $find[$i] = '#<formal>([^<]*)</formal>#i'; $replace[$i] = '\'.call_user_func(\'format\',\'formal\',\'$1\').\''; $i++; $find[$i] = '#<sentence>([^<]*)</sentence>#i'; $replace[$i] = '\'.call_user_func(\'format\',\'sentence\',\'$1\').\''; $i++; $find[$i] = '#<srai>#i'; $replace[$i] = '\'.call_user_func(\'run_srai\',$convoArr,\''; $i++; $find[$i] = '#</srai>#i'; $replace[$i] = '\').\''; $i++; $find[$i] = '#<think>#i'; $replace[$i] = '\'.call_user_func(\'make_null\',\''; $i++; $find[$i] = '#</think>#i'; $replace[$i] = '\').\''; $i++; $find[$i] = '#<person>([^<]*)</person>#i'; $replace[$i] = '\'.call_user_func(\'transform_prounoun\',$convoArr,\'3\',\'$1\').\''; $i++; $find[$i] = '#<person2>([^<]*)</person2>#i'; $replace[$i] = '\'.call_user_func(\'transform_prounoun\',$convoArr,\'2\',\'$1\').\''; $i++; $find[$i] = '#<condition>[\\s]?<li name="([^"]*)" value="([^"]*)">#i'; $replace[$i] = "';\r\n" . ' if( ((isset($convoArr[\'$1\'])) && (strtoupper($convoArr[\'$1\']) === strtoupper(\'$2\'))) || ((isset($convoArr[\'client_properties\'][\'$1\'])) && (strtoupper($convoArr[\'client_properties\'][\'$1\']) === strtoupper(\'$2\'))) )' . "\r\n" . ' { $tmp_botsay .= \''; $i++; $find[$i] = '#<condition name="([^"]*)">#i'; $replace[$i] = "\r\n" . '; $condition = call_user_func(\'clean_condition\',\'$1\'); '; $i++; $find[$i] = '#<li name="([0-9a-z]*)" value="([0-9a-z]*)">#i'; $replace[$i] = "\r\n" . ' elseif( ((isset($convoArr[\'$1\'])) && (strtoupper($convoArr[\'$1\']) === strtoupper(\'$2\'))) || ((isset($convoArr[\'client_properties\'][\'$1\'])) && (strtoupper($convoArr[\'client_properties\'][\'$1\']) === strtoupper(\'$2\'))) )' . "\r\n" . ' { $tmp_botsay .= \''; $i++; $find[$i] = '#<li value="([^"]*)">#i'; $replace[$i] = "\r\n" . ' elseif( ((isset($convoArr[$condition])) && (strtoupper($convoArr[$condition]) === strtoupper(\'$1\'))) || ((isset($convoArr[\'client_properties\'][$condition])) && (strtoupper($convoArr[\'client_properties\'][$condition]) === strtoupper(\'$1\'))) )' . "\r\n" . ' { $tmp_botsay .= \''; $i++; $find[$i] = '#;(\\s|\\s+)?elseif#i'; $replace[$i] = ";\r\nif"; $i++; $find[$i] = "#<\random>(\\?|\\.|\\!\\s)?</li>#eis"; $replace[$i] = '</random>$1\';}'; //this has to be be evalutated immeditately as nothing will change we are just collecting a random value $i++; $find[$i] = "#<random>([^<]*)</random>#eis"; $replace[$i] = 'call_user_func(\'select_random\',\'$1\')'; // this needs a second attempt before i work out a proper fix // the first removes the out random but if there is a nested random it wont work $i++; $find[$i] = "#<random>(.*)</random>#eis"; $replace[$i] = 'call_user_func(\'select_random\',\'$1\')'; $i++; $find[$i] = '#<li>(.*)</li>#i'; $replace[$i] = "\r\n" . 'else { $tmp_botsay .=\'$1\'; } '; $i++; $find[$i] = '#</li>#i'; $replace[$i] = '\'; } '; $i++; $find[$i] = '#</condition>#i'; $replace[$i] = "\r\n" . '$condition = ""; '; //TODO WORK OUT WHY THIS OCCURES $i++; $find[$i] = '#</conditio#i'; $replace[$i] = "\r\n" . '$condition = ""; '; $i++; $find[$i] = '#<set name="([^"]*)">#i'; $replace[$i] = '\'.call_user_func(\'set_simple\',$convoArr,\'$1\',\''; $i++; $find[$i] = '#<set name=\\\\"([^\\\\]*)\\\\">#i'; $replace[$i] = '\'.call_user_func(\'set_simple\',$convoArr,\'$1\',\''; $i++; $find[$i] = '#</set>#i'; $replace[$i] = '\').\''; $i++; $find[$i] = '#</get>#i'; $replace[$i] = ''; $i++; $find[$i] = '#<system>\\s?(add|power|sqrt|divide|multiply|subtract)\\s?(.*)[\\s?](.*)</system>#i'; $replace[$i] = '\'.call_user_func(\'run_system\',\'$1\',\'$2\',\'$3\').\''; $i++; $find[$i] = '#<learn>\\s+?<category>\\s+?<pattern>\\s+?<eval>([^<]*)</eval>\\s+?</pattern>\\s+?<template>\\s+?<eval>([^<]*)</eval>\\s+?</template>\\s+?</category>\\s+?</learn>#ius'; $replace[$i] = '\'; call_user_func(\'make_learn\',$convoArr,\'$1\',\'$2\');'; runDebug(__FILE__, __FUNCTION__, __LINE__, "Built core tag array to make replacements", 4); //custom tags handled here $custom_tag_handle = custom_aiml_to_phpfunctions($find, $replace, $i); $find = $custom_tag_handle['find']; $replace = $custom_tag_handle['replace']; runDebug(__FILE__, __FUNCTION__, __LINE__, "Built custom tag array to make replacements", 4); runDebug(__FILE__, __FUNCTION__, __LINE__, "Looking to replace: " . print_r($find, true), 4); runDebug(__FILE__, __FUNCTION__, __LINE__, "With replacements: " . print_r($replace, true), 4); //actually do the find and replace here $parsed_template = preg_replace($find, $replace, $template); //clean up the find/replace code so that it can actaully evaluate as real php code $parsed_template = clean_for_eval($parsed_template, 0); //decode back before sending $parsed_template = entity_replace('decode', $parsed_template); $parsed_template = foreignchar_replace('decode', $parsed_template); //write to convoArr $convoArr['aiml']['aiml_to_php'] = $parsed_template; //update the aiml table $convoArr = add_aiml_to_php($convoArr); } //evaluate the generated code $botsay = eval_aiml_to_php_code($convoArr, $parsed_template); //if it works it works if not display error message //write the result (what the bot said) to the convoArr $convoArr['aiml']['parsed_template'] = $botsay . " "; runDebug(__FILE__, __FUNCTION__, __LINE__, "The bot will say: {$botsay}", 2); return $convoArr; }