00001 <?php
00023 require_once( dirname(__FILE__) . '/Maintenance.php' );
00024
00025 class CleanupSpam extends Maintenance {
00026 public function __construct() {
00027 parent::__construct();
00028 $this->mDescription = "Cleanup all spam from a given hostname";
00029 $this->addOption( 'all', 'Check all wikis in $wgLocalDatabases' );
00030 $this->addArg( 'hostname', 'Hostname that was spamming' );
00031 }
00032
00033 public function execute() {
00034 global $wgLocalDatabases;
00035
00036 $username = wfMsg( 'spambot_username' );
00037 $wgUser = User::newFromName( $username );
00038
00039 if ( !$wgUser->getId() ) {
00040 $wgUser->addToDatabase();
00041 }
00042 $spec = $this->getArg();
00043 $like = LinkFilter::makeLikeArray( $spec );
00044 if ( !$like ) {
00045 $this->error( "Not a valid hostname specification: $spec", true );
00046 }
00047
00048 if ( $this->hasOption('all') ) {
00049
00050 $this->output( "Finding spam on " . count( $wgLocalDatabases ) . " wikis\n" );
00051 $found = false;
00052 foreach ( $wgLocalDatabases as $wikiID ) {
00053 $dbr = wfGetDB( DB_SLAVE, array(), $wikiID );
00054
00055 $count = $dbr->selectField( 'externallinks', 'COUNT(*)',
00056 array( 'el_index' . $dbr->buildLike( $like ) ), __METHOD__ );
00057 if ( $count ) {
00058 $found = true;
00059 passthru( "php cleanupSpam.php --wiki='$wikiID' $spec | sed 's/^/$wikiID: /'" );
00060 }
00061 }
00062 if ( $found ) {
00063 $this->output( "All done\n" );
00064 } else {
00065 $this->output( "None found\n" );
00066 }
00067 } else {
00068
00069
00070 $dbr = wfGetDB( DB_SLAVE );
00071 $res = $dbr->select( 'externallinks', array( 'DISTINCT el_from' ),
00072 array( 'el_index' . $dbr->buildLike( $like ) ), __METHOD__ );
00073 $count = $dbr->numRows( $res );
00074 $this->output( "Found $count articles containing $spec\n" );
00075 foreach ( $res as $row ) {
00076 $this->cleanupArticle( $row->el_from, $spec );
00077 }
00078 if ( $count ) {
00079 $this->output( "Done\n" );
00080 }
00081 }
00082 }
00083
00084 private function cleanupArticle( $id, $domain ) {
00085 $title = Title::newFromID( $id );
00086 if ( !$title ) {
00087 $this->error( "Internal error: no page for ID $id" );
00088 return;
00089 }
00090
00091 $this->output( $title->getPrefixedDBkey() . " ..." );
00092 $rev = Revision::newFromTitle( $title );
00093 $revId = $rev->getId();
00094 $currentRevId = $revId;
00095
00096 while ( $rev && LinkFilter::matchEntry( $rev->getText() , $domain ) ) {
00097 # Revision::getPrevious can't be used in this way before MW 1.6 (Revision.php 1.26)
00098 #$rev = $rev->getPrevious();
00099 $revId = $title->getPreviousRevisionID( $revId );
00100 if ( $revId ) {
00101 $rev = Revision::newFromTitle( $title, $revId );
00102 } else {
00103 $rev = false;
00104 }
00105 }
00106 if ( $revId == $currentRevId ) {
00107
00108
00109 $this->output( "False match\n" );
00110 } else {
00111 $dbw = wfGetDB( DB_MASTER );
00112 $dbw->begin();
00113 if ( !$rev ) {
00114
00115 $this->output( "blanking\n" );
00116 $article = new Article( $title );
00117 $article->updateArticle( '', wfMsg( 'spam_blanking', $domain ),
00118 false, false );
00119
00120 } else {
00121
00122 $this->output( "reverting\n" );
00123 $article = new Article( $title );
00124 $article->updateArticle( $rev->getText(), wfMsg( 'spam_reverting', $domain ), false, false );
00125 }
00126 $dbw->commit();
00127 wfDoUpdates();
00128 }
00129 }
00130 }
00131
00132 $maintClass = "CleanupSpam";
00133 require_once( DO_MAINTENANCE );