/* private */ var $mUser, $mTimestamp, $mUserText;
/* private */ var $mCounter, $mComment, $mCountAdjustment;
/* private */ var $mMinorEdit, $mRedirectedFrom;
- /* private */ var $mTouched;
+ /* private */ var $mTouched, $mFileCache;
function Article() { $this->clear(); }
$this->mContentLoaded = false;
$this->mUser = $this->mCounter = -1; # Not loaded
$this->mRedirectedFrom = $this->mUserText =
- $this->mTimestamp = $this->mComment = "";
+ $this->mTimestamp = $this->mComment = $this->mFileCache = "";
$this->mCountAdjustment = 0;
$this->mTouched = "19700101000000";
}
if ( "initial" == $formtype ) {
$wpEdittime = $this->getTimestamp();
- $wpTextbox1 = $this->getContent();
+ $wpTextbox1 = $this->getContent(true);
$wpSummary = "";
}
$wgOut->setRobotpolicy( "noindex,nofollow" );
$wgOut->addHTML( wfMsg( "explainconflict" ) );
$wpTextbox2 = $wpTextbox1;
- $wpTextbox1 = $this->getContent();
+ $wpTextbox1 = $this->getContent(true);
$wpEdittime = $this->getTimestamp();
} else {
$s = str_replace( "$1", $wgTitle->getPrefixedText(),
}
}
$wgOut->addHTML( "
-<form id=\"editform\" method=\"post\" action=\"$action\"
+<form id=\"editform\" name=\"editform\" method=\"post\" action=\"$action\"
enctype=\"application/x-www-form-urlencoded\">
<textarea tabindex=1 name=\"wpTextbox1\" rows={$rows}
cols={$cols}{$ew} wrap=\"virtual\">" .
$now = wfTimestampNow();
$won = wfInvertTimestamp( $now );
+ wfSeedRandom();
+ $rand = mt_rand() / mt_getrandmax();
$sql = "INSERT INTO cur (cur_namespace,cur_title,cur_text," .
"cur_comment,cur_user,cur_timestamp,cur_minor_edit,cur_counter," .
"cur_restrictions,cur_user_text,cur_is_redirect," .
wfStrencode( $summary ) . "', '" .
$wgUser->getID() . "', '{$now}', " .
( $isminor ? 1 : 0 ) . ", 0, '', '" .
- wfStrencode( $wgUser->getName() ) . "', $redir, 1, RAND(), '{$now}', '{$won}')";
+ wfStrencode( $wgUser->getName() ) . "', $redir, 1, $rand, '{$now}', '{$won}')";
$res = wfQuery( $sql, $fname );
$newid = wfInsertId();
$wgOut->fatalError( wfMsg( "cannotdelete" ) );
return;
}
- $sub = str_replace( "$1", $image, wfMsg( "deletesub" ) );
+ $sub = str_replace( "$1", $image, wfMsg( "deletesub" ) );
} else {
+
if ( ( "" == trim( $wgTitle->getText() ) )
or ( $wgTitle->getArticleId() == 0 ) ) {
$wgOut->fatalError( wfMsg( "cannotdelete" ) );
return;
}
$sub = str_replace( "$1", $wgTitle->getPrefixedText(),
- wfMsg( "deletesub" ) );
+ wfMsg( "deletesub" ) );
+
+ # determine whether this page has earlier revisions
+ # and insert a warning if it does
+ # we select the text because it might be useful below
+ $sql="SELECT old_text FROM old WHERE old_namespace=0 and old_title='" . wfStrencode($wgTitle->getPrefixedDBkey())."' ORDER BY inverse_timestamp LIMIT 1";
+ $res=wfQuery($sql,$fname);
+ if( ($old=wfFetchObject($res)) && !$wpConfirm ) {
+ $skin=$wgUser->getSkin();
+ $wgOut->addHTML("<B>".wfMsg("historywarning"));
+ $wgOut->addHTML( $skin->historyLink() ."</B><P>");
+ }
+
+ $sql="SELECT cur_text FROM cur WHERE cur_namespace=0 and cur_title='" . wfStrencode($wgTitle->getPrefixedDBkey())."'";
+ $res=wfQuery($sql,$fname);
+ if( ($s=wfFetchObject($res))) {
+
+ # if this is a mini-text, we can paste part of it into the deletion reason
+
+ #if this is empty, an earlier revision may contain "useful" text
+ if($s->cur_text!="") {
+ $text=$s->cur_text;
+ } else {
+ if($old) {
+ $text=$old->old_text;
+ $blanked=1;
+ }
+
+ }
+
+ $length=strlen($text);
+
+ # this should not happen, since it is not possible to store an empty, new
+ # page. Let's insert a standard text in case it does, though
+ if($length==0 && !$wpReason) { $wpReason=wfmsg("exblank");}
+
+
+ if($length < 500 && !$wpReason) {
+
+ # comment field=255, let's grep the first 150 to have some user
+ # space left
+ $text=substr($text,0,150);
+ # let's strip out newlines and HTML tags
+ $text=preg_replace("/\"/","'",$text);
+ $text=preg_replace("/\</","<",$text);
+ $text=preg_replace("/\>/",">",$text);
+ $text=preg_replace("/[\n\r]/","",$text);
+ if(!$blanked) {
+ $wpReason=wfMsg("excontent"). " '".$text;
+ } else {
+ $wpReason=wfMsg("exbeforeblank") . " '".$text;
+ }
+ if($length>150) { $wpReason .= "..."; } # we've only pasted part of the text
+ $wpReason.="'";
+ }
+ }
+
}
# Likewise, deleting old images doesn't require confirmation
<form id=\"deleteconfirm\" method=\"post\" action=\"{$formaction}\">
<table border=0><tr><td align=right>
{$delcom}:</td><td align=left>
-<input type=text size=20 name=\"wpReason\" value=\"{$wpReason}\">
+<input type=text size=60 name=\"wpReason\" value=\"{$wpReason}\">
</td></tr><tr><td> </td></tr>
<tr><td align=right>
<input type=checkbox name=\"wpConfirm\" value='1'>
function rollback()
{
- global $wgUser, $wgTitle, $wgLang, $wgOut;
+ global $wgUser, $wgTitle, $wgLang, $wgOut, $from;
if ( ! $wgUser->isSysop() ) {
$wgOut->sysopRequired();
return;
}
-
+
# Replace all this user's current edits with the next one down
$tt = wfStrencode( $wgTitle->getDBKey() );
$n = $wgTitle->getNamespace();
# Get the last editor
- $sql = "SELECT cur_id,cur_user,cur_user_text FROM cur WHERE cur_title='{$tt}' AND cur_namespace={$n}";
+ $sql = "SELECT cur_id,cur_user,cur_user_text,cur_comment FROM cur WHERE cur_title='{$tt}' AND cur_namespace={$n}";
$res = wfQuery( $sql );
if( ($x = wfNumRows( $res )) != 1 ) {
# Something wrong
$uid = $s->cur_user;
$pid = $s->cur_id;
+ $from = str_replace( '_', ' ', wfCleanQueryVar( $from ) );
+ if( $from != $s->cur_user_text ) {
+ $wgOut->setPageTitle(wfmsg("rollbackfailed"));
+ $wgOut->addWikiText( wfMsg( "alreadyrolled",
+ htmlspecialchars( $wgTitle->getPrefixedText()),
+ htmlspecialchars( $from ),
+ htmlspecialchars( $s->cur_user_text ) ) );
+ if($s->cur_comment != "") {
+ $wgOut->addHTML(
+ wfMsg("editcomment",
+ htmlspecialchars( $s->cur_comment ) ) );
+ }
+ return;
+ }
+
# Get the last edit not by this guy
$sql = "SELECT old_text,old_user,old_user_text
FROM old USE INDEX (name_title_timestamp)
$res = wfQuery( $sql );
if( wfNumRows( $res ) != 1 ) {
# Something wrong
+ $wgOut->setPageTitle(wfMsg("rollbackfailed"));
$wgOut->addHTML( wfMsg( "cantrollback" ) );
return;
}
$this->loadFromFileCache();
exit;
} else {
- wfDebug( " tryFileCache() - starting buffer\n" );
+ wfDebug( " tryFileCache() - starting buffer\n" );
ob_start( array(&$this, 'saveToFileCache' ) );
}
} else {
function fileCacheName() {
global $wgTitle, $wgFileCacheDirectory, $wgLang;
- $hash = md5( $key = $wgTitle->getDbkey() );
- if( $wgTitle->getNamespace() )
- $key = $wgLang->getNsText( $wgTitle->getNamespace() ) . ":" . $key;
- $key = urlencode( $key );
- $hash1 = substr( $hash, 0, 1 );
- $hash2 = substr( $hash, 0, 2 );
- $fn = "{$wgFileCacheDirectory}/{$hash1}/{$hash2}/{$key}.html";
- wfDebug( " fileCacheName() - $fn\n" );
- return $fn;
+ if( !$this->mFileCache ) {
+ $hash = md5( $key = $wgTitle->getDbkey() );
+ if( $wgTitle->getNamespace() )
+ $key = $wgLang->getNsText( $wgTitle->getNamespace() ) . ":" . $key;
+ $key = str_replace( ".", "%2E", urlencode( $key ) );
+ $hash1 = substr( $hash, 0, 1 );
+ $hash2 = substr( $hash, 0, 2 );
+ $this->mFileCache = "{$wgFileCacheDirectory}/{$hash1}/{$hash2}/{$key}.html";
+ wfDebug( " fileCacheName() - {$this->mFileCache}\n" );
+ }
+ return $this->mFileCache;
}
function isFileCacheGood() {
global $wgUser, $wgCacheEpoch;
if(!file_exists( $fn = $this->fileCacheName() ) ) return false;
$cachetime = wfUnix2Timestamp( filemtime( $fn ) );
- $good = ( $this->mTouched <= $cachetime ) and
- $wgUser->validateCache( $cachetime ) and
+ $good = ( $this->mTouched <= $cachetime ) &&
($wgCacheEpoch <= $cachetime );
- wfDebug(" isFileCacheGood() - cachetime $cachetime, good $good\n");
+ wfDebug(" isFileCacheGood() - cachetime $cachetime, touched {$this->mTouched} epoch {$wgCacheEpoch}, good $good\n");
return $good;
}
function loadFromFileCache() {
+ global $wgUseGzip;
wfDebug(" loadFromFileCache()\n");
- readfile($this->fileCacheName());
+ $filename=$this->fileCacheName();
+ $filenamegz = "{$filename}.gz";
+ if( $wgUseGzip
+ && wfClientAcceptsGzip()
+ && file_exists( $filenamegz)
+ && ( filemtime( $filenamegz ) >= filemtime( $filename ) ) ) {
+ wfDebug(" sending gzip\n");
+ header( "Content-Encoding: gzip" );
+ header( "Vary: Accept-Encoding" );
+ $filename = $filenamegz;
+ }
+ readfile( $filename );
}
function saveToFileCache( $text ) {
- # FIXME: assumes directories are already laid out
+ global $wgUseGzip, $wgCompressByDefault;
+
wfDebug(" saveToFileCache()\n");
- $f = fopen( $this->fileCacheName(), "w" );
+ $filename=$this->fileCacheName();
+ $mydir2=substr($filename,0,strrpos($filename,"/")); # subdirectory level 2
+ $mydir1=substr($mydir2,0,strrpos($mydir2,"/")); # subdirectory level 1
+ if(!file_exists($mydir1)) { mkdir($mydir1,0777); } # create if necessary
+ if(!file_exists($mydir2)) { mkdir($mydir2,0777); }
+ $f = fopen( $filename, "w" );
if($f) {
+ $now = wfTimestampNow();
fwrite( $f, str_replace( "</html>",
- "<!-- Cached " . wfTimestampNow() . " -->\n</html>",
+ "<!-- Cached $now -->\n</html>",
$text ) );
fclose( $f );
+ if( $wgUseGzip and $wgCompressByDefault ) {
+ $start = microtime();
+ wfDebug(" saving gzip\n");
+ $gzout = gzencode( str_replace( "</html>",
+ "<!-- Cached/compressed $now -->\n</html>",
+ $text ) );
+ if( $gzout === false ) {
+ wfDebug(" failed to gzip compress, sending plaintext\n");
+ return $text;
+ }
+ if( $f = fopen( "{$filename}.gz", "w" ) ) {
+ fwrite( $f, $gzout );
+ fclose( $f );
+ $end = microtime();
+
+ list($usec1, $sec1) = explode(" ",$start);
+ list($usec2, $sec2) = explode(" ",$end);
+ $interval = ((float)$usec2 + (float)$sec2) -
+ ((float)$usec1 + (float)$sec1);
+ wfDebug(" saved gzip in $interval\n");
+ } else {
+ wfDebug(" failed to write gzip, still sending\n" );
+ }
+ header( "Content-Encoding: gzip" );
+ header( "Vary: Accept-Encoding" );
+ return $gzout;
+ }
}
return $text;
}