SpamFerret/Special

From HTYP, the free directory anyone can edit

Jump to: navigation, search

[edit] Code

<?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
*/
$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.2 2009-10-06 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' );
/*
class clsMenu {
    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;
    }
}
 
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 {
//=======
// 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('<table style="background: #ccffcc;"><tr><td>');
	$wgOut->addWikiText($out,TRUE);	$out = '';
	$wgOut->addHTML('</td></tr></table>');
 
	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.');
  }
// individual admin functions
    public function doInspectEdits() {
	global $wgOut,$wgRequest;
 
	$sqlFilt = $wgRequest->getVal('sqlFilt','');
	$sqlSort = $wgRequest->getVal('sqlSort','ID DESC');
	$sqlRows = $wgRequest->getVal('sqlRows',50);
 
	if ($sqlFilt == '') {
	    $sqlFiltTerm = '';
	} else {
	    $sqlFiltTerm = ' WHERE '.$sqlFilt;
	}
 
	if ($sqlSort == '') {
	    $sqlSortTerm = '';
	} else {
	    $sqlSortTerm = ' ORDER BY '.$sqlSort;
	}
 
	if ($sqlRows == '') {
	    $sqlRowsTerm = '';
	} else {
	    $sqlRowsTerm = ' LIMIT '.$sqlRows;
	}
	$sql = 'SELECT * FROM attempts'.$sqlFiltTerm.$sqlSortTerm.$sqlRowsTerm;
    }
    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 = '<table>';
	    $out .= "\n<tr><td align=right><b>ID</b>:</td><td>{$objRows->ID}</td></tr>";
	    $out .= "\n<tr><td align=right><b>Pattern</b>:</td><td>{$htPattern}</td></tr>";
	    $out .= "\n<tr><td align=right><b>Added</b>:</td><td>{$objRows->WhenAdded}</td></tr>";
	    $out .= "\n<tr><td align=right><b>Tried</b>:</td><td>{$objRows->WhenTried}</td></tr>";
	    $out .= "\n<tr><td align=right><b>flags</b>:</td><td>";
	    $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 .= '</td></tr></table>';
	    $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 = '<nowiki>'.$objRows->Pattern.'</nowiki>';
		$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('<br><b>Database Error</b>: '.$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('<br>Text to check:<br><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);
	$chDelim = '/';
	$strPattCk = str_replace($chDelim,'\\'.$chDelim,$inExpr);
	$isMatch = @preg_match('/'.$strPattCk.'/',$inText,$matches);
	if (isset($php_errormsg)) {
	      $outErr .= "===Error===\n$php_errormsg";
	      $wgOut->AddWikiText($outErr);
	} else {
	      $wgOut->AddWikiText("===Matches===");
	      $wgOut->AddHTML('<pre>'.htmlspecialchars(var_export($matches,TRUE)).'</pre>');
	}
    }
    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('<br>Text to check:<br><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==');
	    if ($doEcho) {
		$wgOut->AddWikiText("'''checked''': ".htmlspecialchars($inText),TRUE);
	    }
 
	    $objSF = new SpamFerret();
	    $objSF->OpenDatabase();
	    $objSF->txtEditRaw = $inText;
	    $objSF->CheckFilters(TRUE);
	    $wgOut->AddWikiText('* '.$gFilterRows.' filter'.Pluralize($gFilterRows).' defined');
	    $wgOut->AddWikiText('* '.$gFilterCount.' filter'.Pluralize($gFilterCount).' checked');
	    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->PatternTbl->GetItem($id);
 
		    $isActive = $objFilt->isActive;
		    if (!$isActive) {
			$wtStyle .= ' color: #888888;';
			$wtStyle .= ' text-decoration: line-through;';
		    }
 
		    $out .= "\n|- style=\"$wtStyle\"\n| $id || ".strlen($text)." || <nowiki>{$objFilt->Pattern}</nowiki>";
		}
		$out .= "\n|}";
	    } else {
		$out = "* No filter matches";
	    }
	    $wgOut->AddWikiText($out);
	    //$wgOut->AddWikiText('* DEBUG: '.$debug);
	}
    }
}
function SpIDSelfLink($iDo,$iKey,$iVal,$iText) {
//    return '[[{{FULLPAGENAME}}/do'.KS_CHAR_URL_ASSIGN.$iDo.'/'.$iKey.KS_CHAR_URL_ASSIGN.$iVal.'|'.$iText.']]';
    return '[[Special:AudioFerret/do'.KS_CHAR_URL_ASSIGN.$iDo.'/'.$iKey.KS_CHAR_URL_ASSIGN.$iVal.'|'.$iText.']]';
}
/*
function SelfLink($iPage,$iKey,$iVal,$iText) {
    return '[[{{FULLPAGENAME}}/page'.KS_CHAR_URL_ASSIGN.$iPage.'/'.$iKey.KS_CHAR_URL_ASSIGN.$iVal.'|'.$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;
    }
}
//--
}
 
Personal tools