function do_handle_upload() { if ($_FILES['data_file']['error'] === UPLOAD_ERR_OK) { $file_name = $_FILES['data_file']['name']; $extension = pathinfo($file_name); if (!isset($extension['extension'])) { $extension = ''; } else { $extension = strtolower($extension['extension']); } if ($extension != 'aiml') { print '<p>Invalid file format.</p>'; } else { $in_dest = JxBotConfig::aiml_dir() . $file_name; if (!@move_uploaded_file($_FILES['data_file']['tmp_name'], $in_dest)) { print '<p>Couldn\'t save file. Check the permissions on the aiml directory.</p>'; } else { //print '<p>File uploaded successfully.</p>'; JxBotNLData::set_file_status($file_name, 'Not Loaded'); } } } else { print '<p>Error uploading file.</p>'; } }
private static function sentence_respond(&$in_input) { /* find a category for the input */ $start_time = microtime(true); $match = JxBotEngine::match($in_input, JxBotConverse::history_response(0), JxBotConverse::predicate('topic')); $end_time = microtime(true); JxBotConverse::$match_time += $end_time - $start_time; /* check recursion */ $category = $match === false ? -1 : $match->matched_category(); $count = 0; foreach (JxBotConverse::$category_stack as $nested_category) { if ($nested_category == $category) { $count++; } } if ($count >= JxBotConverse::MAX_CATEGORY_NESTING) { //print 'CATEGORY LIMIT<br>'; return ''; } JxBotConverse::$category_stack[] = $category; if ($match === false) { /* no match was found; the input was not understood and no default category is available */ $output = '???'; } else { /* select a template at random */ //print 'MATCHED CATEGORY '.$category.'<br>'; $template = JxBotNLData::fetch_templates($category); $count = count($template); if ($count == 0) { $output = '???'; } else { if ($count == 1) { $index = 0; } else { $index = mt_rand(1, $count) - 1; } $output = $template[$index][1]; } if (JxBotConverse::$srai_level == 1) { JxBotConverse::$iq_score += $match->iq_score(); } } /* generate the template */ $template = JxBotAiml::parse_template($output); $output = $template->generate($match); /* track recursion */ array_pop(JxBotConverse::$category_stack); return $output; }
public static function pattern_add($in_category_id, $in_text, $in_that, $in_topic) { //print 'PATTERN: '.$in_text.' : '.$in_that.' : '.$in_topic.'<br>'; //return; $in_full = $in_text . ' : ' . $in_that . ' : ' . $in_topic; $translator = new JxBotAimlPattern(); $in_full = $translator->translate($in_full); //$in_full = JxBotAiml::translate_pattern_tags($in_full); $terms = JxBotNL::normalise_pattern($in_full); $in_full = JxBotNL::upper($in_full); $count = count($terms); $last_node = 0; /* root of graph */ for ($index = 0; $index < $count; $index++) { $expression = $terms[$index]; /*if ($last_node === NULL) { $stmt = JxBotDB::$db->prepare('SELECT id FROM pattern_node WHERE parent IS NULL AND expression=?'); $stmt->execute(array($expression)); } else {*/ $stmt = JxBotDB::$db->prepare('SELECT id FROM pattern_node WHERE parent=? AND expression=?'); $stmt->execute(array($last_node, $expression)); //} $existing = $stmt->fetchAll(PDO::FETCH_NUM); if (count($existing) == 0) { $stmt = JxBotDB::$db->prepare('INSERT INTO pattern_node (parent, expression, sort_key, is_terminal) VALUES (?, ?, ?, ?)'); $sort_key = JxBotNLData::make_sort_key($expression); $stmt->execute(array($last_node, $expression, $sort_key, $index + 1 >= $count ? 1 : 0)); $last_node = JxBotDB::$db->lastInsertId(); if (($sort_key == 5 || $sort_key == 0) && $expression != ':' && !is_numeric($expression) && trim($expression) != '') { JxBotNLData::word_add_lookup($expression); } } else { $last_node = $existing[0][0]; if ($index + 1 >= $count) { $stmt = JxBotDB::$db->prepare('UPDATE pattern_node SET is_terminal=1 WHERE id=?'); $stmt->execute(array($last_node)); } } } try { $stmt = JxBotDB::$db->prepare(' INSERT INTO pattern (id, category, value, that, topic, term_count) VALUES (?, ?, ?, ?, ?, ?)'); $stmt->execute(array($last_node, $in_category_id, $in_text, $in_that, $in_topic, count($terms) - 2)); } catch (Exception $err) { /* detected duplicate pattern */ // for now, just ignore throw new Exception('Pattern already exists.'); //print 'Duplicate pattern: '.$in_full.'<br>'; } return $last_node; }
function page_edit_tmpl() { $inputs = JxBotUtil::inputs('template'); $template = JxBotNLData::template_fetch($inputs['template']); ?> <?php JxWidget::hidden('category', $template['category']); JxWidget::hidden('tmpl-id', $template['id']); ?> <h2>Edit Template</h2> <p><?php JxWidget::memofield('template', 'Template', $template['template'], 5, true); ?> </p> <p><?php JxWidget::button('Cancel', 'action', 'edit'); ?> <?php JxWidget::button('Save Template', 'action', 'save-tmpl'); ?> </p> <?php }
public function generate($in_context) { switch ($this->name) { case 'system': /* security implications; will not implement until reasonable controls are developed and an on/off switch */ /* security implications; will not implement until reasonable controls are developed and an on/off switch */ case 'javascript': /* server-side javascript is not implemented */ break; case 'think': $this->text_value($in_context); break; case 'template': case 'gossip': /* doesn't do anything in this AIML interpreter and is removed in AIML 2.0 */ /* doesn't do anything in this AIML interpreter and is removed in AIML 2.0 */ case 'x-learn-1': /* AIML 1 learn tag to be filtered on import and contents passed through without further action */ return $this->text_value($in_context); case 'random': $count = $this->child_element_count(); $index = mt_rand(1, $count) - 1; return $this->child_element($index)->text_value($in_context); case 'condition': $loop = false; // preparation for AIML 2 loop; will need to keep a stack & check the stack so it can be toggled // by a <loop/> element anywhere in the depth of the <li> do { $count = $this->child_element_count('li'); if ($count == 0) { $predicate = $this->child_or_attr_named($in_context, 'name'); $value = JxBotConverse::predicate($predicate); $pattern = $this->child_or_attr_named($in_context, 'value'); if (JxBotElement::matches_simple_pattern($value, $pattern)) { return $this->text_value($in_context, array('name', 'value')); } } else { $count = $this->child_element_count(); $predicate = $this->child_or_attr_named($in_context, 'name', null); if ($predicate !== null) { $value = JxBotConverse::predicate($predicate); for ($i = 0; $i < $count; $i++) { $item = $this->child_element($i); $pattern = $item->child_or_attr_named($in_context, 'value', null); if ($pattern === null) { return $item->text_value($in_context, array('value')); } if (JxBotElement::matches_simple_pattern($value, $pattern)) { return $item->text_value($in_context, array('value')); } } } else { for ($i = 0; $i < $count; $i++) { $item = $this->child_element($i); $predicate = $item->child_or_attr_named($in_context, 'name'); $value = JxBotConverse::predicate($predicate); $pattern = $item->child_or_attr_named($in_context, 'value', null); if ($pattern === null) { return $item->text_value($in_context, array('value', 'name')); } if (JxBotElement::matches_simple_pattern($value, $pattern)) { return $item->text_value($in_context, array('value', 'name')); } } } } } while ($loop); break; case 'star': case 'thatstar': case 'topicstar': $index = intval($this->child_or_attr_named($in_context, 'index', 1)); return $this->get_capture($in_context, $this->name, $index); case 'srai': return JxBotConverse::srai($this->text_value($in_context)); case 'sr': /* srai star /srai */ return JxBotConverse::srai($this->get_capture($in_context, 'star', 1)); case 'bot': case 'get': $name = trim($this->child_or_attr_named($in_context, 'name')); if ($name !== '') { if ($this->name == 'get') { return JxBotConverse::predicate($name); } else { if ($name == 'size') { return JxBotNLData::pattern_count(); } else { if ($name == 'age') { return JxBotElement::compute_age(); } else { if ($name == 'birthday') { return JxBotElement::birthday(); } else { return JxBotConfig::predicate($name); } } } } } break; case 'tag': /* non-standard Tag feature */ $name = trim($this->child_or_attr_named($in_context, 'name')); return $in_context->tag_value($name); case 'id': return JxBotConverse::predicate('id'); case 'size': /* we return the number of patterns, which is equivalent to AIML standard category count; since in JxBot one category != one pattern. */ return JxBotNLData::pattern_count(); case 'vocabulary': return JxBotNLData::word_count(); case 'version': return JxBot::VERSION; case 'program': return JxBot::PROGRAM . ' ' . JxBot::VERSION; case 'set': $name = trim($this->child_or_attr_named($in_context, 'name')); if ($name != '') { $value = $this->text_value($in_context, array('name')); JxBotConverse::set_predicate($name, $value); return $value; } break; case 'date': $php_format = 'r'; /* default - AIML 1.0 - we specify date & time format */ return date($php_format); case 'uppercase': return JxBotNL::upper($this->text_value($in_context)); case 'lowercase': return JxBotNL::lower($this->text_value($in_context)); case 'formal': return JxBotNL::formal($this->text_value($in_context)); case 'sentence': return JxBotNL::sentence($this->text_value($in_context)); case 'explode': return JxBotNL::explode($this->text_value($in_context)); case 'normalize': return JxBotNL::template_normalize($this->text_value($in_context)); case 'denormalize': return JxBotNL::template_denormalize($this->text_value($in_context)); case 'gender': if (count($this->children) == 0) { return JxBotNL::remap('gender', $this->get_capture($in_context, 'star', 1)); } return JxBotNL::remap('gender', $this->text_value($in_context)); case 'person': if (count($this->children) == 0) { return JxBotNL::remap('person', $this->get_capture($in_context, 'star', 1)); } return JxBotNL::remap('person', $this->text_value($in_context)); case 'person2': if (count($this->children) == 0) { return JxBotNL::remap('person2', $this->get_capture($in_context, 'star', 1)); } return JxBotNL::remap('person2', $this->text_value($in_context)); case 'map': $map_name = $this->child_or_attr_named($in_context, 'name'); return JxBotNL::remap($map_name, $this->text_value($in_context, array('name'))); case 'that': $indicies = JxBotElement::indicies($this->child_or_attr_named($in_context, 'index')); $in_response = count($indicies) >= 1 ? $indicies[0] : 1; $in_sentence = count($indicies) >= 2 ? $indicies[1] : 1; $response = JxBotConverse::history_response($in_response - 1); $sentences = JxBotNL::split_sentences($response); if ($in_sentence < 1 || $in_sentence > count($sentences)) { return ''; } return $sentences[$in_sentence - 1]; case 'input': $indicies = JxBotElement::indicies($this->child_or_attr_named($in_context, 'index')); $in_request = count($indicies) >= 1 ? $indicies[0] : 1; $in_sentence = count($indicies) >= 2 ? $indicies[1] : 1; $request = JxBotConverse::history_request($in_request - 1); $sentences = JxBotNL::split_sentences($request); if ($in_sentence < 1 || $in_sentence > count($sentences)) { return ''; } return $sentences[$in_sentence - 1]; case 'request': $index = intval($this->child_or_attr_named($in_context, 'index', 1)); return JxBotConverse::history_request($index - 1); case 'response': $index = intval($this->child_or_attr_named($in_context, 'index', 1)); return JxBotConverse::history_response($index - 1); default: /* push unknown content & tags through to output */ // ! REVIEW: A better policy might be to tightly control which tags are // allowed through, or provide an appropriate system option. return $this->flatten(); } }
public function import($in_filename) { /* reset the importer */ $this->reset(); /* open the file */ $fh = fopen($in_filename, 'r'); if (!$fh) { return "Server Error: Couldn't open AIML file."; } /* parse the file */ $size = filesize($in_filename); $bytes = 0; while ($data = fread($fh, 4096)) { if (!xml_parse($this->xml_parser, $data, feof($fh))) { $this->error(xml_error_string(xml_get_error_code($this->xml_parser))); break; } $bytes += 4096; if ($bytes > $size) { $bytes = $size; } $percent = number_format($bytes / $size * 100, 1); JxBotNLData::set_file_status(basename($in_filename), 'Loading ' . $percent . '%'); } xml_parse($this->xml_parser, '', true); fclose($fh); /* report errors */ if ($this->_error != '') { return $this->_error; } /* prepare additional notices */ if (count($this->unrecognised) > 0) { $this->notice('The following unrecognised tags were ignored: ' . implode(', ', array_keys($this->unrecognised)), true); } if ($this->has_aiml1_learn) { $this->notice('This AIML file expects the AIML 1.0 semantics of the learn tag, which are not supported by JxBot.', true); } if ($this->has_aiml1_gossip) { $this->notice('This AIML file utilises the old AIML 1.0 gossip tag, which is not supported by JxBot.', true); } if ($this->has_aiml2_learn) { $this->notice('This AIML file utilises the AIML 2.0 learn feature which is not yet supported by JxBot.', true); } if ($this->has_aiml2_sraix) { $this->notice('This AIML file utilises the AIML 2.0 sraix feature which is not yet supported by JxBot.', true); } if ($this->has_aiml2_loop) { $this->notice('This AIML file utilises the AIML 2.0 loop feature which is not yet supported by JxBot.', true); } if ($this->has_aiml2_interval) { $this->notice('This AIML file utilises the AIML 2.0 interval tag which is not yet supported by JxBot.', true); } if ($this->has_aiml_javascript) { $this->notice('This AIML file utilises the AIML server-side javascript feature, which is not supported by JxBot.', true); } if ($this->has_aiml_system) { $this->notice('This AIML file utilises the AIML system call feature, which is not yet supported by JxBot.', true); } if ($this->has_multi_pattern_cats) { $this->notice('This AIML file utilises the JxBot consolidated category representation, which may not be compatible with other AIML interpreters.', true); } if ($this->has_tag) { $this->notice('This AIML file utilises the JxBot tag feature, which may not be compatible with other AIML interpreters.', true); } /* return the result */ return $this->notices; }
protected function walk($in_parent_id, $in_term_index) { /* check search depth to prevent infinite recursion */ $this->search_depth++; if ($this->search_depth > JxBotEngine::MAX_SEARCH_DEPTH) { throw new Exception('Too much recursion (in pattern search)'); } /* look in this branch for all possible matching sub-branches; ie. an exact match with the input term, or, a wildcard or complex pattern term such as a bot property or AIML 2 'set' */ $stmt = JxBotDB::$db->prepare("SELECT id,expression,is_terminal FROM pattern_node \n\t\t\tWHERE parent=? AND ( (expression = ? AND sort_key IN (0,5)) OR (sort_key NOT IN (0,5)) ) \n\t\t\tORDER BY sort_key"); $current_term = $this->get_term($in_term_index); $stmt->execute(array($in_parent_id, $current_term)); $possible_branches = $stmt->fetchAll(PDO::FETCH_NUM); //print "Walk parent=$in_parent_id, term_index=$in_term_index, term=$current_term<br>"; //print '<pre>'; //var_dump($possible_branches); //print '</pre>'; foreach ($possible_branches as $possibility) { /* decode the possibility and prepare to match */ list($br_parent, $br_expr, $br_terminal) = $possibility; // in future, for speed, this information could be assessed at pattern registration // and stored & accessed, possibly using the sort key integer ? $is_wildcard = JxBotEngine::is_wildcard($br_expr); $set_ref = JxBotEngine::is_set_ref($br_expr); $bot_ref = JxBotEngine::is_bot_ref($br_expr); //print $br_expr; //print "Considering possible branch=$br_parent, expr=$br_expr, term=$br_terminal, wild=$is_wildcard :<br>"; // pattern side sets & bot tags will have to be handled similarly, since they may have multi-word values // basically, like wildcards, except all words must match /* branch to appropriate match handler depending on type of branch */ if ($bot_ref !== false || $set_ref !== false) { /* match: bot predicate or set reference: */ if ($bot_ref !== false) { $values = array(JxBotNL::normalise(JxBotConfig::bot($bot_ref))); $match = $this->try_match_values($br_parent, $values, false, $in_term_index, $br_terminal); } else { $values = JxBotNLData::set_values($set_ref); $match = $this->try_match_values($br_parent, $values, true, $in_term_index, $br_terminal); } } else { if (!$is_wildcard) { /* match: normal word or pattern clause separator: */ $match = $this->try_match_word($br_parent, $br_expr, $in_term_index, $br_terminal); } else { /* match: wildcard */ $match = $this->try_match_wildcard($br_parent, $br_expr, $in_term_index, $br_terminal); } } /* if matching was successful, return the matching pattern, otherwise, continue looking at sub-branches at this level */ if ($match !== false) { return $match; } } /* no possible subbranches; no match this branch */ $this->search_depth--; return false; }