Difference between revisions of "SpamFerret/Special"

from HTYP, the free directory anyone can edit if they can prove to me that they're not a spambot
Jump to: navigation, search
(10/6 minor improvements)
(v0.31)
 
Line 10: Line 10:
 
2009-10-01 0.1 (Wzl) incremental improvements; clsMenu now a separate file
 
2009-10-01 0.1 (Wzl) incremental improvements; clsMenu now a separate file
 
2009-10-06 0.2 (Wzl) text-check now shows if matching filters are deactivated
 
2009-10-06 0.2 (Wzl) text-check now shows if matching filters are deactivated
 +
2010-02-23 0.3 (Wzl) finally gave regular users some brief summary text to look at
 +
2010-08-17 0.31 (Wzl) a bit of debugging display in the regex checker
 
*/
 
*/
 
$wgSpecialPages['SpamFerret'] = 'SpecialSpamFerret'; # Let MediaWiki know about your new special page.
 
$wgSpecialPages['SpamFerret'] = 'SpecialSpamFerret'; # Let MediaWiki know about your new special page.
Line 17: Line 19:
 
         'description' => 'special page for SpamFerret administration',
 
         'description' => 'special page for SpamFerret administration',
 
         'author' => 'Woozle (Nick) Staddon',
 
         'author' => 'Woozle (Nick) Staddon',
'version' => '0.2 2009-10-06 alpha'
+
'version' => '0.31 2010-08-17 alpha'
 
);
 
);
 
define('KS_CHAR_URL_ASSIGN',':'); // character used for encoding values in wiki-internal URLs
 
define('KS_CHAR_URL_ASSIGN',':'); // character used for encoding values in wiki-internal URLs
Line 29: Line 31:
  
 
require_once( $wgScriptPath.'includes/SpecialPage.php' );
 
