<?php
if (@$argv[1]==='test' && !@$_SERVER['REQUEST_URI'] && !defined('WS_WEB')) {
define('WS_CONSOLE',1);
define('WS_TEST',1);
require_once('WSInit.php');
}
if (!defined('WS_WEB')) die('bad entry point!');
require_once("includes/LoadBalancer.php");
define('SPACE_CHARS','( | | |\pZ)');
function wsfLoadClass( $class ) {
if ( class_exists( $class ) ) return $class;
@include_once( "$class.php" );
if ( class_exists( $class ) ) return $class;
return NULL;
}
function wsfGetExpertClass( $base, $dbname, $domain, $family, $lang, $is_multilang ) {
$class= NULL;
if (!$class) $class = wsfLoadClass( "{$base}_".str_replace('.','_',$domain) );
if (!$class) $class = wsfLoadClass( "{$base}_{$dbname}" );
if (!$class && !$is_multilang) $class = wsfLoadClass( "{$base}_{$lang}_{$family}" );
if (!$class && !$is_multilang) $class = wsfLoadClass( "{$base}_{$lang}" );
if (!$class) $class = wsfLoadClass( "{$base}_{$family}" );
if (!$class && $is_multilang) $class = wsfLoadClass( "{$base}_{$lang}" );
if (!$class) $class= $base;
return $class;
}
function wsfLoadExpertConfig( $base, $var, $dbname, $domain, $family, $lang, $is_multilang ) {
$$var= array();
#TODO: cache values, use include_once!
wsfLog("loading expert config for {$base} - {$lang} - {$family} - {$dbname} - {$domain}",LL_DEBUG);
@include( $base.'.php' );
if ($is_multilang) @include( "{$base}_{$lang}.php" );
@include( "{$base}_{$family}.php" );
if (!$is_multilang) @include( "{$base}_{$lang}.php" );
if (!$is_multilang) @include( "{$base}_{$lang}_{$family}.php" );
@include( "{$base}_{$dbname}.php" );
@include( "{$base}_".str_replace('.','_',$domain).'.php' );
return $$var;
}
function wsfConfigureObject( &$obj, $conf, $all=false ) {
if (!$conf) return;
$vars= NULL;
if (!$all) $vars= array_keys(get_object_vars($obj));
wsfLog("configuring ".get_class($obj)." object with ".sizeof($conf)." settings",LL_DEBUG);
foreach ($conf as $k => $v) {
if ($all || in_array($k,$vars)) {
$obj->$k= $v;
#print "\n<br/>CONFIGURING: ".get_class($obj)."::$k => $v <br/>\n";
}
#else print "\n<br/>SKIPPING: ".get_class($obj)."::$k <br/>\n";
}
}
function dbFailFunction( &$db, $error ) {
print "<p class='error'><b>Database Error: ".htmlspecialchars($error)."</b></p>";
}
function & openConnection( $uri ) {
if ( is_string($uri) && preg_match( '!^%(.*)$!', $uri, $matches ) ) {
$u= $GLOBALS['wsgDatabases'][$matches[1]];
if (!$u) {
trigger_error('unknown database ID: '.$matches[1], E_USER_WARNING);
return false;
}
$uri= $u;
}
if ( is_array($uri) ) {
extract($uri);
}
else {
//pseudo-url, jdbc-style: driver://[user[:password]@]host/database
if ( !preg_match( '!^([\w\d]+):(//(([^/@:]+)(:([^/@:]+))?@)?([\w\d-.]+)/)?([^;&\?]+)$!', $uri, $matches ) ) {
$dummy=false;
return $dummy;
}
$type= $matches[1];
$user= $matches[4];
$password= $matches[6];
$host= $matches[7];
$dbname= $matches[8];
}
# Get class for this database type
$class = 'Database' . ucfirst( $type );
if ( !class_exists( $class ) ) {
require_once( "includes/$class.php" );
}
#print "==> connecting to $dbname on $host using $class<br/>\n";
# Create object
$db= new $class( $host, $user, $password, $dbname, 'dbFailFunction', 0 );
if ( !$db->mConn ) {
$dummy= false;
return $dummy;
}
$db->mOut= NULL;
$db->ping();
return $db;
}
function & getWikiListDB() {
global $wsgWikiListDB, $wsgWikiListTable;
global $wsgWikiDB;
global $wsgWikiListDBConnection;
if (!$wsgWikiListDB && !$wsgWikiListDBConnection) {
wsfLog('no WikiList database defined!',LL_ERROR);
wfDebugDieBacktrace('no WikiList database defined!');
}
if ( !$wsgWikiListDBConnection ) {
$u= $wsgWikiListDB;
if (strpos($u,':')===false) $u= "$wsgWikiDB/$wsgWikiListDB";
$wsgWikiListDBConnection=& openConnection($u);
if (!$wsgWikiListDBConnection) {
wsfLog('failed to connect to WikiList database ',LL_ERROR);
wfDebugDieBacktrace('failed to connect to WikiList database ');
}
}
return $wsgWikiListDBConnection;
}
function getWikiInfo( $where, $limit= NULL, $usable = true ) {
global $wsgWikiListTable, $wsgWikiDB;
$db=& getWikiListDB();
$w= '';
$w.= "WHERE ";
if ($where) {
$i= 0;
foreach ($where as $c => $v) {
$w.= " $c = ".$db->addQuotes($v)." AND ";
$i+= 1;
}
}
if ($usable) $w.= " is_closed = 0 AND domain is not NULL ";
$sql= 'SELECT * FROM '.$wsgWikiListTable.'
'.$w;
if ($limit) $w.= " LIMIT $limit";
$res= $db->query($sql, 'getWikiInfo');
$wikis= array();
while ($w= $db->fetchObject($res)) {
@$w->baseURL= "http://{$w->domain}/w/index.php";
@$w->dbURL= $wsgWikiDB ? "$wsgWikiDB/{$w->dbname}" : NULL;
$wikis[]= $w;
}
$db->freeResult($res);
return $wikis;
}
function getWikiInfoFromLang( $lang, $family = NULL ) {
global $wsgWikiListDB, $wsgWikiDB;
if ($lang=='simple') $lang= 'en-simple';
if ($lang=='commons' && (!$family || $family=='wikimedia')) {
$lang= 'en';
$family= 'commons';
}
if (!$family) $family= 'wikipedia';
if (!$wsgWikiListDB) {
$w= new stdClass();
@$w->lang= $lang;
@$w->family= $family;
#print "FAMILY: $family; LANG: $lang\n";
if ( $family=='commons' ) @$w->domain= "commons.wikimedia.org";
else @$w->domain= "$lang.$family.org";
if ( $family=='commons' ) @$w->is_multilang= true;
else @$w->is_multilang= false;
if ( $family=='wikipedia' ) @$w->dbname= "{$lang}wiki";
else if ( $family=='commons' ) @$w->dbname= "{$family}wiki";
else @$w->dbname= "$lang$family";
@$w->baseURL= "http://{$w->domain}/w/index.php";
@$w->dbURL= $wsgWikiDB ? "$wsgWikiDB/{$w->dbname}" : NULL;
return $w;
}
else {
$info= getWikiInfo( array( 'lang' => $lang, 'family' => $family ), 1 );
if (!$info) return false;
else return $info[0];
}
}
function getWikiInfoFromDomain( $domain ) {
global $wsgWikiListDB;
#compatibility hack
if (strpos($domain,'.')===false) {
return getWikiInfoFromLang($domain);
}
if (!$wsgWikiListDB) {
$match= array();
if (!preg_match('/^(\w+)\.(\w+)(\.\w+)?$/',$domain,$match)) {
return false;
}
$w= getWikiInfoFromLang($match[1], $match[2]);
@$w->domain= $domain;
return $w;
}
else {
if (!preg_match('/.*\.org$/',$domain)) $domain.= '.org';
$info= getWikiInfo( array( 'domain' => $domain ), 1 );
if (!$info) return false;
else return $info[0];
}
}
function getLargestWikis($n, $family = NULL) {
global $wsgWikiListDB, $wsgWikiDB, $wsgWikiBlacklist;
if (!$wsgWikiListDB) {
global $wsgLanguages;
if (!$n) $l= $wsgLanguages;
else $l= array_slice($wsgLanguages,0,$n);
$wikis= array();
foreach ($l as $lang) {
$info= getWikiInfoFromLang($l);
$wikis[$info['domain']]= $info;
}
return $wikis;
}
else {
global $wsgWikiListTable;
$db=& getWikiListDB();
$sql= "select * from $wsgWikiListTable";
$sql.= " where domain is not null";
$sql.= " and is_closed = 0";
if ($family) $sql.= " and family = ".$db->addQuotes($family);
$sql.= " order by size desc limit $n;";
$wikis= array();
$res= $db->query($sql,'getLargestWikis');
while ( $w= $db->fetchObject($res) ) {
if (!$w->domain) continue;
if ($wsgWikiBlacklist) {
if (in_array($w->domain,$wsgWikiBlacklist)) continue;
if (in_array($w->dbname,$wsgWikiBlacklist)) continue;
}
@$w->baseURL= "http://{$w->domain}/w/index.php";
@$w->dbURL= $wsgWikiDB ? "$wsgWikiDB/{$w->dbname}" : NULL;
$wikis[$w->domain]= $w;
}
$db->freeResult($res);
return $wikis;
}
}
$wsgNamespaceCache= NULL;
$wsgNamespaceCacheReverse= NULL;
$wsgNamespaceCacheComplete= false;
function getCustomNsIndex( $wiki, $ns, $slurp = false ) {
global $wsgNamespaceCache, $wsgNamespaceCacheReverse;
if (!$ns || !$wiki) $k= NULL; //slurp only
else $k= "$wiki#$ns";
if ($wsgNamespaceCacheReverse==NULL) $wsgNamespaceCacheReverse= array();
if ($wsgNamespaceCache==NULL) $wsgNamespaceCache= array();
if ($k && isset($wsgNamespaceCacheReverse[$k]) && (!$slurp || $wsgNamespaceCacheComplete)) return $wsgNamespaceCacheReverse[$k];
getCustomNsText($wiki,0,$slurp); //load
if (!$k) return NULL; //slurp only
if (!isset($wsgNamespaceCacheReverse[$k])) $wsgNamespaceCacheReverse[$k]= NULL;
return $wsgNamespaceCacheReverse[$k];
}
function getCustomNsText( $wiki, $ns, $slurp = false ) {
global $wsgWikiListDB;
global $wsgNamespaceCache, $wsgNamespaceCacheReverse;
global $wsgNamespaceCacheComplete, $wsgCustomNamespaceTable;
if (!$ns || !$wiki) $k= NULL; //slurp only
else $k= "$wiki#$ns";
if ($wsgNamespaceCacheReverse==NULL) $wsgNamespaceCacheReverse= array();
if ($wsgNamespaceCache==NULL) $wsgNamespaceCache= array();
if ($k && isset($wsgNamespaceCache[$k]) && (!$slurp || $wsgNamespaceCacheComplete)) return $wsgNamespaceCache[$k];
if ($wsgWikiListDB && !$wsgNamespaceCacheComplete && $wsgCustomNamespaceTable) {
$db=& getWikiListDB();
$sql= "SELECT * from $wsgCustomNamespaceTable";
if (!$slurp) $sql.= " WHERE domain = ".$db->addQuotes($wiki);
#print "LOADING NS FOR $wiki: $sql<br>";
$res= $db->query($sql,'getCustomNamespaceName');
while ( $w= $db->fetchObject($res) ) {
if (!$w->domain) continue;
$wsgNamespaceCache[$w->domain.'#'.$w->ns_id]= $w->ns_name;
$wsgNamespaceCacheReverse[$w->domain.'#'.$w->ns_name]= $w->ns_name;
}
if ($slurp) $wsgNamespaceCacheComplete= true;
}
if (!$k) return NULL; //slurp only
if (!isset($wsgNamespaceCache[$k])) $wsgNamespaceCache[$k]= $ns;
return $wsgNamespaceCache[$k];
}
define('LL_MUTE', -100);
define('LL_SILENT', -4);
define('LL_QUIET', -2);
define('LL_NORMAL', 0);
define('LL_VERBOSE', 10);
define('LL_NOISY', 100);
define('LL_TRACE', LL_VERBOSE);
define('LL_DEBUG', LL_VERBOSE);
define('LL_INFO', LL_NORMAL);
define('LL_WARN', LL_QUIET);
define('LL_ERROR', LL_SILENT);
function wsfToString($data) {
if ($data === NULL) $data= "<null>";
else if ($data===false) $data= "<false>";
else if ($data===true) $data= "<true>";
else if (is_object($data)) $data= get_object_vars($data);
if (is_array($data)) {
$s= "{";
foreach ( $data as $k => $v ) {
$s.= "$k => ".wsfToString($v).", ";
}
$s.= "}";
$data= $s;
}
return $data;
}
function wsfLog( $msg, $level = LL_NORMAL, $data='@dummy@' ) {
global $wsgLogLevel, $wsgLogHashCounter, $wsgLogSuffix, $wsgLogTag;
if ($level>$wsgLogLevel) {
if ($level>$wsgLogLevel+2) {
return;
}
else {
if ( $wsgLogHashCounter == 0 ) {
print " ";
}
if ($level<LL_NORMAL) print "!";
else print ".";
$wsgLogHashCounter+= 1;
if ( $wsgLogHashCounter > 50 ) {
print $wsgLogSuffix;
$wsgLogHashCounter = 0;
}
}
}
else {
if ( $wsgLogHashCounter > 0 ) {
print $wsgLogSuffix;
$wsgLogHashCounter = 0;
}
if ($data==='@dummy@') $data= '';
else $msg.= " (".wsfToString($data).")";
if ($wsgLogTag) print "<$wsgLogTag>";
print " - $msg";
if ($wsgLogTag) print "</$wsgLogTag>";
print "\n";
}
flush();
}
function wsfDBTitle( $title ) {
$title= urldecode( $title ); #HACKish
$title= Sanitizer::decodeCharReferences( $title );
$title= str_replace(' ','_',$title);
$title= ucfirst($title); //FIXME: unicode! //FIXME: optional!
return $title;
}
function & wsfStripIntKeys( &$array ) {
if ( $array === NULL || $array===false ) return $array;
foreach ( $array as $k => $v ) {
if (is_int($k)) unset($array[$k]);
}
return $array;
}
function stripMarkup( $text ) {
#print "\n---> $text\n";
$text= preg_replace("!\"|'''?|<[\\w\\d]+.*?/?>|</[\\w\\d]+>!",'',$text);
$text= preg_replace('!^[\s]+|[\s]+$!','',$text); #FIXME: unicode whitespace
if (strlen($text>2)) $text= preg_replace('!^[\s"\'\]\[<>,;.:?\{\}]+|[\s"\'\]\[<>,,;.:?\{\}]+$!','',$text); #FIXME: unicode punctuation
$text= Sanitizer::decodeCharReferences( $text );
#print "===> $text\n";
#FIXME: strip punctuation
return $text;
}
function stripHTML( $text ) {
$text= preg_replace("!<[\\w\\d]+.*?/?>|</[\\w\\d]+>!",'',$text);
$text= preg_replace("/<!--.*?-->/",'',$text);
return $text;
}
function endsWith( $haystack, $needle ) {
if (strlen($haystack)<strlen($needle)) return false;
else {
$x= substr($haystack, strlen($haystack) - strlen($needle));
if ($x === $needle) return true;
else return false;
}
}
function escapeChunkCallback( $value, $prefix, &$store ) {
static $i;
if (!isset($i)) $i= 0;
$i+= 1;
$k= "@@$prefix:$i:".rand(1,1000)."@@";
$store[$k]= $value;
return $k;
}
function escapeChunks( $prefix, $preg, &$text, &$store ) {
$code= 'escapeChunkCallback(\'\0\',$prefix,$store)';
$text= preg_replace($preg.'e',$code,$text);
return $text;
}
function unescapeChunks( &$text, &$store ) {
$text= str_replace(array_keys($store),array_values($store),$text);
return $text;
}
class PseudoLoadBalancer {
var $db;
function PseudoLoadBalancer( &$db ) {
$this->db=& $db;
}
function & getConnection( $dummy1, $dummy2, $dummy3 ) {
return $this->db;
}
}
class PseudoOut {
function disable() {}
function sendCacheControl() {}
function debug() {}
}
#global $wgOut;
if (!isset($wgOut) || !$wgOut) {
$wgOut= new PseudoOut();
}
function printRadioButton($name, $value, $current= NULL, $a= '') {
$s= $value!=$current ? '' : " checked='checked' ";
print "<input type='radio' name='$name' value='$value'$s$a/>";
}
function printCheckbox($name, $value, $a= '') {
$s= $value ? " checked='checked' " : '';
print "<input type='checkbox' name='$name' $s$a/>";
}
function printOption($label, $value, $current= NULL, $a= '') {
$s= $value!=$current ? '' : " selected='selected' ";
print "<option value='$value'$s$a>$label</option>";
}
function printSelector($name, $options, $current= NULL) {
print "\n<select name='$name'>";
foreach ($options as $v => $label) {
printOption($label, $v, $current);
}
print "\n</select>\n";
}
function addURLParam(&$url, $key, $value, $html=true) {
if (isset($value) && $value !== NULL && $value!==false && $value!=='') {
$value= urlencode($value);
if ($html) $url.= '&';
else $url.= '&';
$url.= $key;
$url.= '=';
$url.= $value;
}
return $url;
}
function wsfHackingInProgress() {
?>
<p style="border:1px solid black; background-color:yellow; margin:1ex; padding: 1ex;">
<b>WARNING: <i>Hacking in Progress!</i></b><br/>
This tool is currently being modified and debugged. You can try to use it, but you may
get unexpected or wrong results. Or it may simply be broken for a while. Please try again
later if you need to use it for anything serious.
</p>
<?
}
function wsfSubtitle( $name ) {
$help= 'http://meta.wikimedia.org/wiki/User:Duesentrieb/'.urlencode($name);
$talk= 'http://meta.wikimedia.org/wiki/User_talk:Duesentrieb/'.urlencode($name);
?>
<p style='font-size:70%;'>
<a href='<?=$help?>'><?= wsfWikiSenseMessage('help_page_label') ?></a>
|
<a href='<?=$talk?>'><?= wsfWikiSenseMessage('talk_page_label') ?></a>
</p>
<?
}
function wsfFooter( $done = true, $bundle = NULL ) {
global $wsgFooter;
if ($wsgFooter) include($wsgFooter);
}
function wsfHeader( $done = true, $bundle = NULL ) {
global $wsgHeader;
if ($wsgHeader) include($wsgHeader);
}
function wsfCachePut($uri, $data) {
global $wsgCacheDir;
if (!$wsgCacheDir) return false;
if (!file_exists($wsgCacheDir)) return false;
if (!is_dir($wsgCacheDir)) return false;
if (!is_writable($wsgCacheDir) || !is_readable($wsgCacheDir)) return false;
$f= $wsgCacheDir.'/'.str_replace(array('/','&','+','*','?',';',':',' '),'_',$uri).'.cache';
$ok= file_put_contents($f,$data);
return $ok;
}
function wsfCacheGet($uri, $duration, $sendLastModified=false) {
global $wsgCacheDir;
if (!$wsgCacheDir) return false;
if (!file_exists($wsgCacheDir)) return false;
if (!is_dir($wsgCacheDir)) return false;
if (!is_writable($wsgCacheDir) || !is_readable($wsgCacheDir)) return false;
$f= $wsgCacheDir.'/'.str_replace(array('/','&','+','*','?',';',':',' '),'_',$uri).'.cache';
if (!file_exists($f)) return NULL;
if (!is_file($f)) return NULL;
if (!is_readable($f)) return NULL;
$time= filemtime($f);
if (!$duration || ((time() - $time) > $duration) ) { //cache is stale
unlink($f);
return NULL;
}
$data= file_get_contents($f);
if ($data !== NULL && $data!==false && $sendLastModified && !headers_sent()) {
header('Last-Modified: '.wfTimestamp(TS_RFC2822,$time));
}
return $data;
}
function wsfCacheStart($uri, $duration) {
if ($duration===false) return false;
$data= wsfCacheGet($uri, $duration, true);
if ($data===false) return false;
if ($data !== NULL) {
if (!headers_sent()) header('X-WS-Cached: yes');
print $data;
return true;
}
ob_start();
return NULL;
}
function wsfCacheEnd($uri) {
if (!ob_get_level()) return false;
$data= ob_get_contents();
ob_end_flush();
wsfCachePut($uri, $data);
}
if (!function_exists('file_put_contents')) {
function file_put_contents($f, $data, $append = false) {
$fh= fopen($f,$append?'a':'w');
if (!$fh) return false;
$ok= fwrite($fh,$data);
fclose($fh);
return $ok;
}
}
global $wsgWikiSenseMessages;
$wsgWikiSenseMessages= NULL;
function wsfWikiSenseMessage($key) {
global $wsgWikiSenseMessages, $wsgUserLang;
if ($wsgUserLang && $wsgWikiSenseMessages && $wsgWikiSenseMessages->language != $wsgUserLang) {
$wsgWikiSenseMessages= NULL;
}
if (!$wsgWikiSenseMessages) {
if (!class_exists('WikiSenseLocalizer')) {
require_once('WikiSenseLocalizer.php');
}
$wsgWikiSenseMessages= WikiSenseLocalizer::load( 'WikiSense', $wsgUserLang ? $wsgUserLang : 'en' );
}
$args= func_get_args();
return call_user_func_array ( array(&$wsgWikiSenseMessages, 'msg'), $args );
}
function wsfGetReplag() {
global $wsgReplagFile, $wsgReplagPattern;
if (!$wsgReplagFile) return NULL;
$t= file_get_contents($wsgReplagFile);
if ($t === NULL || $t===false) return false;
$t= trim($t);
if ($wsgReplagPattern) $t= eval($wsgReplagPattern);
return $t;
}
function wsfGetReplagHTML() {
$lag= wsfGetReplag();
if ($lag === NULL) return '';
if ($lag===false) return '<span class="error">failed to get replication lag!</span>';
if ($lag==='0' || $lag===0 || $lag < 8) return '<span style="color:green;">database is up to date.</span>';
$html= '';
$s= $lag;
$d= floor($s / (60*60*24));
if ($d) {
$s-= $d * 60*60*24;
if ($html) $html.= ', ';
$html.= "$d days";
}
$h= floor($s / (60*60));
if ($h) {
$s-= $h * 60*60;
if ($html) $html.= ', ';
$html.= "$h hours";
}
$m= floor($s / (60));
if ($m) {
$s-= $m * 60;
if ($html) $html.= ', ';
$html.= "$m minutes";
}
if ($s) {
if ($html) $html.= ', ';
$html.= "$s seconds";
}
if ($lag > 60 * 60 * 12) $style= 'font-weight:bold; color:yellow; background-color:red;';
else if ($lag > 60 * 60) $style= 'color:black; background-color:red;';
else if ($lag > 60 * 5) $style= 'color:black; background-color:orange;';
else if ($lag > 60 * 1) $style= 'color:black; background-color:yellow;';
else $style= 'color:green;';
$html= "<span style='$style'>database lag: $html</span>";
return $html;
}
/*
function preg_replace_recursive($begin, $end, $sep, $mod, $replace, $s) {
$s= preg_replace("$sep$begin((?>.*?)(?R))*.*?$end$sep$mod",'',$s);
return $s;
}
*/
function preg_strip($exp, $s) {
while (true) {
$l= strlen($s);
#print "--> $s \n";
$s= preg_replace($exp,'',$s);
if ($l==strlen($s)) break;
}
return $s;
}
function wsfMicroTime()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
function levensteinDistance($a, $b, $normalize=false, $limit=0) {
$d= array();
$ca= is_array($a) ? sizeof($a) : mb_strlen($a);
$cb= is_array($b) ? sizeof($b) : mb_strlen($b);
if ($a === $b) return 0;
if ($a==='' || $a===NULL || (is_array($a) && sizeof($a)===0)) return $cb;
if ($b==='' || $b===NULL || (is_array($b) && sizeof($b)===0)) return $ca;
$v= abs($ca-$cb);
if ($normalize) $v= $v / (float)max($ca,$cb);
if ($limit && $v > $limit) return $v;
for ($i= 0; $i<=$ca; $i+= 1) $d[$i]= array( 0 => $i );
for ($j= 0; $j<=$cb; $j+= 1) $d[0][$j]= $j;
for ($i= 1; $i<=$ca; $i+= 1) {
for ($j= 1; $j<=$cb; $j+= 1) {
$ach= is_array($a) ? $a[$i-1] : mb_substr($a,$i-1,1);
$bch= is_array($a) ? $a[$i-1] : mb_substr($b,$j-1,1);
$cost= $ach == $bch ? 0 : 1;
$d[$i][$j]= min(
$d[$i-1][$j ] + 1, //deletion
$d[$i ][$j-1] + 1, //insertion
$d[$i-1][$j-1] + $cost //substitution
);
/*
$v= $d[$i][$cb];
if ($normalize) $v= $v / (float)max($ca,$cb);
if ($limit && $v > $limit) return $v;
*/
#FIXME: abort if hopeles... how?!
}
}
if ($normalize) {
$f= (float)$d[$ca][$cb] / (float)max($ca,$cb);
return $f;
}
else return $d[$ca][$cb];
}
if (defined('WS_TEST')) {
$d= levensteinDistance($args[1], $args[2], true, 0.2);
print "DISTANCE: $d\n";
}
?>
WikiSense.php.orig
text/x-php, 23302 bytes (load raw)

