|
|
|
This code supersedes #1585 and #1588
A base class and 2 derivated classes (pkg.dict.php) to generate clients for
dictionary servers that follow the DICT protocol (RFC 2229), such as the
server at dict.org
Included also 2 example of query interfaces generated using this classes, one
performs a simple search (simplesearch.php), and the other shows how to get
information from the dictionary server and use that to generate a form
allowing for more complex searches (extendedsearch.php).
[UPDATE: 2000/06/05] Fixed some bugs reported by Davor Cengija
<davor@croart.com> and found another bug related to URLs referred in the
definition that are also marked as crossrefence terms
[UPDTATE: 2000/06/06] Check for duplicates when creating the links, and
modified the external URLs regex to recognize more protocols, as well as
eliminate crossrefences to RFC's
NOTE: Separate the 3 files before using the examples.
::::::::::::::
pkg.dict.php
::::::::::::::
<?php
/*
* This set of classes implement a subset of the DICT protocol
* and it is meant to be use to generate clients that
* query a DICT server
*
* By default, the class uses the dict.org server in
* the port 2628.
*
* (c) 2000, Jesus M. Castagnetto <jmcastagnetto@zkey.com>
*
* License: GPL, see http://www.gnu.org/copyleft/gpl.txt
*
* Changes:
*
* 2000/06/04 - added the correct link to the GPL license
* 2000/06/05 - added the in_array() method to the base class
* from a suggestion by Davor Cengija <davor@croart.com>
* who pointed out that PHP gained the in_array()
* function in 3.0.12, and 4.0.0
*/
//============================================================
/*
* class DictBase
*
* Base class for implementing the DICT protocol to communicate
* with dictionary servers. It defaults to dict.org and port 2628.
*/
class DictBase {
var $host = "dict.org";
var $port = "2628";
var $max_length = 6144; // 1024 * 6 to cover UTC8 chars
var $socket;
var $valid_codes =
array (
110, 111, 112, 113, 114, 130, 150, 151, 152,
210, 220, 221, 230, 250,
330,
420, 421,
500, 501, 502, 503, 530, 531, 532,
550, 551, 552, 554, 555
);
var $return_code = array();
function DictBase() {
// empty constructor
}
function set($var, $val) {
$this->$var = $val;
}
function get($var) {
return $this->$var;
}
function parse_code($str) {
ereg("^([0-9]{3}) (.+)", $str, &$reg);
$error = ( $reg[1] >= 300 );
$this->return_code = array( "error"=>$error,
"code"=>$reg[1],
"desc"=>$reg[2]);
}
function is_valid_code() {
return $this->in_array($this->return_code["code"], $this->valid_codes);
}
function is_error_code() {
return $this->return_code["error"];
}
function print_code() {
$out = $this->is_error_code() ? "<ERROR> " : "";
$out .= "[".$this->return_code["code"]."] ".$this->return_code["desc"]."\n";
echo $out;
}
function connect() {
$fp = fsockopen($this->host, $this->port, &$errno, &$errstr, 90);
if (!$fp) {
echo "Cannot connect: ".$errno." = ".$errstr."\n";
exit;
} else {
$this->socket = $fp;
}
}
function close() {
fputs($this->socket, "QUIT\r\n");
$tmp = fgets($this->socket, $this->max_length);
fclose($this->socket);
}
function read_data() {
while ($read = fgets($this->socket, $this->max_length)) {
if (ereg("^\.\r\n$",$read))
break;
$out .= $read;
}
return $out;
}
// To support old PHP3 versions ( older than 3.0.12 )
// A point I forgot and Davor Cengija reminded me about
function in_array($element, $arr) {
// figure out version
list($major, $minor, $release) = explode(".", phpversion());
if (($major == 3 && $relesase >= 12) || $major == 4) {
return in_array($element, $arr);
} else {
// assumes that we want to compare element value
while (list($key, $val) = each($arr)) {
if ($val == $element)
return true;
}
return false;
}
}
} // end of base class Dict
//============================================================
/*
* Class DictServerInfo
*
* To generate objects containing DICT server information.
* Extends the DictBase class.
*/
class DictServerInfo extends DictBase {
var $info = array();
function DictServerInfo($host="", $port="", $extended=false) {
$this->init($host, $port, $extended);
}
function init($host, $port, $extended) {
if ($host)
$this->set("host", $host);
if ($port)
$this->set("port", $port);
$this->connect();
// get connection response line
$line = fgets($this->socket, $this->max_length);
$this->parse_code($line);
if ($this->is_error_code()) {
$this->print_code();
exit;
}
// extract capabilities info from response line
ereg("^[0-9]{3} (.*) <([^<]*)> <(.*)>", $line, &$reg);
$this->info["signature"] = $reg[1];
$this->info["capabilities"] = explode(".", $reg[2]);
$this->info["msg-id"] = $reg[3];
// get description on the server and store verbatim
$this->info["server"] = $this->show("SERVER");
// get the dbs and strategies for this server
$dbs = $this->show("DB");
$this->store("databases",$dbs);
$strats = $this->show("STRAT");
$this->store("strategies",$strats);
// get the description of each database
// if extended info is requested
if ($extended)
$this->get_dbs_info();
// close the connection
$this->close();
}
function show($str) {
fputs($this->socket, "SHOW ".$str."\r\n");
$tmp = chop(fgets($this->socket, $this->max_length));
$tmp2 = explode (" ", $tmp);
if ($str == "DB")
$this->info["num_dbs"] = (int) $tmp2[1];
if ($str == "STRAT")
$this->info["num_strat"] = (int) $tmp2[1];
$data = $this->read_data();
$tmp = fgets($this->socket, $this->max_length);
return $data;
}
function store($str, $data) {
$arr = explode("\r\n", $data);
$out = array();
for ($i=0; $i<count($arr); $i++) {
if (chop($arr[$i]) == "")
continue;
ereg("^([^ ]+) \"?([^\"]+)\"?", $arr[$i], &$reg);
$out[$reg[1]] = $reg[2];
}
$this->info[$str] = $out;
}
function get_dbs_info() {
$ndb = $this->info["num_dbs"];
$dbs = $this->info["databases"];
$dbinfo = array();
while (list($k, $v) = each($dbs)) {
$dbinfo[$k] = $this->show("INFO ".$k);
}
$this->info["dbs_desc"] = $dbinfo;
}
function get_info ($str) {
return $this->info[$str];
}
} // end of class DictServerInfo
//============================================================
/*
* class DictQuery
*
* To create query objects to search a DICT server
*/
class DictQuery extends DictBase {
var $term = "";
var $method = "exact";
var $searchdb = "*";
var $query_type = "DEFINE";
var $valid_methods = array ("exact", "prefix", "substring", "suffix",
"re", "regexp", "soundex", "lev");
var $result = array();
var $numres = 0;
function DictQuery($host="", $port="") {
$this->init($host, $port);
}
function init($host, $port) {
if ($host)
$this->set("host", $host);
if ($port)
$this->set("port", $port);
$this->connect();
// get connection response line
$line = fgets($this->socket, $this->max_length);
$this->parse_code($line);
if ($this->is_error_code()) {
$this->print_code();
exit;
}
}
function search($term, $method, $db) {
if (!$this->is_method($method)) {
echo "**ERROR** invalid method: ".$method."\n";
exit;
}
$this->clear_results();
$this->term = $term;
$this->method = $method;
$this->searchdb = $db;
$query = ($method=="exact") ? "DEFINE $db " : "MATCH $db $method ";
$query .= "\"".$term."\"\r\n";
fputs($this->socket, $query);
$line = fgets($this->socket, $this->max_length);
ereg("^[0-9]{3} ([0-9]+) .+", $line, &$reg);
$this->numres = (int) $reg[1];
if ($method != "exact") {
$rlist = $this->read_data();
$this->result = explode("\r\n", chop($rlist));
} else {
$regex = "^[0-9]{3} \"([^\"]+)\" ([^\" ]+) \"([^\"]+)\"";
$allres = array();
$entry = array();
for ($i=0; $i<$this->numres; $i++) {
$line = chop(fgets($this->socket, $this->max_length));
if ($line == "")
continue;
ereg($regex, $line, &$reg);
$entry["term"] = $reg[1];
$entry["dbcode"] = $reg[2];
$entry["dbname"] = $reg[3];
$entry["definition"] = $this->read_data();
$this->result[$i] = $entry;
}
}
}
function define($term, $db="*") {
$this->search($term, "exact", $db);
$this->close();
}
function match($term, $method="prefix", $db="*") {
$this->search($term, $method, $db);
$this->close();
}
function is_method($method) {
return $this->in_array($method, $this->valid_methods);
}
function clear_results() {
$this->numres = 0;
$this->result = array();
}
} // end of class DictQuery
?>
::::::::::::::
simplesearch.php
::::::::::::::
<!--
Simple example that uses pkg.dict.org
(c) 2000, Jesus M. Castagnetto <jmcastagnetto@zkey.com>
License: GPL, see www.gnu.org/copyleft/gpl.txt
Changes:
2000/06/04 - Added the correct link to the GPL license
2000/06/05 - Fixes to bugs reported by Davor Cengija <davor@croart.com>
(1) Links that look like {{UNIX}} were not being stripped
correctly
(2) Crossreference terms sometimes spanned a line break
which looked real ugly/bad
Thanks to Davor for reporting the bugs in this example
2000/06/05 - Found another bug, some crossreferences are to URLs and
not terms in the dictionaries, the makeLink() function has
been fixed to account for that.
2000/06/06 - Check for duplicates when creating the links, and modified
the external URLs regex to recognize more protocols, as well
as eliminate crossrefences to RFC's
-->
<?php
$start=time();
include ("./pkg.dict.php");
?>
<html>
<head>
<title>Simple Form to Query dict.org</title>
</head>
<body>
Search the dict.org server
<p>
<form action="<?php echo $PHP_SELF ?>" method="post">
<input type="text" name="query_term" size="60"
<?php
if ($query_term)
echo "value=\"".$query_term."\"";
?>
><br>
<input type="hidden" name="database" value="*">
<input type="hidden" name="strategy" value="exact">
<input type="submit" name="submit" value=" Search ">
<input type="reset" name="reset" value=" Clear form input ">
<hr>
<?php
// check if element is in the array
function inArray($element, $arr) {
// figure out version
list($major, $minor, $release) = explode(".", phpversion());
if (($major == 3 && $relesase >= 12) || $major == 4) {
return in_array($element, $arr);
} else {
// assumes that we want to compare element value
while (list($key, $val) = each($arr)) {
if ($val == $element)
return true;
}
return false;
}
}
// remove duplicates from array
// and eliminate the patterns in $nolinks
function cleanArray($arr) {
$nolinks = "rfc:";
$out = array();
for ($i=0; $i<count($arr); $i++)
if (!inArray($arr[$i], $out) && !ereg($nolinks, $arr[$i]))
$out[] = $arr[$i];
return $out;
}
//make the links to other words in the description
function mkLinks($str, $db) {
global $PHP_SELF;
// modified the regexes to fix the bug reported by <davor@croart.com>
$patt = "\{+([^{}]+)\}+";
$regex = "<b>\\1</b>";
$out = ereg_replace($patt, $regex, $str);
$patt = "/\{+([^{}]+)\}+/";
preg_match_all($patt, $str, &$reg);
$link = $reg[1];
// clean up array
$link = cleanArray($link);
if (count($link) > 0)
$out .= "<i>See also:</i>\n";
for ($i=0; $i<count($link); $i++) {
// added the line below to fix a second bug reported by <davor@croart.com>
$link[$i] = ereg_replace("[[:space:]]+", " ", $link[$i]);
// observed myself another bug with references to URLs - JMC
// check if it is a HTTP URL or a crossrefence
$protocols = "(http|https|ftp|telnet|gopher)://|(mailto|news):";
if (ereg($protocols, $link[$i])) {
// parse the link and mark it using <>
$prot1 = "^((mailto|news):.+)$";
$prot2 = "(http|https|ftp|telnet|gopher)://";
$prot2 = "^(.*) *\((".$prot2.".+)\)$";
if (ereg($prot1, $link[$i], &$regurl)) {
list ($tmp, $url) = $regurl;
$desc = $url;
} elseif (ereg($prot2, $link[$i], &$regurl)) {
list ($tmp, $desc, $url) = $regurl;
if ($desc == "")
$desc = $url;
}
$out .= "<<a href=\"".chop($url)."\" target=\"_blank\">";
$out .= chop($desc)."</a>> ";
} else {
$out .= "[<a href=\"".$PHP_SELF."?query_term=";
$out .= urlencode($link[$i])."&database=".urlencode($db);
$out .= "&strategy=exact\">".$link[$i]."</a>] ";
if (($i % 5) == 0 && $i > 0)
$out .= "\n";
}
}
$out .= "\n";
return $out;
}
function parr($arr) {
echo "<ul>";
while (list($k,$v) = each($arr)) {
if (gettype($v) == "array") {
echo "<ul>";
echo "* $k , new array*<br>";
parr($v);
echo "</ul>";
} else {
echo "$k = $v<br>";
}
}
echo "</ul>";
}
// perform a query to the server
function doQuery($str, $db, $strategy) {
global $PHP_SELF;
$query = new DictQuery();
$query->define($str, $db);
$n = $query->get("numres");
$res = $query->get("result");
$out = "<b>Found ".count($res);
$out .= (count($res)==1) ? " hit" : " hits";
$out .= "</b> - <i>Term: ".$str.", Database: ".$db.", Strategy: ".$strategy;
$out .= "</i><br>\n<dl>\n";
for ($i=0; $i<count($res); $i++) {
$entry = $res[$i];
$out .= "<dt>[".($i + 1)."] : ".$entry["dbname"]."</dt>\n";
$out .= "<dd><pre>".mkLinks($entry["definition"], $db)."</pre></dd>\n";
}
$out .= "</dl>";
return $out;
}
if ($query_term){
$out = doQuery($query_term, $database, $strategy);
echo $out."\n<hr>\n";
}
?>
Last accessed:
<?php
$end = time();
echo date("Y/m/d H:i:s",time());
echo " [Total processing time: ".($end - $start)." seconds]";
?>
</body>
</html>
::::::::::::::
extendedsearch.php
::::::::::::::
<!--
Extended example that uses pkg.dict.org
(c) 2000, Jesus M. Castagnetto <jmcastagnetto@zkey.com>
License: GPL, see www.gnu.org/copyleft/gpl.txt
Changes:
2000/06/04 - Added the correct link to the GPL license
2000/06/05 - Fixes to bugs reported by Davor Cengija <davor@croart.com>
(1) Links that look like {{UNIX}} were not being stripped
correctly
(2) Crossreference terms sometimes spanned a line break
which looked real ugly/bad
Thanks to Davor for reporting the bugs in this example
2000/06/05 - Found another bug, some crossreferences are to URLs and
not terms in the dictionaries, the makeLink() function has
been fixed to account for that.
2000/06/06 - Check for duplicates when creating the links, and modified
the external URLs regex to recognize more protocols, as well
as eliminate crossrefences to RFC's
-->
<?php
$start=time();
include ("./pkg.dict.php");
?>
<html>
<head>
<title>Extended autogenerated form to query dict.org</title>
</head>
<body>
Search the dict.org server
<p>
<form action="<?php echo $PHP_SELF ?>" method="post">
<input type="text" name="query_term" size="60"
<?php
if ($query_term)
echo "value=\"".$query_term."\"";
?>
><BR>
<?php
/*
* I will autogenerate the form in the code below
* You might want to make a static form to avoid
* the overhead of the on-the-fly HTML code generation
* and the query to the DICT server
*/
// functions to make the form
function mkSelect($name, $nopt, $options, $default) {
$out = "<select name=\"".$name."\">\n";
list($defkey,$defval) = each($default);
$out .= "<option value=\"".$defkey."\" selected>".$defval."</option>\n";
while (list($key,$val) = each($options)) {
if ($key != $defkey)
$out .= "<option value=\"".$key."\">".$val."</option>\n";
}
$out .= "</select>\n";
return $out;
}
function printForm($s) {
$ndbs = $s->get_info("num_dbs");
$dbs = $s->get_info("databases");
$nstrats = $s->get_info("num_strats");
$strategies = $s->get_info("strategies");
$out = "<BR>Use database:<BR>\n";
$out .= mkSelect("database", $ndbs, $dbs, array("*"=>"Any"));
$out .= "<BR>Type of Search:<BR>\n";
$out .= mkSelect("strategy", $ndbs, $strategies, array("exact"=>"Exact Search"));
echo $out;
}
// get non-extended info from the server
$server = new DictServerInfo();
// print the form
printForm($server);
?>
<br>
<input type="submit" name="submit" value=" Search ">
<input type="reset" name="reset" value=" Clear form input ">
<hr>
<?php
/*
* If there was a query, this part will show the result
*/
// check if element is in the array
function inArray($element, $arr) {
// figure out version
list($major, $minor, $release) = explode(".", phpversion());
if (($major == 3 && $relesase >= 12) || $major == 4) {
return in_array($element, $arr);
} else {
// assumes that we want to compare element value
while (list($key, $val) = each($arr)) {
if ($val == $element)
return true;
}
return false;
}
}
// remove duplicates from array
// and eliminate the patterns in $nolinks
function cleanArray($arr) {
$nolinks = "rfc:";
$out = array();
for ($i=0; $i<count($arr); $i++)
if (!inArray($arr[$i], $out) && !ereg($nolinks, $arr[$i]))
$out[] = $arr[$i];
return $out;
}
//make the links to other words in the description
function mkLinks($str, $db) {
global $PHP_SELF;
// modified the regexes to fix the bug reported by <davor@croart.com>
$patt = "\{+([^{}]+)\}+";
$regex = "<b>\\1</b>";
$out = ereg_replace($patt, $regex, $str);
$patt = "/\{+([^{}]+)\}+/";
preg_match_all($patt, $str, &$reg);
$link = $reg[1];
// clean up array
$link = cleanArray($link);
if (count($link) > 0)
$out .= "<i>See also:</i>\n";
for ($i=0; $i<count($link); $i++) {
// added the line below to fix a second bug reported by <davor@croart.com>
$link[$i] = ereg_replace("[[:space:]]+", " ", $link[$i]);
// observed myself another bug with references to URLs - JMC
// check if it is a HTTP URL or a crossrefence
$protocols = "(http|https|ftp|telnet|gopher)://|(mailto|news):";
if (ereg($protocols, $link[$i])) {
// parse the link and mark it using <>
$prot1 = "^((mailto|news):.+)$";
$prot2 = "(http|https|ftp|telnet|gopher)://";
$prot2 = "^(.*) *\((".$prot2.".+)\)$";
if (ereg($prot1, $link[$i], &$regurl)) {
list ($tmp, $url) = $regurl;
$desc = $url;
} elseif (ereg($prot2, $link[$i], &$regurl)) {
list ($tmp, $desc, $url) = $regurl;
if ($desc == "")
$desc = $url;
}
$out .= "<<a href=\"".chop($url)."\" target=\"_blank\">";
$out .= chop($desc)."</a>> ";
} else {
$out .= "[<a href=\"".$PHP_SELF."?query_term=";
$out .= urlencode($link[$i])."&database=".urlencode($db);
$out .= "&strategy=exact\">".$link[$i]."</a>] ";
if (($i % 5) == 0 && $i > 0)
$out .= "\n";
}
}
$out .= "\n";
return $out;
}
// Perform a query to the server
function doQuery($str, $db, $strategy) {
global $PHP_SELF;
$query = new DictQuery();
if ($strategy == "exact") {
$query->define($str, $db);
} else {
$query->match($str, $strategy, $db);
}
$n = $query->get("numres");
$res = $query->get("result");
$out = "<b>Found ".count($res);
$out .= (count($res)==1) ? " hit" : " hits";
$out .= "</b> - <i>Term: ".$str.", Database: ".$db.", Strategy: ".$strategy;
$out .= "</i><br>\n<dl>\n";
for ($i=0; $i<count($res); $i++) {
$entry = $res[$i];
if ($strategy == "exact") {
$out .= "<dt>[".($i + 1)."] : ".$entry["dbname"]."</dt>\n";
$out .= "<dd><pre>".mkLinks($entry["definition"], $db)."</pre></dd>\n";
} else {
$match = explode(" ",chop($entry));
$match_term = str_replace("\"", "", $match[1]);
$out .= "<dt>[". ($i + 1 ) . "] : ";
$out .= "<A HREF=\"".$PHP_SELF."?query_term=".urlencode($match_term);
$out .= "&database=".urlencode($db);
$out .= "&strategy=exact\">";
$out .= $match_term."</a></dt>\n";
$out .= "<dd> Database: ".$match[0]."</dd>";
}
}
$out .= "</dl>";
return $out;
}
// if there was a query ...
if ($query_term){
$out = doQuery($query_term, $database, $strategy);
echo $out."\n<hr>\n";
}
?>
Last accessed:
<?php
$end = time();
echo date("Y/m/d H:i:s",time());
echo " [Total processing time: ".($end - $start)." seconds]";
?>
</body>
</html>
|
|
| phpYellow Pages Standard Categories : PHP, Complete Programs, Databases, Directories, Search | | | simple shopping cart for php3 Categories : PHP, PHP Classes, Complete Programs, Ecommerce | | | DBE - Database Expander: Edit PostgreSQL individual database tables online via your Web browser! Categories : PostgreSQL, Complete Programs, Databases, PHP Classes, PHP | | | Create and restore backup of MySQL databases Categories : MySQL, Databases, PHP, PHP Classes, Complete Programs | | | free, search engine, indexing, system, information, web,
ftp, http, free, software, cgi, php, MySQL, database, php3,
FreeBSD, Linux, Unix, UdmSearch Categories : MySQL, Complete Programs, PHP, Databases, Search | | | Expose - PHP template engine, supports server and client-sided caching,a plugin system, multiple languages, template script language is based on PHP itself. Categories : PHP, PHP Classes, Templates, Complete Programs | | | Functions to access a NNTP/NNRP newsserver. Complete set with examples is at ftp://ftp.nederland.net/pub/nnrplib Categories : Search, PHP, Complete Programs | | | whois domain name lookup dns url Categories : PHP, Search, Network | | | ClassFuncDoc - This script is a classes and functions documentation tool. Categories : PHP, Classes and Objects, Documentation, PHP Classes, Complete Programs | | | An email validation script that actually checks against the recipient's mail server. Categories : Email, Complete Programs, PHP, Network, Debugging | | | Searches through a local INN server's discussions Categories : Search, Complete Programs, PHP | | | Cool guestbook Categories : PHP, Complete Programs, PHP Classes | | | Search and Replace Text : Searches Files for Specified Text and Replaces It by a Given Text Categories : PHP, PHP Classes, Search, Filesystem | | | Class that allows the PHP developer to establish connections with a POP3 mail server amd be able to list, retrieve and delete mail messages from a given mail box.
Categories : Network, Email, PHP, PHP Classes | | | base class to query the whois database Categories : Network, PHP, PHP Classes | |
| | | | chatdev dotcom wrote :1101
Excellent program, I am very surprised not to see a flood of comments on this program, it should be noticed.
Thank you for the source. It works perfectly. =)
-Rick
| |
|
|