require_once( $wgScriptPath.'includes/SpecialPage.php' );
/*
+
if (!defined('LIBMGR')) {
class clsMenu {
+
     require('libmgr.php');
    public $Page;
 
    private $SubNodes;
 
    private $AllNodes;
 
    protected $Action;
 
    protected $Selected;
 
 
 
    public function __construct($iWikiPage) {
 
$this->Page = $iWikiPage;
 
    }
 
    public function WikiText($iAction) {
 
$this->Action = $iAction;
 
if (isset($this->AllNodes[$iAction])) {
 
    $this->AllNodes[$iAction]->Activate();
 
}
 
$out = $this->WikiText_SubMenu($iAction);
 
return $out;
 
    }
 
    public function WikiText_SubMenu($iAction) {
 
$out = NULL;
 
foreach ($this->SubNodes as $objNode) {
 
    if (!is_null($out)) {
 
$out .= ' | ';
 
    }
 
    $out .= $objNode->WikiText($iAction);
 
}
 
return $out;
 
    }
 
    public function Add(clsMenuNode $iNode) {
 
$this->SubNodes[$iNode->Name] = $iNode;
 
$this->Root()->AllNodes[$iNode->Name] = $iNode;
 
$iNode->Parent = $this;
 
    }
 
     protected function Root() {
 
return $this;
 
    }
 
    protected function Activate() {    } // do nothing
 
    public function Execute() {
 
if (isset($this->Selected)) {
 
    $out = $this->Selected->DoAction();
 
} else {
 
    $out = NULL;
 
}
 
return $out;
 
    }
 
 
}
 
}
 +
clsLibMgr::Add('menus', KFP_MW_PLUGINS.'/menu.php',__FILE__,__LINE__);
 +
clsLibMgr::Load('menus' ,__FILE__,__LINE__);
  
abstract class clsMenuNode extends clsMenu {
 
    public $Name;
 
    protected $Text;
 
    protected $DoSpec;
 
    public $Parent;
 
    protected $IsActive;
 
 
    public function __construct($iText, $iDo) {
 
$this->Name = $iDo;
 
$this->Text = $iText;
 
$this->DoSpec = $iDo;
 
    }
 
    public function Root() {
 
return $this->Parent->Root();
 
    }
 
    abstract public function DoAction();
 
    protected function Activate() {
 
$this->IsActive = TRUE;
 
$this->Parent->Activate();
 
    }
 
    public function WikiText($iAction) {
 
$wtSelf = $this->Root()->Page;
 
$wtItem = "[[$wtSelf/page".KS_CHAR_URL_ASSIGN."{$this->DoSpec}/|{$this->Text}]]";
 
// if ($iAction == $this->DoSpec) {
 
if ($this->IsActive) {
 
    $out = "'''$wtItem'''";
 
    $this->Root()->Selected = $this;
 
} else {
 
    $out = $wtItem;
 
}
 
return $out;
 
    }
 
}
 
 
class clsMenuRow extends clsMenuNode {
 
    public function DoAction() {
 
$out = "<br>'''{$this->Text}''': ";
 
$out .= $this->WikiText_SubMenu($this->Root()->Action);
 
return $out;
 
    }
 
}
 
 
class clsMenuItem extends clsMenuNode {
 
    public function DoAction() {
 
// later: actually implement menu item action
 
    }
 
}
 
*/
 
 
class SpecialSpamFerret extends SpecialPage {
 
class SpecialSpamFerret extends SpecialPage {
 
//=======
 
//=======
Line 235: Line 147:
 
PURPOSE: do only stuff that regular users are allowed to do
 
PURPOSE: do only stuff that regular users are allowed to do
 
*/
 
*/
$wgOut->AddWikiText('Hello regular user! I haven\'t written anything for you yet, but eventually.');
+
//$wgOut->AddWikiText('Hello regular user! I haven\'t written anything for you yet, but eventually.');
  }
+
$sql = 'SELECT MIN(`When`) AS WhenEarly, COUNT(ID) AS Count, didAllow FROM attempt GROUP BY didAllow';
 +
$objRows = self::DB()->DataSet($sql);
 +
if ($objRows->HasRows()) {
 +
    $utOldest = NULL;
 +
    while ($objRows->NextRow()) {
 +
$intCount = $objRows->Row['Count'];
 +
$utWhen = strtotime($objRows->Row['WhenEarly']);
 +
if (is_null($utOldest) || ($utWhen < $utOldest)) {
 +
    $utOldest = $utWhen;
 +
}
 +
if ($objRows->didAllow) {
 +
    $outAllowed = $intCount.' edit'.Pluralize($intCount).' allowed';
 +
} else {
 +
    $outRejected = $intCount.' attempted spam'.Pluralize($intCount).' rejected';
 +
}
 +
    }
 +
    $out = $outRejected.' and '.$outAllowed.' since '.date('F j, Y',$utOldest).'.';
 +
} else {
 +
    $out = 'No edit attempts recorded by SpamFerret yet!';
 +
}
 +
$wgOut->AddHTML($out);
 +
// URL needs to be broken up in order not to get filtered as spam >.<
 +
$wgOut->AddHTML('<br>See <a href="http'.'://htyp.org/SpamFerret">HTYP</a> for all available documentation.');
 +
    }
 
// individual admin functions
 
// individual admin functions
 
     public function doInspectEdits() {
 
     public function doInspectEdits() {
 
global $wgOut,$wgRequest;
 
global $wgOut,$wgRequest;
 
 
$sqlFilt = $wgRequest->getVal('sqlFilt','');
+
$arOpts['filt'] = $wgRequest->getVal('sqlFilt','');
$sqlSort = $wgRequest->getVal('sqlSort','ID DESC');
+
$arOpts['sort'] = $wgRequest->getVal('sqlSort','ID DESC');
$sqlRows = $wgRequest->getVal('sqlRows',50);
+
$arOpts['rows'] = $wgRequest->getVal('sqlRows',50);
 
+
// LATER: display form for changing these defaults
if ($sqlFilt == '') {
 
    $sqlFiltTerm = '';
 
} else {
 
    $sqlFiltTerm = ' WHERE '.$sqlFilt;
 
}
 
  
if ($sqlSort == '') {
+
//$objTbl =  
    $sqlSortTerm = '';
+
//$objRows->
} else {
 
    $sqlSortTerm = ' ORDER BY '.$sqlSort;
 
}
 
  
if ($sqlRows == '') {
 
    $sqlRowsTerm = '';
 
} else {
 
    $sqlRowsTerm = ' LIMIT '.$sqlRows;
 
}
 
$sql = 'SELECT * FROM attempts'.$sqlFiltTerm.$sqlSortTerm.$sqlRowsTerm;
 
 
     }
 
     }
 
     public function doEditFilter($iID) {
 
     public function doEditFilter($iID) {
Line 337: Line 258:
 
$wgOut->AddHTML('</form>');
 
$wgOut->AddHTML('</form>');
 
$wgOut->AddWikiText('==Results==');
 
$wgOut->AddWikiText('==Results==');
$wgOut->AddWikiText("'''checked''': ".htmlspecialchars($inExpr),TRUE);
+
$wgOut->AddWikiText("'''checked''': <nowiki>".htmlspecialchars($inExpr),TRUE).'</nowiki>';
 +
/*
 +
// prefix any '/' characters with an escape ('\') because we are using the format which requires '/' at either end
 
$chDelim = '/';
 
$chDelim = '/';
 
$strPattCk = str_replace($chDelim,'\\'.$chDelim,$inExpr);
 
$strPattCk = str_replace($chDelim,'\\'.$chDelim,$inExpr);
 
$isMatch = @preg_match('/'.$strPattCk.'/',$inText,$matches);
 
$isMatch = @preg_match('/'.$strPattCk.'/',$inText,$matches);
 +
*/
 +
// first 2 lines are a kluge until CheckRegex() is static, returning results in array
 +
$objSF = new SpamFerret();
 +
 +
global $gRegexMatches,$strDbg;
 +
$isMatch = $objSF->CheckRegex($inExpr,$inText);
 +
$wgOut->AddWikiText($strDbg,TRUE);
 +
$matches = $gRegexMatches;
 +
 
if (isset($php_errormsg)) {
 
if (isset($php_errormsg)) {
 
      $outErr .= "===Error===\n$php_errormsg";
 
      $outErr .= "===Error===\n$php_errormsg";
Line 366: Line 298:
 
if ($inText != '') {
 
if ($inText != '') {
 
    $wgOut->AddWikiText('==Results==');
 
    $wgOut->AddWikiText('==Results==');
    if ($doEcho) {
 
$wgOut->AddWikiText("'''checked''': ".htmlspecialchars($inText),TRUE);
 
    }
 
  
 
    $objSF = new SpamFerret();
 
    $objSF = new SpamFerret();
 
    $objSF->OpenDatabase();
 
    $objSF->OpenDatabase();
 
    $objSF->txtEditRaw = $inText;
 
    $objSF->txtEditRaw = $inText;
    $objSF->CheckFilters(TRUE);
+
    $arArgs['doAll'] = TRUE;
    $wgOut->AddWikiText('* '.$gFilterRows.' filter'.Pluralize($gFilterRows).' defined');
+
  // LATER: allow user to enter title of existing page for generating diff
    $wgOut->AddWikiText('* '.$gFilterCount.' filter'.Pluralize($gFilterCount).' checked');
+
    $arArgs['diff'] = '!!NEW: '.$inText;
 +
    if ($doEcho) {
 +
$out = "* '''checked''':";
 +
$out .= "\n** '''plain''': ".htmlspecialchars($inText);
 +
$out .= "\n** '''diff''': ".htmlspecialchars($arArgs['diff']);
 +
$wgOut->AddWikiText($out,TRUE);
 +
    }
 +
    $objSF->CheckFilters($arArgs);
 +
    $out =
 +
      "\n* ".$gFilterRows.' filter'.Pluralize($gFilterRows).' defined'.
 +
      "\n* ".$gFilterCount.' filter'.Pluralize($gFilterCount).' checked';
 +
    $wgOut->AddWikiText($out);
 
    if (is_array($gFilterMatches)) {
 
    if (is_array($gFilterMatches)) {
 
$out = "{|\n|-\n! ID || length || filter";
 
$out = "{|\n|-\n! ID || length || filter";
Line 384: Line 324:
 
    $isOdd = !$isOdd;
 
    $isOdd = !$isOdd;
  
    $objFilt = $objSF->PatternTbl->GetItem($id);
+
    $objFilt = $objSF->FiltTbl()->GetItem($id);
  
 
    $isActive = $objFilt->isActive;
 
    $isActive = $objFilt->isActive;
Line 402: Line 342:
 
}
 
}
 
     }
 
     }
 +
/*
 +
LATER: for debugging why a particular string doesn't seem to be triggering the filter it should trigger
 +
    public function CheckFiltersLocal($iCheckAll) {
 +
global $gRegexMatches,$gFilterMatches,$gFilterRows,$gFilterCount;
 +
global $debug;
 +
 +
$this->PatternTbl = new clsTable($this->dbSpam);
 +
  $this->PatternTbl->Name('patterns');
 +
  $this->PatternTbl->KeyName('ID');
 +
 +
$this->PatternRows = $this->PatternTbl->GetData();
 +
$objRow = $this->PatternRows;
 +
 +
$strTextEdit = strtolower($this->txtEditRaw);
 +
$this->txtEditChk = $strTextEdit; // text after being massaged for checking
 +
$this->isMatch = FALSE;
 +
$gFilterCount = 0;
 +
$gFilterRows = $this->PatternRows->RowCount();
 +
//$objDataPatterns->StartRows();
 +
while($objRow->NextRow() && (!$this->isMatch || $iCheckAll)) {
 +
    $isMatch = FALSE;
 +
    if ($objRow->isDiff) {
 +
if (isset($this->txtDiff)) {
 +
    $strTextCk = $this->txtDiff;
 +
} else {
 +
    $strTextCk = NULL;
 +
}
 +
    } else {
 +
$strTextCk = $strTextEdit;
 +
    }
 +
    if (!is_null($strTextCk)) {
 +
$gFilterCount++;
 +
$strPattern = $objRow->Pattern;
 +
$isRegex = $objRow->isRegex;
 +
$this->idPattern = $objRow->ID;
 +
if ($isRegex) {
 +
    $isMatch = $this->CheckRegex($strPattern,$strTextCk);
 +
 +
    if (isset($php_errormsg)) {
 +
    $this->AddErrorLine('Filter #'.$this->idPattern.' generated error "'.$php_errormsg);
 +
    }
 +
 +
    if ($isMatch) {
 +
    $this->strMatch = $gRegexMatches[0];
 +
    }
 +
} else {
 +
    if (empty($strPattern)) {
 +
$isMatch = FALSE;
 +
    } else {
 +
$this->strMatch = stristr($strTextCk,$strPattern);
 +
$isMatch = ($this->strMatch != '');
 +
    }
 +
}
 +
if ($isMatch) {
 +
    $this->isMatch = TRUE;
 +
    if ($iCheckAll) {
 +
$gFilterMatches[$this->idPattern] = $this->strMatch;
 +
    }
 +
}
 +
    }
 +
}
 +
    }
 +
*/
 
}
 
}
 +
class clsAttempts extends clsTable {
 +
    public function __construct($iDB) {
 +
parent::__construct($iDB);
 +
  $this->Name('attempt');
 +
  $this->KeyName('ID');
 +
  $this->ClassSng('clsAttempt');
 +
    }
 +
    public function GetRecent(array $iarOpts) {
 +
if (empty($iarOpts['filt'])) {
 +
    $sqlFilt = '';
 +
} else {
 +
    $sqlFilt = ' WHERE '.$iarOpts['filt'];
 +
}
 +
 +
if (empty($iarOpts['sort'])) {
 +
    $sqlSort = '';
 +
} else {
 +
    $sqlSort = ' ORDER BY '.$iarOpts['sort'];
 +
}
 +
 +
if (empty($iarOpts['rows'])) {
 +
    $sqlRows = '';
 +
} else {
 +
    $sqlRows = ' LIMIT '.$iarOpts['rows'];
 +
}
 +
$sql = 'SELECT * FROM attempts'.$sqlFilt.$sqlSort.$sqlRows;
 +
$objRows = $this->DataSet($sql);
 +
return $objRows;
 +
    }
 +
}
 +
class clsAttempt extends clsDataSet {
 +
}
 +
 +
// UTILITY FUNCTIONS //
 
function SpIDSelfLink($iDo,$iKey,$iVal,$iText) {
 
function SpIDSelfLink($iDo,$iKey,$iVal,$iText) {
 
//    return '[[{{FULLPAGENAME}}/do'.KS_CHAR_URL_ASSIGN.$iDo.'/'.$iKey.KS_CHAR_URL_ASSIGN.$iVal.'|'.$iText.']]';
 
//    return '[[{{FULLPAGENAME}}/do'.KS_CHAR_URL_ASSIGN.$iDo.'/'.$iKey.KS_CHAR_URL_ASSIGN.$iVal.'|'.$iText.']]';
Line 435: Line 472:
 
}
 
}
 
//--
 
//--
}
+
}</php>
</php>
 

Latest revision as of 18:46, 18 August 2010

Code

<php><?php /*

NAME: SpecialSpamFerret
PURPOSE: Special page for administering the SpamFerret database
REQUIRES: SpamFerret (for now...)
AUTHOR: Woozle (Nick) Staddon
VERSION:

2009-08-04 0.0 (Wzl) Started writing 2009-10-01 0.1 (Wzl) incremental improvements; clsMenu now a separate file 2009-10-06 0.2 (Wzl) text-check now shows if matching filters are deactivated 2010-02-23 0.3 (Wzl) finally gave regular users some brief summary text to look at 2010-08-17 0.31 (Wzl) a bit of debugging display in the regex checker

  • /

$wgSpecialPages['SpamFerret'] = 'SpecialSpamFerret'; # Let MediaWiki know about your new special page. $wgExtensionCredits['other'][] = array(

       'name' => 'Special:SpamFerret',

'url' => 'http://htyp.org/SpamFerret',

       'description' => 'special page for SpamFerret administration',
       'author' => 'Woozle (Nick) Staddon',

'version' => '0.31 2010-08-17 alpha' ); define('KS_CHAR_URL_ASSIGN',':'); // character used for encoding values in wiki-internal URLs

function wfSpecialSpamFerret() { // This registers the page's class. I think. global $wgRequest;

$app = new SpecialSpamFerret($wgRequest); }

require_once( $wgScriptPath.'includes/SpecialPage.php' ); if (!defined('LIBMGR')) {

   require('libmgr.php');

} clsLibMgr::Add('menus', KFP_MW_PLUGINS.'/menu.php',__FILE__,__LINE__); clsLibMgr::Load('menus' ,__FILE__,__LINE__);

class SpecialSpamFerret extends SpecialPage { //======= // STATIC

   static private $objDB;
   static public function Setting($iName) {

global $wgSpamFerretSettings;

return $wgSpamFerretSettings[$iName];

   }
   static public function DB() {

if (!isset(self::$objDB)) { self::$objDB = new clsDatabase(self::Setting('dbspec')); self::$objDB->Open(); } return self::$objDB;

   }

//======= // DYNAMIC

 protected $args;
 public function __construct() {

global $wgMessageCache;

parent::__construct( 'SpamFerret' ); $this->includable( false );

       $wgMessageCache->addMessage('spamferret', 'SpamFerret administration');
 }
 function execute( $par ) {

global $wgUser;

$this->setHeaders(); $this->GetArgs($par);

if ($wgUser->isAllowed('editinterface')) { $this->doAdmin(); } else { $this->doUser(); }

 }
 private function GetArgs($par) {

/*

PURPOSE: Parses variable arguments from the URL
 The URL is formatted as a series of arguments /arg=val/arg=val/..., so that we can always refer directly
   to any particular item as a wiki page title while also not worrying about hierarchy/order.
  • /
   $args_raw = split('/',$par);
   foreach($args_raw as $arg_raw) {

if (strpos($arg_raw,KS_CHAR_URL_ASSIGN) !== FALSE) { list($key,$val) = split(KS_CHAR_URL_ASSIGN,$arg_raw); $this->args[$key] = $val; }

   }
 }
 public function doAdmin() {

global $wgOut; /* PURPOSE: do stuff that only admins are allowed to do

  • /

if (isset($this->args['page'])) { $page = $this->args['page']; } else { $page = NULL; } // display menu $wtSelf = 'Special:'.$this->name();

$objMenu = new clsMenu($wtSelf); $objMenu->Add($objRow = new clsMenuRow('Utilities','menu.util')); $objRow->Add(new clsMenuItem('check expression','ckexpr')); $objRow->Add(new clsMenuItem('check text','cktext')); $objMenu->Add($objRow = new clsMenuRow('Inspect','menu.insp')); $objRow->Add(new clsMenuItem('recent edits','edits')); $objRow->Add(new clsMenuItem('filters','filters'));

$out = $objMenu->WikiText($page); $out .= $objMenu->Execute();

$wgOut->addHTML('

');

$wgOut->addWikiText($out,TRUE); $out = ;

$wgOut->addHTML('

');

if (!is_null($page)) { $id = isset($this->args['id'])?$this->args['id']:NULL; switch ($page) { case 'ckexpr': $this->doRegexChecker(); break; case 'cktext': $this->doTextChecker(); break; case 'edits': $this->doInspectEdits(); break; case 'filters': $this->doInspectFilters(); break; case 'filter': $this->doEditFilter($id); } }

 }
 public function doUser() {

global $wgOut; /* PURPOSE: do only stuff that regular users are allowed to do

  • /

//$wgOut->AddWikiText('Hello regular user! I haven\'t written anything for you yet, but eventually.'); $sql = 'SELECT MIN(`When`) AS WhenEarly, COUNT(ID) AS Count, didAllow FROM attempt GROUP BY didAllow'; $objRows = self::DB()->DataSet($sql); if ($objRows->HasRows()) { $utOldest = NULL; while ($objRows->NextRow()) { $intCount = $objRows->Row['Count']; $utWhen = strtotime($objRows->Row['WhenEarly']); if (is_null($utOldest) || ($utWhen < $utOldest)) { $utOldest = $utWhen; } if ($objRows->didAllow) { $outAllowed = $intCount.' edit'.Pluralize($intCount).' allowed'; } else { $outRejected = $intCount.' attempted spam'.Pluralize($intCount).' rejected'; } } $out = $outRejected.' and '.$outAllowed.' since '.date('F j, Y',$utOldest).'.'; } else { $out = 'No edit attempts recorded by SpamFerret yet!'; } $wgOut->AddHTML($out); // URL needs to be broken up in order not to get filtered as spam >.< $wgOut->AddHTML('
See <a href="http'.'://htyp.org/SpamFerret">HTYP</a> for all available documentation.');

   }

// individual admin functions

   public function doInspectEdits() {

global $wgOut,$wgRequest;

$arOpts['filt'] = $wgRequest->getVal('sqlFilt',); $arOpts['sort'] = $wgRequest->getVal('sqlSort','ID DESC'); $arOpts['rows'] = $wgRequest->getVal('sqlRows',50); // LATER: display form for changing these defaults

//$objTbl = //$objRows->

   }
   public function doEditFilter($iID) {

global $wgOut;

$dbSP = self::DB(); $tblFilt = new clsTable($dbSP); $tblFilt->Name('patterns'); $tblFilt->KeyName('ID'); $objRows = $tblFilt->GetItem($iID); if ($objRows->hasRows()) { $htPattern = htmlspecialchars($objRows->Pattern);

$out = '

'; $out .= "\n"; $out .= "\n"; $out .= "\n"; $out .= "\n"; $out .= "\n
ID:{$objRows->ID}
Pattern:{$htPattern}
Added:{$objRows->WhenAdded}
Tried:{$objRows->WhenTried}
flags:";

$out .= ShowFlag('active',$objRows->isActive,'Active'); $out .= ShowFlag('regex',$objRows->isRegex,'Regex'); $out .= ShowFlag('diff',$objRows->isDiff,'Diff'); $out .= ShowFlag('isurl',$objRows->isURL,'URL');

$out .= '

';

$wgOut->AddHTML($out); $out = ; }

   }
   public function doInspectFilters() {

global $wgOut;

$dbSP = self::DB(); $tblFilt = new clsTable($dbSP); $tblFilt->Name('patterns'); $tblFilt->KeyName('ID'); $objRows = $tblFilt->GetData(); if ($objRows->hasRows()) { $out = "{| class=sortable\n|-\n! ID || Pattern || A? || U? || R? || D? || Added || Tried || Count"; $isOdd = TRUE; while ($objRows->NextRow()) { $wtStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;'; $isOdd = !$isOdd;

$id = $objRows->ID; $wtID = SpIDSelfLink('filter','id',$id,$id); $strPatt = ''.$objRows->Pattern.''; $isActive = $objRows->isActive; $isURL = $objRows->isURL; $isRegex = $objRows->isRegex; $isDiff = $objRows->isDiff; $wtAdded = TimeStamp_HideTime($objRows->WhenAdded); $wtTried = TimeStamp_HideTime($objRows->WhenTried); $intCount = $objRows->Count;

$out .= "\n|- style=\"$wtStyle\"\n|$wtID||$strPatt||$isActive||$isURL||$isRegex||$isDiff||$wtAdded||$wtTried||align=right|$intCount"; } $out .= "\n|}\n"; $wgOut->AddWikiText($out); } else { $wgOut->AddHTML('No filters have been defined.'); if (!$dbSP->isOk()) { $wgOut->AddHTML('
Database Error: '.$dbSP->getError()); } }

   }
   public function doRegexChecker() {

global $wgOut,$wgRequest;

$inExpr = $wgRequest->getVal('expr'); $inText = $wgRequest->getVal('sample');

$wgOut->AddHTML('<form method=post action="">'); $wgOut->AddHTML('Expression: <input name=expr size=80 value="'.htmlspecialchars($inExpr).'">'); $wgOut->AddHTML('
Text to check:
<textarea name=sample cols=50 rows=10>'.htmlspecialchars($inText).'</textarea>'); $wgOut->AddHTML('<input name=go type=submit value="Evaluate">'); $wgOut->AddHTML('</form>'); $wgOut->AddWikiText('==Results=='); $wgOut->AddWikiText("checked: ".htmlspecialchars($inExpr),TRUE).''; /* // prefix any '/' characters with an escape ('\') because we are using the format which requires '/' at either end $chDelim = '/'; $strPattCk = str_replace($chDelim,'\\'.$chDelim,$inExpr); $isMatch = @preg_match('/'.$strPattCk.'/',$inText,$matches);

  • /

// first 2 lines are a kluge until CheckRegex() is static, returning results in array $objSF = new SpamFerret();

global $gRegexMatches,$strDbg; $isMatch = $objSF->CheckRegex($inExpr,$inText); $wgOut->AddWikiText($strDbg,TRUE); $matches = $gRegexMatches;

if (isset($php_errormsg)) { $outErr .= "===Error===\n$php_errormsg"; $wgOut->AddWikiText($outErr); } else { $wgOut->AddWikiText("===Matches===");

$wgOut->AddHTML('

'.htmlspecialchars(var_export($matches,TRUE)).'

');

}

   }
   public function doTextChecker() {

global $wgOut,$wgRequest; global $gFilterMatches,$gFilterCount,$gFilterRows; global $debug;

$inText = $wgRequest->getVal('sample'); $doEcho = $wgRequest->getVal('doShowText'); $htDoEcho = $doEcho?' checked':;

$wgOut->AddHTML('Check sample text against all defined filters.'); $wgOut->AddHTML('<form method=post action="">'); $wgOut->AddHTML('
Text to check:
<textarea name=sample cols=50 rows=10>'.$inText.'</textarea>'); $wgOut->AddHTML('<input name=go type=submit value="Evaluate">'); $wgOut->AddHTML('<input name=doShowText type=checkbox'.$htDoEcho.'>Echo input text'); $wgOut->AddHTML('</form>'); if ($inText != ) { $wgOut->AddWikiText('==Results==');

$objSF = new SpamFerret(); $objSF->OpenDatabase(); $objSF->txtEditRaw = $inText; $arArgs['doAll'] = TRUE; // LATER: allow user to enter title of existing page for generating diff $arArgs['diff'] = '!!NEW: '.$inText; if ($doEcho) { $out = "* checked:"; $out .= "\n** plain: ".htmlspecialchars($inText); $out .= "\n** diff: ".htmlspecialchars($arArgs['diff']); $wgOut->AddWikiText($out,TRUE); } $objSF->CheckFilters($arArgs); $out = "\n* ".$gFilterRows.' filter'.Pluralize($gFilterRows).' defined'. "\n* ".$gFilterCount.' filter'.Pluralize($gFilterCount).' checked'; $wgOut->AddWikiText($out); if (is_array($gFilterMatches)) { $out = "{|\n|-\n! ID || length || filter"; $isOdd = FALSE; foreach ($gFilterMatches as $id=>$text) {

$wtStyle = $isOdd?'background:#ffffff;':'background:#eeeeee;'; $isOdd = !$isOdd;

$objFilt = $objSF->FiltTbl()->GetItem($id);

$isActive = $objFilt->isActive; if (!$isActive) { $wtStyle .= ' color: #888888;'; $wtStyle .= ' text-decoration: line-through;'; }

$out .= "\n|- style=\"$wtStyle\"\n| $id || ".strlen($text)." || {$objFilt->Pattern}"; } $out .= "\n|}"; } else { $out = "* No filter matches"; } $wgOut->AddWikiText($out); //$wgOut->AddWikiText('* DEBUG: '.$debug); }

   }

/*

LATER: for debugging why a particular string doesn't seem to be triggering the filter it should trigger
   public function CheckFiltersLocal($iCheckAll) {

global $gRegexMatches,$gFilterMatches,$gFilterRows,$gFilterCount; global $debug;

$this->PatternTbl = new clsTable($this->dbSpam); $this->PatternTbl->Name('patterns'); $this->PatternTbl->KeyName('ID');

$this->PatternRows = $this->PatternTbl->GetData(); $objRow = $this->PatternRows;

$strTextEdit = strtolower($this->txtEditRaw); $this->txtEditChk = $strTextEdit; // text after being massaged for checking $this->isMatch = FALSE; $gFilterCount = 0; $gFilterRows = $this->PatternRows->RowCount(); //$objDataPatterns->StartRows(); while($objRow->NextRow() && (!$this->isMatch || $iCheckAll)) { $isMatch = FALSE; if ($objRow->isDiff) { if (isset($this->txtDiff)) { $strTextCk = $this->txtDiff; } else { $strTextCk = NULL; } } else { $strTextCk = $strTextEdit; } if (!is_null($strTextCk)) { $gFilterCount++; $strPattern = $objRow->Pattern; $isRegex = $objRow->isRegex; $this->idPattern = $objRow->ID; if ($isRegex) { $isMatch = $this->CheckRegex($strPattern,$strTextCk);

if (isset($php_errormsg)) { $this->AddErrorLine('Filter #'.$this->idPattern.' generated error "'.$php_errormsg); }

if ($isMatch) { $this->strMatch = $gRegexMatches[0]; } } else { if (empty($strPattern)) { $isMatch = FALSE; } else { $this->strMatch = stristr($strTextCk,$strPattern); $isMatch = ($this->strMatch != ); } } if ($isMatch) { $this->isMatch = TRUE; if ($iCheckAll) { $gFilterMatches[$this->idPattern] = $this->strMatch; } } } }

   }
  • /

} class clsAttempts extends clsTable {

   public function __construct($iDB) {

parent::__construct($iDB); $this->Name('attempt'); $this->KeyName('ID'); $this->ClassSng('clsAttempt');

   }
   public function GetRecent(array $iarOpts) {

if (empty($iarOpts['filt'])) { $sqlFilt = ; } else { $sqlFilt = ' WHERE '.$iarOpts['filt']; }

if (empty($iarOpts['sort'])) { $sqlSort = ; } else { $sqlSort = ' ORDER BY '.$iarOpts['sort']; }

if (empty($iarOpts['rows'])) { $sqlRows = ; } else { $sqlRows = ' LIMIT '.$iarOpts['rows']; } $sql = 'SELECT * FROM attempts'.$sqlFilt.$sqlSort.$sqlRows; $objRows = $this->DataSet($sql); return $objRows;

   }

} class clsAttempt extends clsDataSet { }

// UTILITY FUNCTIONS // function SpIDSelfLink($iDo,$iKey,$iVal,$iText) { // return ''.$iText.'';

   return ''.$iText.'';

} /* function SelfLink($iPage,$iKey,$iVal,$iText) {

   return ''.$iText.'';

}

  • /

function ShowFlag($iName,$iVal,$iText) {

   $out = '<input type=checkbox name="'.$iName.'" value='.$iVal.'>'.$iText;
   return $out;

}

if (!function_exists('TimeStamp_HideTime')) { //-- function TimeStamp_HideTime($iStamp) {

   if (is_string($iStamp)) {

$intStamp = strtotime($iStamp);

   } else if (is_int($iStamp)) {

$intStamp = $iStamp;

   } else {

$intStamp = NULL;

   }
   if (!is_null($intStamp)) {

return date('Y-m-d',$intStamp);

   } else {

return NULL;

   }

} //-- }</php>