User:Rich Smith/iglooMain.js
Appearance
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump. This code will be executed when previewing this page. |
Documentation for this user script can be added at User:Rich Smith/iglooMain. |
// <nowiki>
/* ======================================================== *\
** igloo frontend manager - main
\* ======================================================== */
/*
fixes:
- fixed a bug that prevented igloo from intercepting and blocking some key presses in Google Chome.
- fixed a bug that caused text size issues in the vector skin - igloo will now more aggressively defend its CSS.
- fixed a bug where igloo would occasionally wait much longer than was necessary after loading data from iglooNet before proceeding.
- fixed a bug where page titles containing more than one apostrophe could not be clicked on in the recent changes feed.
- fixed an initial filter error where only one condition would be checked.
- fixed a bug where igloo did not display total sessions correctly.
changes:
- implemented the filter system.
- added settings for controlling filters.
- created the default filters for general use.
- make several improvements to the profanity highlighter.
behind the scenes:
- altered iglooNet to be able to stream filters.
- introduced the ID system.
*/
function iglooMain () {
this.internalCounter = 0;
this.iglooBase = new wa_document ();
this.launch = function ( details ) {
switch ( this.internalCounter ) {
default: case 0:
this.startload = new Date ();
this.canDebug = ( typeof console !== 'undefined' );
wa_window.prototype = new wa_document;
wa_element.prototype = new wa_document;
// step 1 of launching: build the loading interface.
var t = 'igloo - ' + iglooSettings.versionString;
var t2 = '';
for ( var i = 0; i < wgUserGroups.length; i ++ ) {
if ( wgUserGroups[i] == 'steward' ) { t2 += 'steward|'; }
else if ( wgUserGroups[i] == 'suppress' ) { t2 += 'suppresser|'; }
else if ( wgUserGroups[i] == 'checkuser' ) { t2 += 'checkuser|'; }
else if ( wgUserGroups[i] == 'bureaucrat' ) { t2 += 'bureaucrat|'; }
else if ( wgUserGroups[i] == 'sysop' ) { t2 += 'administrator|'; iglooSettings.mesysop = true; }
else if ( wgUserGroups[i] == 'rollbacker' ) { t2 += 'rollback|'; }
}
if ( t2 !== '' ) t += ' [wiki:' + t2.substr ( 0, t2.length - 1 ) + ']';
//t += ' [igloo:' + iglooSettings.iglooFlags + ']';
document.title = t;
iglooSettings.userGroup = t2.substr ( 0, t2.length - 1 );
this.iglooBase.wk_base.innerHTML= ''; // just destroy the mediawiki page content
this.iglooInterface = new wa_window ( this.iglooBase.wk_base );
this.iglooInterface.win_bg = '#ededff';
this.iglooInterface.win_maintfill = false;
this.iglooInterface.win_fill = true;
this.iglooInterface.applyAll ();
// step 2 of launching: add text.
this.iglooLoading = new wa_window ( this.iglooBase.wk_base );
this.iglooLoading.win_width = 210;
this.iglooLoading.win_height= 17;
this.iglooLoading.win_bd = '#bbbbff';
this.iglooLoading.win_bd_wd = 1;
this.iglooLoading.win_bg = '#fdfdff';
this.iglooLoading.win_content = '<div style="color: #555588; font-size: 14px; font-weight: bold; text-align: center; width: 100%;">Finalising load. Please wait...</div>';
this.iglooLoading.applyAll ();
this.iglooLoading.center ( 'both', true, new Array ( 0, -100 ) );
// step 3 of launching: verify session.
this.iglooSession = new iglooSecurity ();
if ( typeof this.iglooSession.shutdown != 'undefined' ) return false;
this.iglooSession.verifySession ( 'initial' );
// increment counter
this.internalCounter ++;
break;
case 1:
// step 4 of launching: the session is verified, tell the user.
this.iglooLoading.win_width = 330;
this.iglooLoading.win_content = '<div style="color: #555588; font-size: 14px; font-weight: bold; text-align: center; width: 100%;">Verified session. Requesting from iglooNet...</div>';
this.iglooLoading.applyAll ();
this.iglooLoading.center ( 'both', true, new Array ( 0, -100 ) );
// increment counter
this.internalCounter ++;
// run
this.iglooNet = new iglooNet ();
this.iglooNet.retrieve ( true );
break;
case 2:
// step 5 of lauching: load the user settings
this.iglooLoading.win_width = 180;
this.iglooLoading.win_content = '<div style="color: #555588; font-size: 14px; font-weight: bold; text-align: center; width: 100%;">Loading user settings...</div>';
this.iglooLoading.applyAll();
this.iglooLoading.center ( 'both', true, new Array ( 0, -100 ) );
// increment counter
this.internalCounter ++;
// run
this.iglooManageSettings = new iglooManageSettings ();
this.iglooManageSettings.retrieve ();
break;
case 3:
// adjust title now that the settings have loaded and we know the iglooNet permissions
document.title = document.title + ' [igloo:' + iglooSettings.iglooFlags + ']';
// display first run if relevant
// increment counter
this.internalCounter ++;
if ( iglooSettings.firstRun == true ) {
var url = iglooSettings.remoteHost + 'main.php?action=settings&do=set&session='+igloo.iglooSession.session+'&me='+encodeURIComponent(wgUserName)+'&setting=firstRun&value=false';
iglooImport( url, true, 'iglooFirstRun' );
wa ( ':api' ).get ( 'ig_firstrun', iglooSettings.localBase + 'config', 1 ).wait ( function () {
var firstruntext = wa ( ':api' ).results ['ig_firstrun']['query']['pages']['page']['revisions']['rev']['#text'], regTest = /firstrun:(.+?);;/i, o;
firstruntext = regTest.exec ( firstruntext );
firstruntext = firstruntext[1].replace ( '%CURRENTUSER%', wgUserName );
igloo.iglooLoading.win_width = 900;
igloo.iglooLoading.win_height = 400;
igloo.iglooLoading.win_content = firstruntext;
igloo.iglooLoading.applyAll ();
igloo.iglooLoading.center ( 'both', true );
} ).run ();
} else { this.launch (); }
break;
case 4:
// finalising launch: the session is verified, tell the user.
this.iglooLoading.win_width = 210;
this.iglooLoading.win_height= 17;
this.iglooLoading.win_content = '<div style="color: #555588; font-size: 14px; font-weight: bold; text-align: center; width: 100%;">Success. Building interface...</div>';
this.iglooLoading.applyAll ();
this.iglooLoading.center ( 'both', true, new Array ( 0, -100 ) );
// preload images
if ( iglooSettings.preloadInterface === true ) {
var images = new Array ( 'logo', 'back', 'back-grey', 'forward', 'forward-grey', 'hist', 'revert', 'settings', 'go' ), images2 = new Array ();
for ( var i = 0, l = images.length; i < l; i ++ ) {
images2 [i] = new Image ();
images2 [i].src = iglooSettings.remoteHost + 'images/igloo-' + images [i] + '.png';
}
}
// increment counter
this.internalCounter ++;
// run
setTimeout( "igloo.launch ();", 750 );
break;
case 5:
this.endload = new Date ();
// start the required program elements. log if possible.
this.iglooDiff = new iglooDiff ();
this.iglooDiff.start ();
if ( this.canDebug === true ) console.log ( 'igloo: started diff component' );
this.iglooStatus = new iglooStatus ();
this.iglooStatus.start ();
if ( this.canDebug === true ) console.log ( 'igloo: started status component' );
this.iglooControls = new iglooControls ();
this.iglooControls.start ();
if ( this.canDebug === true ) console.log ( 'igloo: started control component' );
this.iglooChanges = new iglooChanges ();
this.iglooChanges.start ();
if ( this.canDebug === true ) console.log ( 'igloo: started changes component' );
this.iglooPopup = new iglooPopup ();
this.iglooPopup.start ();
if ( this.canDebug === true ) console.log ( 'igloo: started popup component' );
this.iglooActions = new iglooActions ();
if ( this.canDebug === true ) console.log ( 'igloo: started actions component' );
this.iglooManageSettings.start ();
if ( this.canDebug === true ) console.log ( 'igloo: started settings component' );
// hide the loading element
this.iglooLoading.hide ();
if ( this.canDebug === true ) console.log ( 'igloo: completed load!' );
break;
}
}
this.shutdown = function ( reason, retry ) {
if (reason == null) { reason = ''; } else { reason = '<br />'+reason; }
if (retry == 'retry') { reason += '<br /><span style="cursor: pointer;" onmouseover="this.style.color=\'#333333\';" onmouseout="this.style.color=\'#555588\';" onclick="window.location = window.location.href;">retry</span> | <span style="cursor: pointer;" onmouseover="this.style.color=\'#333333\';" onmouseout="this.style.color=\'#555588\';" onclick="window.location = \''+iglooSettings.articleBase+iglooSettings.localBase+'Help\';">help</span>'; }
if (retry == 'tryagain') { reason += '<br /><span style="cursor: pointer;" onmouseover="this.style.color=\'#333333\';" onmouseout="this.style.color=\'#555588\';" onclick="window.location = \''+iglooSettings.articleBase+iglooSettings.localBase+'init\';">new session</span>'; }
if ( typeof this.iglooChanges != 'undefined' ) this.iglooChanges.destroy ();
if ( typeof this.iglooDiff != 'undefined' ) this.iglooDiff.destroy ();
if ( typeof this.iglooControls != 'undefined' ) this.iglooControls.destroy ();
if ( typeof this.iglooStatus != 'undefined' ) this.iglooStatus.destroy ();
if ( typeof this.iglooManageSettings != 'undefined' ) this.iglooManageSettings.hidedisplay ();
if ( typeof this.iglooSession != 'undefined' ) clearTimeout ( this.iglooSession.verificationTimer );
if ( typeof this.iglooNet != 'undefined' ) clearTimeout ( this.iglooNet.retrievalTimer );
this.iglooLoading.show ();
this.iglooLoading.win_height = 0;
this.iglooLoading.win_width = 350;
this.iglooLoading.win_content = '<div style="color: #555588; font-size: 14px; font-weight: bold; text-align: center; width: 100%;">igloo has closed'+reason+'</div>';
this.iglooLoading.applyAll ();
this.iglooLoading.center ( 'both' );
return true;
}
}
function iglooNet () {
// the iglooNet module retrieves wiki data from the igloo server to help fight vandalism
this.initial = true;
this.lastUpdate = 0;
this.iglooScores = [];
this.iglooCount = 0;
this.pingFails = 0;
this.iglooCommit = 0;
this.retrieve = function ( cacheBypass ) {
if ( typeof igloo.iglooStatus != 'undefined' ) igloo.iglooStatus.addStatus ( 'Requesting data from iglooNet...' );
this.internalCounter = 0;
if ( cacheBypass == true ) { var cache = '&cachebypass=true'; } else { var cache = ''; }
iglooImport ( iglooSettings.remoteHost + 'main.php?action=retrieve&pingfails=' + this.pingFails + '' + cache + '&me=' + encodeURIComponent ( wgUserName ) + '&session=' + igloo.iglooSession.session, true, 'iglooRetrieve' );
this.retrieveFailed = setTimeout ( function () { igloo.shutdown ( 'userlist retrieval failed - lost connection to iglooNet', 'retry' ); return false; }, iglooSettings.serverTimeout * 3 * 1000 );
//this.retrieveMain ();
}
this.retrieveMain = function ( status ) {
if ( status === 'ok' ) {
clearTimeout ( this.retrieveFailed );
igloo.iglooNet.mergeUpdates ( iglooNetScores );
return true;
} else {
igloo.shutdown ( 'session invalid or expired', 'tryagain' );
return false;
}
/*thisUpdate = false;
if ( typeof iglooScoresDone != 'undefined' ) if ( iglooScoresDone != 'unknown' ) if ( iglooScoresDone == 'ok' ) {
iglooScoresDone = 'unknown';
this.pingFails = 0;
igloo.iglooNet.mergeUpdates ( iglooNetScores );
return true;
} else {
igloo.shutdown ( 'session invalid or expired', 'tryagain' );
return false;
}
if ( this.internalCounter >= ( iglooSettings.serverTimeout * 3 ) ) {
this.pingFails ++;
if ( typeof igloo.iglooStatus !== 'undefined' ) igloo.iglooStatus.addStatus ( '<strong>Server connect failed (action: retrieve; pingfails ' + this.pingFails + ')</strong>' );
if ( this.pingFails >= iglooSettings.permitPingfails ) {
igloo.shutdown ( 'userlist retrieval failed - lost connection to iglooNet', 'retry' );
return false;
}
if ( igloo.canDebug === true ) console.log ( 'igloo: pingfail on retrieve (number '+this.pingFails+')' );
this.internalCounter = 0;
this.retrieveMain ();
return false;
} else {
this.internalCounter ++;
thisUpdate = this;
setTimeout ( "if ( thisUpdate ) { thisUpdate.retrieveMain (); }", 500 );
}*/
}
this.mergeUpdates = function ( newUpdates ) {
// the merge updates function takes the data that the iglooNet server has just sent and merges it into the central iglooScores array that is used
// to list the diffs to the user.
var j = 0;
for ( var i in newUpdates ) {
// newUpdates[i][0] = u [or] p
// newUpdates[i][1] = score [or] flag
// i = username [or] pagename
if ( ! this.iglooScores[i] ) {
// if we don't already have data on this item
this.iglooScores[i] = [];
this.iglooScores[i] = newUpdates[i];
} else {
// if we DO already have data on this item, update it
this.iglooScores[i].length = 0;
this.iglooScores[i] = [];
this.iglooScores[i] = newUpdates[i];
}
j ++;
this.iglooCount ++;
}
if ( this.initial == true ) {
igloo.launch ();
this.initial = false;
}
this.retrievalTimer = setTimeout ("igloo.iglooNet.retrieve();", 30 * 1000);
}
this.scoreObject = function ( object ) {
// generally, administrators/crats will be sent as a risk of 0 and rollbackers will be given 0.2.
// trusted users, who have made over 250 edits will be assigned a score of 0.4 - mysteriously meaning
// vandalism is likely to appear first, but there will always be an 'untrustworthy' edit to check.
// by default, other users and IPs will have 0.5 - the server assigns higher scores based on user
// actions
var score = [];
score.length= 0;
score[0] = false;
score[1] = '';
if ( (igloo.iglooNet.iglooScores[object]) && (igloo.iglooNet.iglooScores[object][0] == 'u') ) {
score[0] = igloo.iglooNet.iglooScores[object][1];
}
// if we have special data on this page, such as a whitelist of priority warning, append it here.
// pages that are whitelisted will be sent with a priority of 0, regardless of the user score
// pages that are flagged will gain a score of 0.7
// pages that are blacklisted will gain a score of 0.9
if ( ( igloo.iglooNet.iglooScores[object] ) && ( igloo.iglooNet.iglooScores[object][0] == 'p' ) ) {
switch ( igloo.iglooNet.iglooScores[object][1] ) {
case 'w':
score[0] = 0;
score[1] = 'w';
break;
case 'f':
score[0] = 0.6;
score[1] = 'f';
break;
case 'b':
score[0] = 0.9;
score[1] = 'b';
break;
}
}
return score;
}
this.colourScore = function ( score, defaultCol ) {
defaultCol = typeof ( defaultCol ) != 'undefined' ? defaultCol : '#ffffff';
if ( score === false ) return defaultCol;
if (iglooSettings.enableFeedColour == false) {
var col = defaultCol;
} else if ( score >= 0.8 ) {
var col = iglooSettings.flagColours[0];
} else if ( score >= 0.6 ) {
var col = iglooSettings.flagColours[1];
} else if ( score >= 0.4 ) {
var col = iglooSettings.flagColours[2];
} else if ( score >= 0.2 ) {
var col = iglooSettings.flagColours[3];
} else if ( score >= 0 ) {
var col = iglooSettings.flagColours[4];
} else {
var col = defaultCol;
}
return col;
}
this.genCode = function ( len ) {
var a = new Array ( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ), s = '', x = a.length;
for ( var i = 0; i < len; i ++ ) {
var r = Math.floor ( Math.random () * x );
s += a[r];
}
return s;
}
this.investigate = function ( user ) {
if ( ( typeof user !== 'string' ) || ( iglooSettings.iglooFlags.indexOf ( 't' ) === -1 ) || ( iglooSettings.commitToIgNet === false ) ) return false;
var score = this.scoreObject ( user );
if ( ( user.match ( /^[0-9]+\.[0-9]+\.[0-9]+\.?[0-9]*$/i ) === null ) && ( this.iglooCommit >= iglooSettings.commitWhen ) && ( ( score[0] === false ) || ( iglooSettings.recheck === true ) ) ) {
this.iglooCommit = 0; // reset counter
var url = iglooSettings.remoteHost + 'main.php?action=investigate&session=' + igloo.iglooSession.session + '&me=' + encodeURIComponent ( wgUserName ) +'&user=' + user + '';
iglooImport ( url, true, 'iglooInvestigate' );
} else { this.iglooCommit ++; }
}
}
function iglooFilter ( filter ) {
// generate filter variables
this.conditions = [];
this.events = [];
this.activeChange = false;
this.blockFilters = false; // whether to block further filter execution after this one
this.parseFilter = function ( code ) {
var t = t2 = t3 = t4 = [];
// split into statements
t = code.split ( "\n" );
if ( t.length === 0 ) return false; // if no statements
// for each statement, extract the commands
for ( var i = 0, l = t.length; i < l; i ++ ) {
t2 [i] = [];
t2 [i] = t [i].split ( ' ' );
// switch the type of statement (i.e. the first command)
switch ( t2 [i] [0] ) {
case 'if': case 'ifany':
if ( this.parseCondition ( t2 [i] ) === false ) return false;
break;
case 'set': case 'hide': case 'mark': case'blockfilters':
if ( this.parseEvent ( t2 [i] ) === false ) return false;
break;
case '': case '//': //comments
break;
default:
// if we cannot recognise the command, die.
return false;
break;
}
}
}
this.parseCondition = function ( array ) {
if ( array.length < 4 ) return false;
// insert this condition
var useId = this.conditions.length;
this.conditions [useId] = {};
// if vs ifany
this.conditions [useId] ['type'] = array [0];
if ( array [0] === 'if' ) {
switch ( array [1] ) { default: return false; break; case 'summary': case 'oldsize': case 'newsize': case 'changesize': case 'tags': case 'title': case 'user': case 'score': break; }
this.conditions [useId] ['target'] = array [1];
if ( this.conditions [useId] ['negate'] = ( ( array [2] === 'NOT' ) || ( array [2] === '!' ) ) ) { var s = 3; } else { var s = 2; }
switch ( array [s] ) { default: return false; break; case 'regexmatch': case 'contains': case '==': case '<': case '>': break; }
// op limits
if ( ( array [1] === 'tags' ) && ( ( array [s] !== 'regexmatch' ) && ( array [s] !== 'contains' ) && ( array [s] !== '==' ) ) ) return false;
if ( ( ( array [s] === '<' ) || ( array [s] === '>' ) ) && ( ( array [1] !== 'oldsize' ) && ( array [1] !== 'newsize' ) && ( array [1] !== 'changesize' ) && ( array [1] !== 'score' ) ) ) return false;
// fin
this.conditions [useId] ['op'] = array [s];
this.conditions [useId] ['value'] = '';
for ( var i = s+1, l = array.length; i < l; i ++ ) {
this.conditions [useId] ['value'] += array [i] + ' ';
}
this.conditions [useId] ['value'] = this.conditions [useId] ['value'].substr ( 0, this.conditions [useId] ['value'].length - 1 );
}
return true;
}
this.parseEvent = function ( array ) {
var t = {};
// the command
t ['type'] = array [0];
switch ( array [0] ) {
default: return false; break;
case 'set': // set [score/id] [absolute/relative] value
// checks
if ( ( array [1] !== 'score' ) && ( array [1] !== 'id' ) && ( array [1] !== 'comment' ) ) return false; // unrecognised
if ( ( array [1] !== 'comment' ) && ( array [2] !== 'absolute' ) && ( array [2] !== 'relative' ) ) return false; // unrecognised
if ( array [1] === 'score' ) {
if ( isNaN ( array [3] = parseFloat ( array [3] ) ) === true ) return false; // not a number
array [3] = Math.round ( array [3] * 10 ) / 10;
t ['action'] = array [2];
t ['value'] = array [3];
} else if ( array [1] === 'id' ) {
if ( isNaN ( array [3] = parseInt ( array [3], 10 ) ) === true ) return false; // not a number
if ( ( array [3] > 99 ) || ( array [3] < 0 ) ) return false; // out of range
t ['action'] = array [2];
t ['value'] = array [3];
} else {
t ['value'] = '';
for ( var i = 2, l = array.length; i < l; i ++ ) {
t ['value'] += array [i] + ' ';
}
t ['value'] = t ['value'].substr ( 0, t ['value'].length - 1 );
}
// build
t ['target'] = array [1]; // what part of the change data do we want to edit?
break;
}
// insert this event
var useId = this.events.length;
this.events [useId] = t;
return true;
}
this.applyFilter = function ( change ) {
this.activeChange = change;
if ( this.checkConditions () === true ) { this.executeActions (); return this.activeChange; } else { return change; }
}
this.checkConditions = function () {
for ( var i = 0, l = this.conditions.length; i < l; i ++ ) {
var m = this.conditions [i];
switch ( m ['type'] ) {
case 'if':
// convert targets to id codes
var target;
switch ( m['target'] ) {
case 'summary': target = 9; break;
case 'changesize': target = 8; break;
case 'oldsize': target = 6; break;
case 'newsize': target = 7; break;
case 'tags': target = 10; break;
case 'title': target = 0; break;
case 'user': target = 1; break;
case 'score': target = 4; break;
default: return false; break;
}
var meTrue = m['negate'] ? false : true; var meFalse = ! meTrue, r = false;
switch ( m['op'] ) {
case 'regexmatch':
var extractReg = /^\/(.+?)\/([igm]*)$/ig;
var regMatch = extractReg.exec ( this.dataReplace ( m['value'] ) );
var regTest = new RegExp ( regMatch [1], regMatch [2] );
extractReg.lastIndex = 0;
if ( this.activeChange [target].match ( regTest ) !== null ) { r = meTrue; } else { r = meFalse; }
break;
case 'contains':
if ( this.activeChange [target].indexOf ( this.dataReplace ( m['value'] ) ) > -1 ) { r = meTrue; } else { r = meFalse; }
break;
case '==':
if ( this.activeChange [target] == m['value'] ) { r = meTrue; } else { r = meFalse; }
break;
case '<':
if ( this.activeChange [target] < parseFloat ( m['value'] ) ) { r = meTrue; } else { r = meFalse; }
break;
case '>':
if ( this.activeChange [target] > parseFloat ( m['value'] ) ) { r = meTrue; } else { r = meFalse; }
break;
default: r = false; break;
}
break;
}
if ( r === false ) return false;
}
return true;
}
this.executeActions = function () {
for ( var i = 0, l = this.events.length; i < l; i ++ ) {
var m = this.events [i];
switch ( m ['type'] ) {
case 'set':
if ( m['target'] === 'comment' ) {
if ( typeof this.activeChange [11] !== 'string' ) this.activeChange [11] = '';
this.activeChange [11] += ' ' + this.dataReplace ( m['value'] );
break;
}
var existing = this.activeChange [4]; var scoreStr = existing.toString ( 10 );
if ( scoreStr.indexOf ( '.' ) === -1 ) scoreStr += '.0';
var score = scoreStr.substr ( 0, scoreStr.indexOf ( '.' ) + 2 );
var id = scoreStr.substr ( scoreStr.indexOf ( '.' ) + 2 );
if ( id == '' ) id = '00';
if ( id.length === 1 ) id += '0';
if ( m['target'] === 'score' ) {
var newScore = parseFloat ( score );
if ( m['action'] === 'relative' ) {
newScore += parseFloat ( m['value'] );
newScore = Math.round ( newScore * 10 ) / 10;
newId = id;
} else {
newScore = parseFloat ( m['value'] );
newScore = Math.round ( newScore * 10 ) / 10;
newId = id;
}
} else {
var newId = parseInt ( id, 10 );
if ( m['action'] === 'relative' ) {
newId += parseInt ( m['value'], 10 );
if ( newId > 99 ) newId = 99;
if ( newId < 0 ) newId = 0;
newId = newId.toString ( 10 );
newScore = Math.round ( parseFloat ( score ) * 10 ) / 10;
} else {
newId = parseInt ( m['value'], 10 );
newId = newId.toString ( 10 );
newScore = Math.round ( parseFloat ( score ) * 10 ) / 10;
}
}
if ( ( parseInt ( newId, 10 ) < 10 ) && ( newId.substr ( 0, 1 ) !== '0' ) ) newId = '0' + newId;
var final = parseFloat ( newScore + '' + newId );
this.activeChange [4] = final;
break;
case 'blockfilters':
this.blockFilters = true;
break;
}
}
}
this.dataReplace = function ( string ) {
var regTest = /%DATA([0-9A-Z]+)%/g, c = this.activeChange;
regTest.lastIndex = 0;
var o = string.replace ( regTest, function ( m, m2 ) {
if ( m2 === 'ME' ) {
return wgUserName;
} else {
if ( c[m2] === null ) return false;
return c[m2].toString();
}
} );
return o;
}
// on create
this.parseSuccess = this.parseFilter ( filter ); // return parse success
return true;
}
function iglooSecurity () {
this.userActivity = true;
this.pingFails = 0;
if ( (window.location.href.indexOf('&sessionkey=') == -1) || (window.location.href.indexOf('::::') == -1) ) { igloo.shutdown('invalid session provided', 'tryagain'); this.shutdown = true; return false; }
this.session = window.location.href.substr(window.location.href.indexOf('&sessionkey=') + 12);
this.session = this.session.substr(0, this.session.length - 4);
this.verifySession = function ( type ) {
this.internalCounter = 0;
if ( this.userActivity == true ) { var alive = '&keep-alive=true'; } else { var alive = '&keep-alive=false'; }
this.userActivity = false;
iglooImport( iglooSettings.remoteHost + 'main.php?action=verify&pingfails=' + this.pingFails + '&user=' + encodeURIComponent ( wgUserName ) + '&verify=' + this.session + alive, true, 'iglooVerify' );
this.checkVerification ( type );
}
this.checkVerification = function ( type ) {
if ( typeof iglooSessionVerified != 'undefined' ) if ( iglooSessionVerified != 'unknown' ) if ( iglooSessionVerified == 'ok' ) {
this.pingFails = 0;
iglooSessionVerified = 'unknown';
this.verificationTimer = setTimeout("igloo.iglooSession.verifySession();", 45 * 1000);
if ( type == 'initial' ) {
igloo.launch();
}
return true;
} else {
igloo.shutdown('session invalid or expired', 'tryagain');
return false;
}
if ( this.internalCounter >= iglooSettings.serverTimeout * 2 ) {
this.pingFails ++;
if ( type != 'initial' ) igloo.iglooStatus.addStatus ( '<strong>Server connect failed (action: verify; pingfails ' + this.pingFails + ')</strong>' );
if ( this.pingFails >= iglooSettings.permitPingfails ) {
igloo.shutdown ( 'verification failed - lost connection to iglooNet', 'retry' );
}
return false;
} else {
this.internalCounter ++;
setTimeout("igloo.iglooSession.checkVerification('"+type+"');", 1000);
}
}
}
function iglooManageSettings () {
// the iglooManageSettings module retrieves settings from the igloo server, and replaces the defaults where applicable.
this.settingsEnabled = true;
this.retrieve = function () {
this.internalCounter = 0;
iglooImport ( iglooSettings.remoteHost + 'main.php?action=settings&me=' + encodeURIComponent(wgUserName) + '&do=get&session=' + igloo.iglooSession.session, true, 'iglooNetSettings' );
this.retrieveMain ();
}
this.retrieveMain = function () {
thisSetting = false;
if ( typeof iglooNetSettingsDone != 'undefined' ) if ( iglooNetSettingsDone != 'unknown' ) if ( iglooNetSettingsDone == 'ok' ) {
// success
this.overwritelocal ();
this.managefilters ();
// continue launch
igloo.launch ();
return true;
} else {
igloo.shutdown( 'session invalid or expired', 'tryagain' );
return false;
}
if ( this.internalCounter >= ( iglooSettings.serverTimeout * 2 ) ) {
igloo.shutdown( 'settings failed - lost connection to iglooNet', 'retry' );
return false;
} else {
this.internalCounter ++;
thisSetting = this;
setTimeout( "if ( thisSetting ) { thisSetting.retrieveMain (); }", 500 );
}
}
this.overwritelocal = function () {
for ( i in iglooNetSettings ) {
if ( iglooSettings [i] !== undefined ) {
iglooSettings [i] = iglooNetSettings [i];
}
}
return true;
}
this.managefilters = function () {
for ( var i = 0, l = iglooSettings.filterList.length; i < l; i ++ ) {
iglooSettings.filterList[i][4] = new iglooFilter ( iglooSettings.filterList[i][3] );
if ( iglooSettings.filterList[i][4].parseSuccess === false ) { alert ( 'Warning: parse error; igloo filter failed to parse, global filter ID ' + iglooSettings.filterList[i][0] ); }
}
return true;
}
this.set = function ( setting, value ) {
if ( this.settingsEnabled === true ) {
iglooImport ( iglooSettings.remoteHost + 'main.php?action=settings&me=' + encodeURIComponent ( wgUserName ) + '&do=set&setting=' + encodeURIComponent ( setting ) + '&value=' + encodeURIComponent ( value ) + '&session=' + igloo.iglooSession.session, true, 'iglooNetDoSet' );
this.settingsEnabled = false;
return true;
} else {
alert ( 'Could not alter setting - previous requests are still being processed. Please wait, then try again.' );
return false;
}
}
this.freeSettings = function () {
this.settingsEnabled = true;
}
this.start = function () {
this.mainContent = '<div id="igloo-settings-tabs" style="width: 790px; height: 14px; padding-left: 10px; "></div><div id="igloo-settings-content" style="width: 800px; height: 385px; border-top: 1px solid #000;"></div>';
if ( igloo.canDebug === true ) console.log ( 'igloo: prepped settings main' );
}
this.showdisplay = function () {
// generate interface
igloo.iglooPopup.show ( this.mainContent );
// add tabs
this.addtab ( 'info', 'user info' );
this.addtab ( 'general', 'general' );
this.addtab ( 'interface', 'interface' );
//this.addtab ( 'actions', 'actions' );
this.addtab ( 'filters', 'filters' );
if ( iglooSettings.mesysop ) this.addtab ( 'admin', 'admin' );
this.addtab ( 'close', 'close' );
// default tab
this.switchtab ( 'info' );
// dynamic key blocking
iglooSettings.dynamicBlockKeys = 'settings';
return true;
}
this.hidedisplay = function () {
igloo.iglooPopup.hide ();
iglooSettings.dynamicBlockKeys = 'default';
return true;
}
this.addtab = function ( tabid, tabtext ) {
if ( ( ! tabid ) || ( ! tabtext ) ) return false;
var tabscont = document.getElementById ( 'igloo-settings-tabs' );
tabscont.innerHTML += '<div id="igloo-settings-tab-' + tabid + '" style="float: left; position: relative; top: 1px; font-size: 10px; height: 12px; width: 50px; border: 1px solid #000; text-align: center; cursor: pointer; margin-right: 10px;" onclick="igloo.iglooManageSettings.switchtab (\'' + tabid + '\');"> ' + tabtext + '</div>';
return tabscont;
}
this.genFilterText = function () {
var filterText = '';
for ( var i = 0, l = iglooSettings.filterList.length; i < l; i ++ ) {
var t = iglooSettings.filterList [i], optionsString = 'this filter has a problem';
var disp = t[3].replace ( /\\/g, '\\\\' );
disp = disp.replace ( /\n/g, '\\n' );
disp = disp.replace ( /\'/g, '\\\'' );
//this.disEnString = new Array ();
//this.disEnString[i] = ( t[1] === true ) ? 'iglooImport ( \''+iglooSettings.remoteHost+'main.php?action=settings&me=' + encodeURIComponent ( wgUserName ) + '&do=set&setting=disablefilter&value='+t[0]+'\', true, \'iglooFilter\' ); iglooSettings.filterList['+i+'][1] = false;' : 'iglooImport ( \''+iglooSettings.remoteHost+'main.php?action=settings&me=' + encodeURIComponent ( wgUserName ) + '&do=set&setting=enablefilter&value='+t[0]+'\', true, \'iglooFilter\' ); iglooSettings.filterList['+i+'][1] = true;';
var disEnString = ( t[1] === true ) ? 'Disable' : 'Enable';
//disEnString = disEnString.replace ( /'/g, '\\\'' );
if ( t[2] !== 'default' ) {
var saveString = '';
optionsString = '<span style="cursor: pointer;" onclick="var d = document.getElementById (\'igloo-filter-details\'); d.innerHTML = \'<span id=\\\'igloo-filter-current-id\\\' style=\\\'display: none;\\\'>'+i+':'+t[0]+'</span><textarea id=\\\'igloo-filter-text\\\' style=\\\'width: 540px; height: 290px;\\\'>'+disp+'</textarea><br /><div><input disabled id=\\\'igloo-save-filter\\\' type=\\\'button\\\' value=\\\'Save filter changes\\\' style=\\\'width: 260px; margin-left: 5px;\\\' /><input id=\\\'igloo-toggle-filter-disable\\\' type=\\\'button\\\' value=\\\'' + disEnString + ' this filter\\\' style=\\\'width: 260px; margin-left: 10px;\\\' /></div>\'; igloo.iglooManageSettings.attachfilterbuttons ( '+i+' );" onmouseover="this.style.textDecoration=\'underline\';" onmouseout="this.style.textDecoration=\'none\';">edit</span>';
optionsString += ' | <span style="cursor: pointer;" onclick="iglooImport ( \'' + iglooSettings.remoteHost + 'main.php?action=settings&me=' + encodeURIComponent ( wgUserName ) + '&do=set&setting=deletefilter&value=' + t[0] + '&session=' + igloo.iglooSession.session + '\', true, \'iglooFilter\' ); iglooSettings.filterList.splice ( ' + i + ', 1 ); igloo.iglooManageSettings.switchtab ( \'filters\' );" onmouseover="this.style.textDecoration=\'underline\';" onmouseout="this.style.textDecoration=\'none\';">delete</span>';
} else {
optionsString = '<span style="cursor: pointer;" onclick="var d = document.getElementById (\'igloo-filter-details\'); d.innerHTML = \'<span id=\\\'igloo-filter-current-id\\\' style=\\\'display: none;\\\'>'+i+':'+t[0]+'</span><textarea disabled style=\\\'width: 540px; height: 290px;\\\'>'+disp+'</textarea><br /><div><input type=\\\'button\\\' disabled value=\\\'You cannot edit this filter\\\' style=\\\'width: 260px; margin-left: 5px;\\\' /><input id=\\\'igloo-toggle-filter-disable\\\' type=\\\'button\\\' value=\\\'' + disEnString + ' this filter\\\' style=\\\'width: 260px; margin-left: 10px;\\\' /></div>\'; igloo.iglooManageSettings.attachfilterbuttons ( '+i+' );" onmouseover="this.style.textDecoration=\'underline\';" onmouseout="this.style.textDecoration=\'none\';">view filter (cannot edit)</span>';
}
var col = ( t[1] === true ) ? '' : 'background-color: #ffbbbb;';
filterText += '<li style="'+col+' margin-left: -4px; list-style-type: none; list-style-image: none; marker-offset: 0px;">';
filterText += '- filter ' + t[0] + ' (' + optionsString + ')';
filterText += '</li>';
}
if ( i === 0 ) filterText = '<li style="margin-left: 0px; padding-left: 4px; list-style-type: none; list-style-image: none; marker-offset: 0px;">no filters</li>';
return filterText;
}
this.togglefilterenabled = function ( to ) {
var t = document.getElementById ( 'igloo-toggle-filter-disable' ), id = document.getElementById ( 'igloo-filter-current-id' ).innerHTML.split ( ':' );
id = parseInt ( id[0], 10 );
if ( to === 'enabled' ) {
iglooImport ( iglooSettings.remoteHost+'main.php?action=settings&me=' + encodeURIComponent ( wgUserName ) + '&do=set&setting=enablefilter&value=' + iglooSettings.filterList[id][0] + '&session=' + igloo.iglooSession.session, true, 'iglooFilter' );
iglooSettings.filterList[id][1] = true;
t.value = 'Disable this filter';
t.onclick = function () { igloo.iglooManageSettings.togglefilterenabled ( 'disabled' ); document.getElementById ( 'igloo-filter-list' ).innerHTML = igloo.iglooManageSettings.genFilterText (); }
} else {
iglooImport ( iglooSettings.remoteHost+'main.php?action=settings&me=' + encodeURIComponent ( wgUserName ) + '&do=set&setting=disablefilter&value=' + iglooSettings.filterList[id][0] + '&session=' + igloo.iglooSession.session, true, 'iglooFilter' );
iglooSettings.filterList[id][1] = false;
t.value = 'Enable this filter';
t.onclick = function () { igloo.iglooManageSettings.togglefilterenabled ( 'enabled' ); document.getElementById ( 'igloo-filter-list' ).innerHTML = igloo.iglooManageSettings.genFilterText (); }
}
return true;
}
this.attachfilterbuttons = function ( id ) {
if ( id !== 'new' ) {
var t = document.getElementById ( 'igloo-toggle-filter-disable' );
if ( iglooSettings.filterList[id][1] === true ) {
// enabled, so disable
t.onclick = function () { igloo.iglooManageSettings.togglefilterenabled ( 'disabled' ); document.getElementById ( 'igloo-filter-list' ).innerHTML = igloo.iglooManageSettings.genFilterText (); }
} else {
// disabled, so enable
t.onclick = function () { igloo.iglooManageSettings.togglefilterenabled ( 'enabled' ); document.getElementById ( 'igloo-filter-list' ).innerHTML = igloo.iglooManageSettings.genFilterText (); }
}
}
if ( document.getElementById ( 'igloo-filter-text' ) !== null ) {
t = document.getElementById ( 'igloo-filter-text' );
t.onkeyup = function () {
var t2 = new iglooFilter ( document.getElementById ( 'igloo-filter-text' ).value );
if ( t2.parseSuccess === false ) {
var t3 = document.getElementById ( 'igloo-save-filter' );
t3.disabled = true;
t3.value = 'Parse error: filter is invalid';
} else {
var t3 = document.getElementById ( 'igloo-save-filter' );
t3.disabled = false;
if ( document.getElementById ( 'igloo-filter-current-id' ).innerHTML.indexOf ( 'new' ) > -1 ) {
t3.value = 'Create new filter';
} else {
t3.value = 'Save filter changes';
}
}
}
}
if ( document.getElementById ( 'igloo-save-filter' ) !== null ) {
t = document.getElementById ( 'igloo-save-filter' );
t.onclick = function () {
this.disabled = true;
var id = document.getElementById ( 'igloo-filter-current-id' ).innerHTML.split ( ':' );
var data = document.getElementById ( 'igloo-filter-text' ).value;
// if new
if ( id[1] === 'new' ) {
var t = [], n = true;
t [0] = igloo.iglooNet.genCode ( 5 );
t [1] = true;
t [2] = wgUserName;
t [3] = data;
t [4] = new iglooFilter ( t [3] );
id [1] = t [0];
iglooSettings.filterList.push ( t );
} else {
var t = iglooSettings.filterList [ parseInt ( id[0], 10 ) ], n = false;
t [3] = data;
t [4] = new iglooFilter ( t [3] );
iglooSettings.filterList [ parseInt ( id[0], 10 ) ] = t;
}
iglooImport ( iglooSettings.remoteHost+'main.php?action=settings&me=' + encodeURIComponent ( wgUserName ) + '&do=set&setting=editfilter&id=' + id [1] + '&value=' + encodeURIComponent ( data ) + '&session=' + igloo.iglooSession.session, true, 'iglooFilter' );
if ( n === true ) { igloo.iglooManageSettings.switchtab ( 'filters' ); } else { document.getElementById ( 'igloo-filter-list' ).innerHTML = igloo.iglooManageSettings.genFilterText (); }
}
}
}
this.switchtab = function ( tabid ) {
if ( ! tabid ) { throw 'igloo: unexpected settings call, tab is missing'; return false; }
var tabcont = document.getElementById ( 'igloo-settings-content' ), v;
switch ( tabid ) {
case 'info':
tabcont.innerHTML = ''; // blank
tabcont.innerHTML += '<div style="padding: 10px;">Welcome to the igloo settings panel. From here, you can update your igloo settings - there is no need to save your changes or restart igloo as any alterations will take place immediately. igloo currently has the following data regarding your account:<br /><br />- username: ' + wgUserName + '<br />- recognised usergroup: ' + iglooSettings.userGroup + '<br />- igloo user flags: ' + iglooSettings.iglooFlags + '<br />- igloo trust status: N/A<br />- total sessions: ' + iglooSettings.totalSessions + '<br />- last connected from: ' + iglooSettings.lastConnectIp + '<br />- last connected: ' + iglooSettings.lastConnectTime + '<br /></div>';
break;
case 'general':
tabcont.innerHTML = ''; // blank
var cont = '';
cont += '<div style="padding: 10px;">Change general igloo settings here.<br /><table style="background-color: #ccccff; border: none; margin-top: 5px; margin-left: 15px; width: 550px;">'
v = iglooSettings.updateTime;
cont += '<tr style="margin-left: 15px;"><td>Update time</td><td><input onchange="if ( isNaN ( parseInt ( this.value ) ) === true ) this.value = iglooSettings.updateTime;" onblur="if ( igloo.iglooManageSettings.set ( \'updateTime\', this.value ) === false ) { this.value = iglooSettings.updateTime; } else { iglooSettings.updateTime = parseInt ( this.value ); }" type="text" value="'+v+'" /></td></tr>';
v = iglooSettings.updateQuantity;
cont += '<tr style="margin-left: 15px;"><td>Update quantity</td><td><input onchange="if ( isNaN ( parseInt ( this.value ) ) === true ) this.value = iglooSettings.updateQuantity;" onblur="if ( igloo.iglooManageSettings.set ( \'updateQuantity\', this.value ) === false ) { this.value = iglooSettings.updateQuantity; } else { iglooSettings.updateQuantity = parseInt ( this.value ); }" type="text" value="'+v+'" /></td></tr>';
v = iglooSettings.updateLimit;
cont += '<tr style="margin-left: 15px;"><td>Update list limit</td><td><input onchange="if ( isNaN ( parseInt ( this.value ) ) === true ) this.value = iglooSettings.updateLimit;" onblur="if ( igloo.iglooManageSettings.set ( \'updateLimit\', this.value ) === false ) { this.value = iglooSettings.updateLimit; } else { iglooSettings.updateLimit = parseInt ( this.value ); }" type="text" value="'+v+'" /></td></tr>';
v = iglooSettings.promptRevertSelf ? 'checked' : '';
cont += '<tr style="margin-left: 15px;"><td>Prompt on self revert</td><td><input onchange="if ( igloo.iglooManageSettings.set ( \'promptRevertSelf\', this.checked ) === false ) this.checked = ! this.checked;" type="checkbox" '+v+' /></td></tr>';
v = iglooSettings.profFilter ? 'checked' : '';
cont += '<tr style="margin-left: 15px;"><td>Enable profanity highlighting</td><td><input onchange="if ( igloo.iglooManageSettings.set ( \'profFilter\', this.checked ) === false ) this.checked = ! this.checked;" type="checkbox" '+v+' /></td></tr>';
cont += '</table></div>';
tabcont.innerHTML = cont;
break;
case 'interface':
tabcont.innerHTML = ''; // blank
var cont = '';
cont += '<div style="padding: 10px;">Change igloo interface settings here.<br /><table style="background-color: #ccccff; border: none; margin-top: 5px; margin-left: 15px; width: 550px;">'
v = iglooSettings.preloadInterface ? 'checked' : '';
cont += '<tr style="margin-left: 15px;"><td>Preload interface elements</td><td><input onchange="if ( igloo.iglooManageSettings.set ( \'preloadInterface\', this.checked ) === false ) this.checked = ! this.checked;" type="checkbox" '+v+' /></td></tr>';
v = iglooSettings.diffFontSize;
cont += '<tr style="margin-left: 15px;"><td>Diff font size (px)</td><td><input onchange="if ( parseInt ( this.value ) == NaN ) this.value = iglooSettings.diffFontSize;" onblur="if ( igloo.iglooManageSettings.set ( \'diffFontSize\', this.value ) === false ) { this.value = iglooSettings.diffFontSize; } else { iglooSettings.diffFontSize = parseInt ( this.value ); }" type="text" value="'+v+'" /></td></tr>';
v = iglooSettings.enableFeedColour ? 'checked' : '';
cont += '<tr style="margin-left: 15px;"><td>Enable feed colouring</td><td><input onchange="if ( igloo.iglooManageSettings.set ( \'enableFeedColour\', this.checked ) === false ) { this.checked = ! this.checked; } else { iglooSettings.enableFeedColour = this.checked; }" type="checkbox" '+v+' /></td></tr>';
v = iglooSettings.histWinTimeout;
cont += '<tr style="margin-left: 15px;"><td>History window timeout</td><td><input onblur="if ( igloo.iglooManageSettings.set ( \'histWinTimeout\', this.value ) === false ) { this.value = iglooSettings.histWinTimeout; } else { iglooSettings.histWinTimeout = parseFloat ( this.value ); }" type="text" value="'+v+'" /></td></tr>';
cont += '</table></div>';
tabcont.innerHTML = cont;
break;
case 'admin':
tabcont.innerHTML = ''; // blank
var cont = '';
cont += '<div style="padding: 10px;">This is the igloo admin settings panel - here, you can change settings related to performing administrative actions using igloo.<br /><table style="background-color: #ccccff; border: none; margin-top: 5px; margin-left: 15px; width: 550px;">'
v = iglooSettings.preloadInterface ? 'checked' : '';
cont += '<tr style="margin-left: 15px;"><td>Action after final warning</td><td><select onchange="if ( this.value == \'select\' ) return false; igloo.iglooManageSettings.set ( \'blockAction\', this.value );"><option value="select">Select...</option><option value="auto">Use autoblock</option><option value="standard">Choose block options</option><option value="report">Report to AIV</option></select></td></tr>';
//v = iglooSettings.enableFeedColour ? 'checked' : '';
//cont += '<tr style="margin-left: 15px;"><td>Enable feed colouring</td><td><input onchange="if ( igloo.iglooManageSettings.set ( \'enableFeedColour\', this.checked ) === false ) { this.checked = ! this.checked; } else { iglooSettings.enableFeedColour = this.checked; }" type="checkbox" '+v+' /></td></tr>';
//v = iglooSettings.histWinTimeout;
//cont += '<tr style="margin-left: 15px;"><td>History window timeout</td><td><input onblur="if ( igloo.iglooManageSettings.set ( \'histWinTimeout\', this.value ) === false ) { this.value = iglooSettings.histWinTimeout; } else { iglooSettings.histWinTimeout = parseFloat ( this.value ); }" type="text" value="'+v+'" /></td></tr>';
cont += '</table></div>';
tabcont.innerHTML = cont;
break;
case 'filters':
// build filterText
var filterText = this.genFilterText ();
// build display
var cont = ''; // blank
cont += '<div style="padding: 10px;">To create a new filter, click the \'new filter\' button. Be aware that poorly designed filters can have an adverse effect on performance. You cannot edit the default filters.<br /><table style="background-color: #ccccff; border: 1px solid #000; margin-top: 5px; margin-left: 15px; width: 750px;">'
cont += '<tr><td valign="top" style="width: 150px; height: 330px; border-right: 1px solid #000;">';
cont += '<input type="button" style="width: 200px;" value="New Filter" onclick="var d = document.getElementById (\'igloo-filter-details\'); d.innerHTML = \'<span id=\\\'igloo-filter-current-id\\\' style=\\\'display: none;\\\'>0:new</span><textarea id=\\\'igloo-filter-text\\\' style=\\\'width: 540px; height: 290px;\\\'>// Type filter details below.</textarea><br /><div><input disabled id=\\\'igloo-save-filter\\\' type=\\\'button\\\' value=\\\'Create new filter\\\' style=\\\'width: 530px; margin-left: 5px;\\\' /></div>\'; igloo.iglooManageSettings.attachfilterbuttons ( \'new\' );" /><br /><ul style="overflow: auto;" id="igloo-filter-list">' + filterText + '</ul>';
cont += '</td><td valign="top" id="igloo-filter-details" style="width: 600px; padding: 0px;">';
cont += '<div style="padding: 10px;">Select \'edit\' from a filter on the left to begin...</div>';
cont += '</td></tr></table></div>';
tabcont.innerHTML = cont;
break;
case 'close':
this.hidedisplay ();
break;
default:
throw 'igloo: unexpected settings call, tab content undefined';
break;
}
}
}
function iglooChanges () {
// the iglooChanges object is the object that retrieves, sorts, manages and displays changes from Wikipedia
this.recentChanges = []; // main array, holding the changes
this.viewedChanges = []; // main array, holding diffs that should NOT be displayed (we've seen them already)
this.serverDetails = []; // main array, holding details from the server regarding users and pages
this.start = function () {
// start the changed program
this.startInterface ();
this.startTicker ();
}
this.startTicker = function () {
// perform the refresh ticks that grab info from the server
this.updateContent ();
this.refreshTicker = setInterval ( "igloo.iglooChanges.updateContent();", iglooSettings.updateTime * 1000 );
}
this.startInterface = function () {
// this creates the basic interface into which changes are placed when they have been received.
// essentially, it is a div that will contain clickable list elements.
this.changeDisplay = new wa_window ( igloo.iglooInterface );
this.changeDisplay.win_width = 190;
this.changeDisplay.win_height = parseInt ( igloo.iglooInterface.win_obj.style.height ) - 50;
this.changeDisplay.win_bg = '#ffffff';
this.changeDisplay.win_bd_rt = '1px solid #000000'; this.changeDisplay.win_bd_bt = '1px solid #000000';
this.changeDisplay.win_padding = 0;
this.changeDisplay.win_content = '<ul style="font-size: 10px; width: 100%; height: 100%; margin: 0px; padding: 0px; overflow-x: hidden; overflow-y: auto;" id="iglooChangesList"></ul>';
this.changeDisplay.applyAll ();
this.logoDisplay = new wa_window ( igloo.iglooInterface );
this.logoDisplay.win_top = parseInt ( igloo.iglooInterface.win_obj.style.height ) - 50;
this.logoDisplay.win_width = 190;
this.logoDisplay.win_height= 50;
this.logoDisplay.win_bg = '#ffffff';
this.logoDisplay.win_bd_tp = '1px solid #000000';
this.logoDisplay.win_padding = 0;
this.logoDisplay.win_content = '<img style="position: relative; top: -15px; left: 20px;" src="' + iglooSettings.remoteHost + 'images/igloo-logo.png" />';
this.logoDisplay.applyAll ();
}
this.addToViewed = function ( revid ) {
// mark an oldid as viewed so we do not display it more than once in the display window.
var sizeLimit = 30;
this.viewedChanges.push ( revid );
if ( this.viewedChanges.length > sizeLimit ) this.viewedChanges.shift ();
return true;
}
this.markViewed = function ( revid ) {
this.addToViewed ( revid );
// next, remove it from the recentChanges array, and redisplay that.
for ( var i = 0; i < this.recentChanges.length; i ++ ) {
if ( this.recentChanges[i][2] == revid ) {
this.recentChanges.splice(i, 1);
var change = i;
}
}
this.displayChanges ();
}
this.updateContent = function () {
var update = new iglooUpdateChanges ();
}
this.displayChanges = function () {
var visibleChangeOutput = '';
for ( var i = 0; i < this.recentChanges.length; i ++ ) {
if ( typeof this.recentChanges[i][4] == 'undefined' ) this.recentChanges[i][4] = 0.5;
var backgroundColour = igloo.iglooNet.colourScore ( this.recentChanges[i][4] );
if ( this.recentChanges[i][3] == true ) { var newPage = '<span style="font-weight: bold; font-size: 1.2em;">N</span> '; } else { var newPage = ''; }
visibleChangeOutput += '<li onclick="igloo.iglooControls.action_loadFromFeed(\''+this.recentChanges[i][0].replace (/'/g, '\\\'')+'\', \''+this.recentChanges[i][1].replace (/'/g, '\\\'')+'\', \''+this.recentChanges[i][2].replace (/'/g, '\\\'')+'\', '+this.recentChanges[i][3]+', '+this.recentChanges[i][4]+', \''+this.recentChanges[i][11].replace (/'/g, '\\\'')+'\');" onmouseover="this.style.backgroundColor = \'#dddddd\';" onmouseout="this.style.backgroundColor = \''+backgroundColour+'\';" style="cursor: pointer; width: 186px; padding: 2px; border-bottom: 1px solid #000000; list-style-type: none; list-style-image: none; marker-offset: 0px; background-color: '+backgroundColour+';">'+newPage+this.recentChanges[i][0]+'</li>';
}
document.getElementById('iglooChangesList').innerHTML = visibleChangeOutput;
}
this.destroy = function () { // calling this will destroy the interface and connections of this object.
this.changeDisplay.hide ();
this.logoDisplay.hide ();
if ( typeof this.refreshTicker != 'undefined' ) clearInterval ( this.refreshTicker );
}
}
function iglooUpdateChanges () {
// the iglooUpdate object handles making a request to the server, and returning an array of data.
this.updateCounter = 0;
this.update = function () {
switch ( this.updateCounter ) {
default: case 0:
// first, get some recent changes
var aRequest = this;
this.ajax = new wa_ajaxcall ();
this.ajax.requestUrl = iglooSettings.rootApi + '?format=xml&action=query&list=recentchanges&rcprop=user|title|ids|sizes|comment|tags&rctype=edit|new&rclimit=' + iglooSettings.updateQuantity;
this.ajax.doRequest ( function () {
aRequest.updateCounter ++;
aRequest.update ();
});
break;
case 1:
// recent changes are held such that:
// [0] = title
// [1] = user
// [2] = oldid
// [3] = new page?
// [4] = user vandal score
// [5] = priority note - a priority note is assigned to pages that have priority for some reason. These will be displayed at the top of the list, regardless of the score of the user.
// [6] = old length
// [7] = new length
// [8] = changed length
// [9] = comment
// [10] = tag string
// [11] - igloo change comments (can be set using filters)
this.tempChanges = [];
var data = this.ajax.response.getElementsByTagName ( 'rc' );
for (var i = 0; i < data.length; i++) {
this.tempChanges[i] = [];
this.tempChanges[i][0] = data[i].getAttribute ( 'title' );
this.tempChanges[i][1] = data[i].getAttribute ( 'user' );
this.tempChanges[i][2] = data[i].getAttribute ( 'revid' );
if ( data[i].getAttribute ( 'type' ) == 'edit' ) {
this.tempChanges[i][3] = false;
} else {
this.tempChanges[i][3] = true;
}
this.tempChanges[i][4] = 0;
this.tempChanges[i][5] = 0;
this.tempChanges[i][6] = parseInt ( data[i].getAttribute ( 'oldlen' ) );
this.tempChanges[i][7] = parseInt ( data[i].getAttribute ( 'newlen' ) );
this.tempChanges[i][8] = this.tempChanges[i][7] - this.tempChanges[i][6];
this.tempChanges[i][9] = data[i].getAttribute ( 'comment' );
var t = data[i].childNodes[0].childNodes, s = '::';
for ( var j = 0, l = t.length; j < l; j ++ ) {
s += t[j].childNodes[0].wholeText + '::';
}
this.tempChanges[i][10] = s;
this.tempChanges[i][11] = '';
}
this.updateCounter ++;
this.update ();
break;
case 2:
// we have the details - build the temporary changes array
var score = [];
for ( var i = 0; i < this.tempChanges.length; i ++ ) {
// if we have special data on this user, such as a priority score, append it here.
// check for pages
score.length = 0;
score = igloo.iglooNet.scoreObject ( this.tempChanges[i][0] );
// check for users
if ( score[0] === false ) {
score.length = 0;
score = igloo.iglooNet.scoreObject ( this.tempChanges[i][1] );
}
// backup
if ( score[0] === false ) score[0] = iglooSettings.defaultUserScore;
this.tempChanges[i][4] = score[0];
this.tempChanges[i][5] = score[1];
// apply any relevant filters to the changes we've loaded
if ( iglooSettings.enableFilters === true ) {
for ( var j = 0, l = iglooSettings.filterList.length; j < l; j ++ ) {
var t = iglooSettings.filterList [j];
if ( ( t[1] === false ) || ( t[4].parseSuccess === false ) ) continue;
this.tempChanges[i] = t[4].applyFilter ( this.tempChanges[i] );
if ( t[4].blockFilters === true ) {
t[4].blockFilters = false;
break;
}
}
}
}
// we want to remove all duplicates from the temp array, by copying them into
// another temp array only if they are not already there.
var tempArray = [];
for ( var i = 0; i < this.tempChanges.length; i ++ ) {
var t = false;
for ( var j = 0; j < tempArray.length; j ++ ) {
if ( this.tempChanges[i][0] == tempArray[j][0] ) {
t = true; break;
}
}
if ( t === false ) tempArray.push ( this.tempChanges[i] );
}
// now, remove any elements that are on the viewed list that we do not wish to display to the user OR that were made by our user
var limit = tempArray.length
for (var i = 0; i < limit; i ++) {
if ( ( in_array ( tempArray[i][2], igloo.iglooChanges.viewedChanges ) == true ) || ( ( tempArray[i][1] == wgUserName ) && ( iglooSettings.hideOwn == true ) ) ) {
tempArray.splice ( i, 1 ); i --; limit --;
} else {
if ( ( tempArray[i][0] == igloo.iglooDiff.currentDiff[0] ) && ( igloo.iglooActions.reversionEnabled !== 'pause' ) ) {
// if this is the same title as the page we're viewing, update the display
igloo.iglooChanges.addToViewed ( tempArray[i][2] );
igloo.iglooDiff.display ( tempArray[i][0], tempArray[i][1], tempArray[i][2], tempArray[i][3], tempArray[i][4], tempArray[i][11] );
igloo.iglooDiff.haschanged = true;
tempArray.splice ( i, 1 ); i --; limit --;
}
}
}
// we now have the full array of scores
// go through the main recent changes array, check if there are any pages that match
// here and there, delete them from the main array, then merge this one into the main one
var i = 0;
while ( typeof igloo.iglooChanges.recentChanges[i] != 'undefined' ) {
for ( var j = 0; j < tempArray.length; j ++ ) {
if ( typeof igloo.iglooChanges.recentChanges[i] == 'undefined' ) break;
if ( igloo.iglooChanges.recentChanges[i][0] == tempArray[j][0] ) {
igloo.iglooChanges.recentChanges.splice ( i, 1 );
i --;
}
}
i ++;
}
// recent changes array now holds all the data it did before EXCEPT titles that conflict with the new changes
// merge the new changes into the old ones
igloo.iglooChanges.recentChanges = tempArray.concat ( igloo.iglooChanges.recentChanges );
// now, sort the array based on the float values :)
igloo.iglooChanges.recentChanges = sort_array_multi ( igloo.iglooChanges.recentChanges, 4, 'descending' );
// check that we aren't over the hard limit for number of changes. If we are, remove those least likely to be vandalism.
if ( igloo.iglooChanges.recentChanges.length > iglooSettings.updateLimit ) {
igloo.iglooChanges.recentChanges = igloo.iglooChanges.recentChanges.splice ( 0, iglooSettings.updateLimit ); }
// now, we have to display the changes to the user!
igloo.iglooChanges.displayChanges ();
break;
}
}
this.update();
}
function iglooDiff () {
// the iglooDiff module is the object that displays and styles Wikiepdia diffs in the main window
this.viewingDiff = false;
this.previousDiff = [];
this.currentDiff = [];
this.displayCounter = 0;
this.displayHistory = [];
this.historyPosition = 0;
this.canAddToHist = true;
this.start = function () { // this functions creates the diff window for future use, and displays the latest news in it :)
this.startInterface ();
this.displayWelcome ();
this.warnedParser = false;
}
this.startInterface = function () {
// this creates the basic interface into which changes are placed when they have been received.
// essentially, it is a div that will contain clickable list elements.
this.scoreDisplay = new wa_window ( igloo.iglooInterface );
this.scoreDisplay.win_left = 190;
this.scoreDisplay.win_top = 79;
this.scoreDisplay.win_width = parseInt ( igloo.iglooInterface.win_obj.style.width ) - 200;
this.scoreDisplay.win_height= 11;
this.scoreDisplay.win_bg = '#ffffff';
this.scoreDisplay.win_bd_bt = '1px solid #000000';
this.scoreDisplay.win_padding = 2;
this.scoreDisplay.win_fontsize = 10;
this.scoreDisplay.win_content = 'You are not yet viewing a diff';
this.scoreDisplay.applyAll ();
this.diffDisplay = new wa_window ( igloo.iglooInterface );
this.diffDisplay.win_left = 190;
this.diffDisplay.win_top = 95;
this.diffDisplay.win_width = parseInt ( igloo.iglooInterface.win_obj.style.width ) - 200;
this.diffDisplay.win_height= parseInt ( igloo.iglooInterface.win_obj.style.height ) - 255;
this.diffDisplay.win_bg = '#ededff';
this.diffDisplay.win_padding = 5;
this.diffDisplay.win_content = '<div id="iglooDiffDisplay" style="width: 100%; height: 100%; overflow: auto;">DIFFS INIT</div>';
this.diffDisplay.applyAll ();
}
this.displayWelcome = function () {
// this function specifically displays the welcome message in the diff window
var welcomeRequest = new wa_mediawikiApi ();
welcomeRequest.onCompleteAction = function ( data ) {
var regTest = /welcome:(.+?);;/i, o;
regResult = regTest.exec( this.data['page']['revisions'][0]['content'] );
o = regResult[1].replace ( '%CURRENTVERSION%', iglooSettings.version );
document.getElementById( 'iglooDiffDisplay' ).innerHTML = o;
};
welcomeRequest.getPage ( iglooSettings.localBase + 'config', 1, 'content' );
}
this.display = function ( title, user, revisionId, newPage, diffScore, iglooNetComment ) { // this function displays the diff of an edit on the screen for the user
// the user has displayed activity by initiating a diff display.
this.viewingDiff = true;
this.haschanged = false;
igloo.iglooSession.userActivity = true;
// update the holding variables. Some of these may be absent based on the origin of the display call.
if ( typeof this.currentDiff[0] != 'undefined' ) { this.previousDiff[0] = this.currentDiff[0]; this.previousDiff[1] = this.currentDiff[1]; this.previousDiff[2] = this.currentDiff[2]; this.previousDiff[3] = this.currentDiff[3]; this.previousDiff[4] = this.currentDiff[4]; this.previousDiff[5] = this.currentDiff[5]; }
this.currentDiff[0] = title; this.currentDiff[1] = user; this.currentDiff[2] = revisionId; this.currentDiff[3] = newPage; this.currentDiff[4] = diffScore; this.currentDiff[5] = iglooNetComment;
// add to history
this.manageHist ();
// investigate
if ( this.currentDiff [1] ) igloo.iglooNet.investigate ( this.currentDiff [1] );
// decide upon the request to perform - is this a specific request, or a general one?
if ( ! revisionId ) {
revisionId = false;
var url = mw.config.get('wgServer') + mw.config.get('wgScript') + '?title=' + encodeURIComponent ( title ) + '&diff=cur&diffonly=true&redirect=no';
} else {
var url = mw.config.get('wgServer') + mw.config.get('wgScript') + '?oldid=' + revisionId + '&diff=prev&diffonly=true&redirect=no';
}
var aDisplay = this;
this.ajax = new wa_ajaxcall ();
this.ajax.requestUrl = url;
this.ajax.doRequest ( function () {
aDisplay.parseScreenScrape ();
});
}
this.manageHist = function () {
// add the PREVIOUS page to the display history.
if ( ( this.currentDiff[0] ) && ( this.currentDiff[1] ) && ( this.currentDiff[2] ) ) if ( this.canAddToHist == true ) {
// first, remove any history between the current position and 0.
if ( this.historyPosition > 0 ) {
var temp = [];
temp.length = 0;
temp = this.displayHistory.slice(this.historyPosition);
this.displayHistory.length = 0;
this.displayHistory = temp;
this.historyPosition = 0;
}
// then add the page
var histEntry = [];
histEntry.length = 0;
histEntry[0] = this.currentDiff[0]; histEntry[1] = this.currentDiff[1]; histEntry[2] = this.currentDiff[2];
this.displayHistory.unshift ( histEntry );
if ( this.displayHistory > iglooSettings.maxHistory ) this.displayHistory.length = iglooSettings.maxHistory;
}
this.canAddToHist = true;
// handle greying of invalid options
var backButton = document.getElementById('igloo-buttons-back-b');
var forwardButton = document.getElementById('igloo-buttons-forward-b');
var backUrl = '' + iglooSettings.remoteHost + 'images/igloo-back';
var forwardUrl = '' + iglooSettings.remoteHost + 'images/igloo-forward';
var grey = '-grey';
var filetype = '.png';
if (this.displayHistory.length <= 1) { backButton.src = backUrl + grey + filetype; forwardButton.src = forwardUrl + grey + filetype; }
else if ( (this.displayHistory.length > 1) && (this.historyPosition == 0) ) { backButton.src = backUrl + filetype; forwardButton.src = forwardUrl + grey + filetype; }
else if ( (this.displayHistory.length > 1) && (this.historyPosition == (this.displayHistory.length - 1)) ) { backButton.src = backUrl + grey + filetype; forwardButton.src = forwardUrl + filetype; }
else { backButton.src = backUrl + filetype; forwardButton.src = forwardUrl + filetype; }
}
this.goBack = function ( count ) {
if ( this.displayHistory.length <= 0 ) return false;
if ( ! count ) count = 1;
if ( ( this.historyPosition + count ) > this.displayHistory.length ) count = this.displayHistory.length;
this.historyPosition += count;
var doView = this.displayHistory [this.historyPosition];
this.canAddToHist = false;
this.display ( doView[0], doView[1], doView[2] );
return true;
}
this.goForward = function(count) {
if (this.historyPosition <= 0) return false;
if (!count) count = 1;
if ( (this.historyPosition - count) < 0 ) { this.historyPosition = 0; } else { this.historyPosition -= count; }
var doView = this.displayHistory[this.historyPosition];
this.canAddToHist = false;
this.display(doView[0], doView[1], doView[2]);
}
this.parseScreenScrape = function ( html ) {
if ( html == null ) {
if ( typeof this.ajax.responseXML !== 'undefined' ) { html = this.ajax.responseXML; var tryParse = false; } else
{ html = this.ajax.responseText; var tryParse = true; }
}
if ( ! html ) return false;
// CSS details: object widths
var markerwidth = 14;
var contentwidth = ( this.diffDisplay.win_width / 2 ) - markerwidth;
// step 0 - build an XML document from the HTML for IE - cos it's rubbish
var ie = false, err = false, t = 'nothing';
if ( ( ! html.getElementById ) && ( tryParse === false ) ) {
// we're hacking for IE
ie = true;
// get, then clean, the responseText
html = this.ajax.pageRequest.responseText;
html = html.substr ( html.indexOf ( '<html' ) );
html = html.replace ( / /g, ' ' );
var doc = ie_create_document ();
var test = doc.loadXML ( html );
if ( doc.parseError.errorCode != 0 ) {
alert ( 'Internet Explorer failed to parse the incoming page because igloo sanitised it incorrectly. XML parser returned:'+"\n"+doc.parseError.reason );
return false;
}
html = doc;
} else {
// perform error checking on the retrieved document
if ( html.getElementsByTagName ) {
var err = html.getElementsByTagName ( 'parsererror' ), attempt;
err = err.length;
} else { var err = 1, attempt; }
if ( err > 0 ) {
if ( typeof this.ajax.responseText !== 'undefined' ) {
attempt = this.ajax.responseText;
// sanitise XML
attempt = attempt.replace ( / /g, ' ' );
attempt = attempt.replace ( /&/g, '&' );
attempt = attempt.replace ( /®/g, '®' );
attempt = attempt.replace ( /©/g, '©' );
// final replacements
attempt = attempt.replace ( /&([^#])/g, '&$1' );
if ( window.DOMParser ) {
var parser = new DOMParser ();
html = parser.parseFromString ( attempt, 'text/xml' );
if ( html.getElementsByTagName ( 'parsererror' ).length > 0 ) { err = true; t = html.getElementsByTagName ( 'parsererror' )[0].firstChild.nodeValue; } else {
if ( this.warnedParser !== true ) igloo.iglooStatus.addStatus ( '<strong>Warning: igloo was forced to sanitise the incoming page because it contained invalid XML. This is most commonly caused by a faulty, recent change to the Wikipedia page layout and may require reporting if you frequently receive this error.</strong>' );
this.warnedParser = true;
}
} else {
err = true;
}
} else {
err = true;
}
}
}
if ( err === true ) {
// clean
document.getElementById('iglooDiffDisplay').innerHTML = '';
// the container div
var innerDiv = document.createElement ( 'div' );
innerDiv.setAttribute ( 'id', 'iglooInnerDiv' );
innerDiv.style.margin = 'auto';
t = t.replace ( '<', '<' ); t = t.replace ( '>', '>' ); t = t.replace ( "\n", '<br />' );
innerDiv.innerHTML = '<strong>igloo error: an unrecoverable XML parsing error occured on the page you attempted to view. This is most commonly caused by a faulty, recent change to the Wikipedia page layout. If you are receiving this error frequently, you should stop using igloo and report the problem to User:Ale_jrb.</strong><br />Details:</br />' + t;
// display everything in the window
document.getElementById('iglooDiffDisplay').appendChild ( innerDiv );
document.getElementById('iglooDiffDisplay').innerHTML += ' ';
return false;
}
// step 1 - build an array of the data that is displayed by the diff screen
// this.diffData[0] = old
// this.diffData[1] = new
// #[0] = revision as of
// #[1] = username
// #[2] = comment/summary
this.diffData = [];
this.diffData[0] = []; this.diffData[1] = [];
for ( var i = 0; i < 3; i ++ ) {
if ( html.getElementById ) { // good browsers
if ( html.getElementById ( 'mw-diff-otitle' + ( i + 1 ) ) != null ) { this.diffData[0][i] = echo_nodes_recursive ( html.getElementById ( 'mw-diff-otitle' + ( i + 1 ) ) ); }
if ( html.getElementById ( 'mw-diff-ntitle' + ( i + 1 ) ) != null ) { this.diffData[1][i] = echo_nodes_recursive ( html.getElementById ( 'mw-diff-ntitle' + ( i + 1 ) ) ); }
} else { // the trash that is IE
this.diffData[0][i] = ie_getElementById ( html, 'mw-diff-otitle' + ( i + 1 ) ).text;
this.diffData[1][i] = ie_getElementById ( html, 'mw-diff-ntitle' + ( i + 1 ) ).text;
}
}
// step 2 - remove that from the visible diff
var allTables = html.getElementsByClassName ( 'diff' );
for ( var i = 0; i < allTables.length; i ++ ) {
if ( allTables[i].className == 'diff' ) break;
}
if ( i >= allTables.length ) i = ( allTables.length - 1 );
if (i < 0 ) { var newPage = true; } else { var newPage = false; }
if ( newPage == false ) {
var table = document.createElement ( 'table' );
table.className = 'diff';
// in order to add content to the table in IE, we must first add it to a diff. We also handle styling IE output here.
if ( ie ) {
var tempIEDiv = document.createElement ( 'div' );
var tempIETable = ie_cloneNode ( allTables[i] );
tempIEDiv.appendChild ( tempIETable );
//tempIEDiv.innerHTML = this.flag(tempIEDiv.innerHTML);
tempIEDiv.innerHTML = tempIEDiv.innerHTML.replace(/class='?diff-context'?/ig, 'style="background-color: #ddddff;"');
tempIEDiv.innerHTML = tempIEDiv.innerHTML.replace(/class='?diff-addedline'?/ig, 'style="background-color: #ccddcc;"');
tempIEDiv.innerHTML = tempIEDiv.innerHTML.replace(/class='?diff-deletedline'?/ig, 'style="background-color: #ffffaa;"');
tempIEDiv.innerHTML = tempIEDiv.innerHTML.replace(/class='?diff['>]/ig, 'style="width: 100%; font-size: 12px; background-color: #ededff;"');
tempIEDiv.innerHTML = tempIEDiv.innerHTML.replace(/(del |ins )class=['"]?.*?diffchange.*?['"]?(>)?/ig, '$1style="text-decoration: none; font-weight: bold; color: #ff0000;"$2');
tempIEDiv.innerHTML = tempIEDiv.innerHTML.replace(/class='?diff-marker'?/ig, 'style="width: '+markerwidth+'px; font-size: 14px; font-weight: bold;"');
tempIEDiv.innerHTML = tempIEDiv.innerHTML.replace(/class='?diff-content'?/ig, 'style="width: '+contentwidth+'px;"');
table.appendChild ( tempIEDiv );
} else {
table.innerHTML = allTables[i].innerHTML.toString();
var size = iglooSettings.diffFontSize;
table.innerHTML = table.innerHTML.replace ( /class="diff-addedline"/ig, 'class="diff-addedline" style="font-size: '+size+'px;"' );
table.innerHTML = table.innerHTML.replace ( /class="diff-context"/ig, 'class="diff-context" style="font-size: '+size+'px;"' );
table.innerHTML = table.innerHTML.replace ( /class="diff-deletedline"/ig, 'class="diff-deletedline" style="font-size: '+size+'px;"' );
table.innerHTML = this.flagProfanity(table.innerHTML);
}
// remove the built in rubbish
if ( table.getElementsByTagName ( 'tr' )[0] != null ) table.getElementsByTagName ( 'tr' )[0].parentNode.removeChild ( table.getElementsByTagName ( 'tr' )[0] );
// add our own (basically rubbish) stuff
// first, users
var newTr = document.createElement ( 'tr' );
if ( this.diffData[0][1] ) {
var oldEditor = this.diffData[0][1].substr( 0, this.diffData[0][1].indexOf('(talk') );
} else { var oldEditor = '? missing - report ?'; }
if ( this.diffData[1][1] ) {
var newEditor = this.diffData[1][1].substr( 0, this.diffData[1][1].indexOf('(talk') );
} else { var newEditor = '? missing - report ?'; }
// if we don't have the user for this diff, we might as well set it, even if something goes wrong; it's better than nothing
if ( typeof this.currentDiff[1] == 'undefined' ) this.currentDiff[1] = newEditor;
if ( this.currentDiff[1] === true ) /* will be true if a revert fails; we should still try and score it */ this.currentDiff[1] = newEditor;
var newTd1 = document.createElement ( 'td' );
newTd1.innerHTML = ''+oldEditor+'';
newTd1.setAttribute ( 'colspan', '2' );
newTd1.setAttribute ( 'align', 'center' );
newTd1.setAttribute ( 'width', '50%' );
var newTd2 = document.createElement ( 'td' );
newTd2.innerHTML = ''+newEditor+'';
newTd2.setAttribute ( 'colspan', '2' );
newTd2.setAttribute ( 'align', 'center' );
newTd2.setAttribute ( 'width', '50%' );
newTr.appendChild(newTd1); newTr.appendChild(newTd2);
table.insertBefore(newTr, table.firstChild);
// second, summaries
var newTr = document.createElement('tr');
if ( ( typeof this.diffData[0][2] != 'undefined' ) && ( this.diffData[0][2] != false ) ) { var oldSummary = this.diffData[0][2]; } else { var oldSummary = ''; }
if ( ( typeof this.diffData[1][2] != 'undefined' ) && ( this.diffData[1][2] != false ) ) { var newSummary = this.diffData[1][2]; } else { var newSummary = ''; }
if ( oldSummary.indexOf ( '(del/undel)' ) > -1 ) oldSummary = oldSummary.substr ( 0, oldSummary.indexOf ( '(del/undel)' ) );
if ( newSummary.indexOf ( '(del/undel)' ) > -1 ) newSummary = newSummary.substr ( 0, newSummary.indexOf ( '(del/undel)' ) );
var newTd1 = document.createElement('td');
newTd1.innerHTML = ''+oldSummary+'';
newTd1.setAttribute('colspan','2');
newTd1.setAttribute('align','center');
var newTd2 = document.createElement('td');
newTd2.innerHTML = ''+newSummary+'';
newTd2.setAttribute('colspan','2');
newTd2.setAttribute('align','center');
newTr.appendChild(newTd1); newTr.appendChild(newTd2);
table.insertBefore(newTr, table.childNodes[1]);
} else {
// step 2 - get the page content
var table = document.createElement ( 'div' );
table.setAttribute ( 'style', 'font-size: 12px;' );
table.className = 'diff diff-contentalign-left';
var text = this.ajax.pageRequest.responseText;
text = text.substring ( text.indexOf ( '</h2>' ), text.indexOf ( '<div class="printfooter"' ) );
table.innerHTML = text;
}
// step 3 - remove old details
if (document.getElementById('iglooPageTitle') != null) document.getElementById('iglooPageTitle').parentNode.removeChild(document.getElementById('iglooPageTitle'));
if (document.getElementById('iglooInnerDiv') != null) document.getElementById('iglooInnerDiv').parentNode.removeChild(document.getElementById('iglooInnerDiv'));
document.getElementById('iglooDiffDisplay').innerHTML = '';
// step 4 - output the page title to the diff screen
var pageTitle = document.createElement('div');
pageTitle.setAttribute('id', 'iglooPageTitle');
pageTitle.style.fontSize = '16px';
pageTitle.style.fontWeight = 'bold';
pageTitle.style.width = '100%';
pageTitle.style.marginBottom = '5px';
pageTitle.style.borderBottom = '1px solid #000';
if ( this.currentDiff[3] ) { var extra = '(NEW PAGE) '; } else { var extra = ''; }
var pageTitleContent = document.createTextNode(extra + this.currentDiff[0]);
pageTitle.appendChild(pageTitleContent);
document.getElementById('iglooDiffDisplay').appendChild(pageTitle);
// step 5 - output the table in question to the diff screen
// here, we handle styling for NON-IE browsers
if ( ! ie ) {
var style = document.createElement('style');
style.setAttribute('type', 'text/css');
var cssString = 'span.iglooProfanity { background-color: #ff99ff; font-weight: bold; text-decoration: underline; } table.diff { width: 100%; font-size: 12px; background-color: #ededff; } col.diff-marker { width: '+markerwidth+'px; font-size: 14px; font-weight: bold; } col.diff-content { width: '+contentwidth+'px; } td.diff-lineno { font-weight: bold; } td.diff-addedline { background-color: #ccffcc; } td.diff-deletedline { background-color: #ffffaa; } td.diff-context { background-color: #ddddff; } .diffchange { text-decoration: none; font-weight: bold; color: #ff0000; }';
var cssText = document.createTextNode(cssString);
style.appendChild(cssText);
document.getElementById('iglooDiffDisplay').appendChild(style);
}
// the container div
var innerDiv = document.createElement ( 'div' );
innerDiv.setAttribute ( 'id', 'iglooInnerDiv' );
innerDiv.style.margin = 'auto';
// stick the table of stuff into the div
innerDiv.appendChild ( table );
// display everything in the window
document.getElementById('iglooDiffDisplay').appendChild(innerDiv);
document.getElementById('iglooDiffDisplay').innerHTML += ' ';
// we can now revert this edit
if ( igloo.iglooActions.reversionEnabled == 'pause' ) igloo.iglooActions.reversionEnabled = 'yes';
// handle the diff scoring window
this.updateScoreDisplay ( this.currentDiff[4] );
}
this.updateScoreDisplay = function ( score ) {
if ( score == null ) {
score = igloo.iglooNet.scoreObject ( this.currentDiff[1] );
score = score[0];
if ( score === false ) score = iglooSettings.defaultUserScore;
}
if ( typeof this.currentDiff[5] !== 'string' ) this.currentDiff[5] = '';
if ( score != null ) {
if ( score >= 0.8 ) {
this.scoreDisplay.win_content = 'igloo asserts that this edit is <strong>PROBABLE VANDALISM</strong>.';
} else if ( score >= 0.6 ) {
this.scoreDisplay.win_content = 'igloo asserts that this edit is <strong>possible vandalism</strong>.';
} else if ( score >= 0.4 ) {
this.scoreDisplay.win_content = 'igloo has little or no data on this diff, and cannot make a risk assertion.';
} else if ( score >= 0.2 ) {
this.scoreDisplay.win_content = 'igloo asserts that this edit is <strong>unlikely to be vandalism</strong>.';
} else if ( score >= 0 ) {
this.scoreDisplay.win_content = 'igloo asserts that this edit is <strong>free from vandalism</strong>.';
} else {
this.scoreDisplay.win_content = 'iglooNet data for this diff is missing.';
}
} else {
score = iglooSettings.defaultUserScore;
this.scoreDisplay.win_content = 'iglooNet data for this diff is missing.';
}
this.scoreDisplay.win_content += '' + this.currentDiff[5];
this.scoreDisplay.win_bg = igloo.iglooNet.colourScore ( score, '#ffffff' );
this.scoreDisplay.applyAll();
}
this.flagProfanity = function(html) {
// this function flags profanity in the diff window
if ( iglooSettings.profFilter !== true ) return html;
var profanity = new Array(
/\b((?:moth[era]*)?[ -]*f+(?:u|oo)[ck]{2,}(?:ing?|er|hole)?s*|s[e3]+x+[iey]*|r[a4]p(?:e+d*|i+s+t+s*)|su[ck]+(?:s+|ed+|i+n+g+)?|gang[- ]?bang(?:er|ing)?|(?:(?:t+h+|f+)r[e3]{2,}|four)+s[o0]+me+)\b/ig, /* sexual intercourse */
/\b(h[o0]+m[o0]+(?:sexual(?:it(?:y|e)+)?)?|(?:is +)?ga+[iy]+|lesb(?:ian|[o0]*))\b/ig, /* homosexuality */
/\b([ck][o0]+[ck]{2,}(?:head|face|(?:su[ck]{2,}(?:er|ing)?))?|d[o0]+n+g|p[3e]+n[iu]+s+[3e]*s*|p+[3e]{2,}|d[i1]+[ck]{2,}s*(?:su[ck]{2,}(?:er|ing)?)?|manh(?:[o0]{2,}|u+)d+|b[o0]+n+e*r+s*|ball[sz]+(?:a[ck]{2,})?)\b/ig, /* male genitalia */
/\b(cun+(?:t|[iey]+)s*|vag(?:ina)?s*|puss+[yie]+s*|fann+[yie]+s*)\b/ig, /* female genitalia */
/\b(t+i+t+(?:s*|[iey]+[sz]*)|breasts*|b+[o0]{2,}b+[ieys]*)\b/ig, /* breasts */
/\b(anal+|ar*ss+e*|ar*se+s+|(?:bum+|butt+) ?(?:h[o0]+le|cr+a[ck]+|o(?:[ck]+s|x+))?)\b/ig, /* anus */
/\b((?:bull)?(?:s+hite*|ass+)(?:holes?|he[a4]+d+s*)?|cr[a4*]+p+[iy]*|cru+d+|poo+)\b/ig, /* excretion */
/\b(w*h+[o0]+r*e+s*|prostitutes*|s+l+u+t+s*|slags*|cu+m+(?:ing)?|d[il]{2,}d[o0]+[o0e]*s*|(?:b+l+[o0]+w+|h+[a4]+n+d+|t[i1]+t+[iey]*)j+[o0]+b+[sz]*|c[o0]+ndom[sz]*|p[o0]+rn)\b/ig, /* sexual */
/\b(nigg+(?:er|a+)s*|naz+i+[sz]+|ped[o0]+(?:[phf]+ile)?[sz]*)\b/ig, /* racism & libel */
/\b(ret[a4]+r+d+(?:ed|s)?|f+[a4]+g+([o0]+t+)?s*|d[ou]+che?(ba+g)?s*|bast[ea]rds*|bit*ch[iey]*|[you]*r+ ?m+[ou]+m+)\b/ig, /* other insults */
/('{3,}bold text'{3,}|'{2,}italic text'{2,}|\[{2,}link title\]{2,}|\[http:\/\/www\.example\.com link title\]|={2,} *headline text *={2,})/ig, /* wiki test */
/\b(q[qwerty]{5,}|[asdf]{8,}|[ghjkl]{8,}|[uiop]{8,})\b/ig, /* nonsense */
/\b(lol(?:l*ol|cat[sz]*)*|li+e+k)\b/ig, /* lolz */
/\b(ha?i+(?=\/)|he+ll+o+|(?:ha+|hee+|ho+)+|l[ou]+v+|ya|ye+h+)\b/ig, /* laughs/greetz */
/([!?;]{3,}|[.|]{4,}|={6,}|([a-z0-9])\2{6,})/ig /* repeating characters */
);
for ( var i = 0, l = profanity.length; i < l; i ++ ) {
html = html.replace(profanity[i], '<span class="iglooProfanity">$1</span>');
}
return html;
}
this.destroy = function () { // calling this will destroy the interface and connections of this object.
this.diffDisplay.hide ();
this.scoreDisplay.hide ();
}
}
function iglooHist () {
// the iglooHist object handles the retrieval and display of the history of a page, in order
// that it can be displayed to the user.
// timer var
this.timer = null;
this.startInterface = function() {
if (document.getElementById('igloo-buttons-history') == null) return false;
this.histCatcher = new wa_window ( document.getElementById ( 'igloo-buttons-history' ) );
this.histCatcher.win_top = 71;
this.histCatcher.win_left = -100;
this.histCatcher.win_width = 170;
this.histCatcher.win_height= 80;
this.histCatcher.win_alpha = 0;
this.histCatcher.win_cursor = 'pointer';
this.histCatcher.win_disp = 'none';
this.histCatcher.applyAll ();
this.histDisplay = new wa_window ( document.getElementById ( 'igloo-buttons-history' ) );
this.histDisplay.win_top = 77;
this.histDisplay.win_left = -100;
this.histDisplay.win_width = 170;
this.histDisplay.win_bg = '#d0d0d0';
this.histDisplay.win_bd = '#000000';
this.histDisplay.win_bd_wd = 1;
this.histDisplay.win_padding = 2;
this.histDisplay.win_fontsize = 10;
this.histDisplay.win_cursor = 'pointer';
this.histDisplay.win_disp = 'none';
this.histDisplay.win_content = '<div id="iglooPageHistory-note" style="width: 100%;">loading page history - wait...</div><ul style="display: none; width: 100%; height: 100%; margin: 0px; padding: 0px; overflow-x: hidden; overflow-y: auto;" id="iglooPageHistory-cont"></ul>';
this.histDisplay.applyAll ();
// unfortunately, these pseudo events cannot be detatched. See waLib.js for implementation.
wa_attach ( document.getElementById ( 'igloo-buttons-history' ), 'mouseenter', igloo.iglooHist.mouseOver );
wa_attach ( document.getElementById ( 'igloo-buttons-history' ), 'mouseleave', igloo.iglooHist.mouseOut );
}
this.mouseOver = function () {
if ( igloo.iglooDiff.viewingDiff === true ) {
if ( igloo.iglooHist.timer ) { clearTimeout ( igloo.iglooHist.timer ); igloo.iglooHist.timer = false; } else {
igloo.iglooHist.histDisplay.show (); igloo.iglooHist.histCatcher.show ();
igloo.iglooHist.getHistory ();
}
}
}
this.mouseOut = function () {
igloo.iglooHist.timer = setTimeout(function() { igloo.iglooHist.histDisplay.hide(); igloo.iglooHist.histCatcher.hide(); igloo.iglooHist.timer = false; }, iglooSettings.histWinTimeout * 1000);
}
this.getHistory = function ( callback, data ) {
// the get history module retrieves a page history and displays it to the user
switch ( callback ) {
default: case 0:
document.getElementById ( 'iglooPageHistory-cont' ).innerHTML = 'loading page history - wait...';
var pageHist = new wa_mediawikiApi ();
pageHist.onCompleteAction = function ( data ) { igloo.iglooHist.getHistory ( 1, data ); };
pageHist.getPage ( igloo.iglooDiff.currentDiff[0], 15, 'ids|user' );
break;
case 1:
document.getElementById('iglooPageHistory-cont').style.display = 'block';
document.getElementById('iglooPageHistory-note').style.display = 'none';
var pageHistory = '';
for (var i = 0; i < data['page']['revisions'].length; i ++ ) {
var revision = data['page']['revisions'][i];
var user = revision['user'];
var score = igloo.iglooNet.scoreObject(user);
var backgroundColour = igloo.iglooNet.colourScore(score[0], '#ffffff');
pageHistory += '<li id="iglooHist_'+revision['id']+'" onclick="igloo.iglooControls.action_loadFromFeed(\''+igloo.iglooDiff.currentDiff[0].replace ('\'', '\\\'')+'\', \''+revision['user']+'\', \''+revision['id']+'\');" onmouseover="this.style.backgroundColor = \'#dddddd\';" onmouseout="this.style.backgroundColor = \''+backgroundColour+'\';" style="cursor: pointer; width: 186px; padding: 2px; border-bottom: 1px solid #000000; list-style-type: none; list-style-image: none; marker-offset: 0px; background-color: '+backgroundColour+';">'+revision['user']+'</li>';
}
pageHistory += '<li style="width: 100%; list-style-type: none; list-style-image: none; text-align: center;" onclick="igloo.iglooActions.sendLinkToParent(wgServer + wgScript + \'?title=\' + igloo.iglooDiff.currentDiff[0] + \'&action=history\');">- full history -</li>';
document.getElementById('iglooPageHistory-cont').innerHTML = pageHistory;
break;
}
}
}
function iglooControls () {
// the igloo controls module handles attaching to, and watching, keyboard events, and performing the requested function
this.blockActions = false;
this.start = function () { // this functions creates the diff window for future use, and displays the latest news in it :)
this.startInterface ();
this.bindKeys ();
}
this.startInterface = function () {
this.controlDisplay = new wa_window ( igloo.iglooInterface );
this.controlDisplay.win_left = 190;
this.controlDisplay.win_width = parseInt ( igloo.iglooInterface.win_obj.style.width ) - 192;
this.controlDisplay.win_height= 78;
this.controlDisplay.win_bg = '#fdfdff';
this.controlDisplay.win_bd_tp = '1px solid #000000';
this.controlDisplay.win_bd_bt = '1px solid #000000';
this.controlDisplay.win_padding = 1;
this.controlDisplay.win_content = '<div id="iglooControlsDisplay" style="width: 100%; height: 100%;">CONTROLS INIT</div>';
this.controlDisplay.applyAll ();
this.attachButtons ();
igloo.iglooHist = new iglooHist ();
igloo.iglooHist.startInterface ();
}
this.attachButtons = function() {
var parent = document.getElementById('iglooControlsDisplay'), buttons = 0;
var panelButton = '<div id="igloo-buttons-revertwarn" style="position: relative; float: left; padding-left: -1px; padding-top: -1px; width: 73px; height: 73px; margin-top: 7px; margin-left: 5px; cursor: pointer;"><img src="' + iglooSettings.remoteHost + 'images/igloo-revert.png" onclick="if (typeof igloo.iglooDiff.currentDiff[0] != \'undefined\') { igloo.iglooControls.action_revertDiff(); }" /></div>';
panelButton += '<div id="igloo-buttons-back" style="position: relative; float: left; padding-left: -1px; padding-top: -1px; width: 50px; height: 50px; margin-top: 2px; margin-left: 20px; cursor: pointer;"><img id="igloo-buttons-back-b" src="' + iglooSettings.remoteHost + 'images/igloo-back-grey.png" onclick="igloo.iglooControls.action_historyBack();" /></div>'; buttons ++;
panelButton += '<div id="igloo-buttons-forward" style="position: relative; float: left; padding-left: -1px; padding-top: -1px; width: 50px; height: 50px; margin-top: 2px; margin-left: 10px; cursor: pointer;"><img id="igloo-buttons-forward-b" src="' + iglooSettings.remoteHost + 'images/igloo-forward-grey.png" onclick="igloo.iglooControls.action_historyForward();" /></div>'; buttons ++;
if ( iglooSettings.mesysop === true ) { panelButton += '<div id="igloo-buttons-block" style="position: relative; float: left; padding-left: -1px; padding-top: -1px; width: 50px; height: 50px; margin-top: 2px; margin-left: 10px; cursor: pointer;"><img id="igloo-buttons-block-b" src="' + iglooSettings.remoteHost + 'images/igloo-block.png" onclick="igloo.iglooControls.action_block();" /></div>'; buttons ++; }
var browsePos = ( 62 * buttons ) - 15;
panelButton += '<div id="igloo-input-browse" style="position: relative; float: left; top: 53px; left: -' + browsePos + 'px; width: 230px; height: 20px;"><input id="igloo-browse-to" type="text" style="width: 200px; height: 14px; " onfocus="igloo.iglooControls.action_browseFocus();" onblur="igloo.iglooControls.action_browseBlur();" /> <img style="position: relative; top: -3px; cursor: pointer;" src="' + iglooSettings.remoteHost + 'images/igloo-go.png" onclick="igloo.iglooControls.action_browseBarDo();" /></div>';
panelButton += '<div id="igloo-buttons-settings" style="position: relative; float: right; padding-left: -1px; padding-top: -1px; width: 73px; height: 73px; margin-top: 3px; margin-right: 5px; cursor: pointer;"><img src="' + iglooSettings.remoteHost + 'images/igloo-settings.png" onclick="igloo.iglooManageSettings.showdisplay ();" /></div>';
panelButton += '<div id="igloo-buttons-history" style="position: relative; float: right; padding-left: -1px; padding-top: -1px; width: 73px; height: 73px; margin-top: 3px; margin-right: 5px; cursor: pointer;"><img src="' + iglooSettings.remoteHost + 'images/igloo-hist.png" /></div>';
parent.innerHTML = panelButton;
}
this.bindKeys = function() {
wa_attach ( document, 'keydown', igloo.iglooControls.killKeys );
//wa_attach ( document, 'keypress', igloo.iglooControls.killKeys );
wa_attach ( document, 'keyup', igloo.iglooControls.handleKeys );
}
this.handleKeys = function ( e ) {
if ( ! e ) e = window.event;
if ( e.keyCode ) {
var keyPress = e.keyCode;
var use = 'key';
} else {
var keyPress = e.charCode;
var use = 'char';
}
var result = igloo.iglooControls.manageKeys ( keyPress, use, false );
if ( result === true ) return true;
if ( e.preventDefault ) { e.preventDefault (); } else { return false; }
return true;
}
this.killKeys = function ( e ) {
// check whether to prevent the default action
if ( iglooSettings.blockKeys === false ) return true;
if ( ! e ) e = window.event;
if ( e.keyCode ) {
var keyPress = e.keyCode;
var use = 'key';
} else {
var keyPress = e.charCode;
var use = 'char';
}
var result = igloo.iglooControls.manageKeys ( keyPress, use, true );
if ( result === true ) return true;
if ( e.preventDefault ) { e.preventDefault (); } else { return false; }
return true;
}
this.manageKeys = function ( code, use, killcheck ) {
var key = { 'default' :
{ 'key' : { 'backspace' : 8, 'space' : 32, 'q' : 81, 'f5' : 116 }, 'char' : { 'backspace' : 8, 'space' : 32, 'q' : 113, 'f5' : 0 } },
'browsebar' :
{ 'key' : { 'f5' : 116, 'enter' : 13 }, 'char' : { 'f5' : 0, 'enter' : 0 } },
'settings' :
{ 'key' : { 'f5' : 116 }, 'char' : { 'f5' : 0 } }
};
// the active key set
var key = key [iglooSettings.dynamicBlockKeys] [use];
if ( killcheck === true ) {
for ( var i in key ) {
if ( key [i] == code ) {
return false;
} // if exists, block
}
return true; // otherwise, don't
}
switch ( iglooSettings.dynamicBlockKeys ) {
case 'default':
switch ( code ) {
case key ['backspace']: // backspace
igloo.iglooControls.action_historyBack ();
break;
case key ['space']: // spacebar
if (typeof igloo.iglooChanges.recentChanges[0] != 'undefined') {
igloo.iglooControls.action_loadFromFeed(igloo.iglooChanges.recentChanges[0][0], igloo.iglooChanges.recentChanges[0][1], igloo.iglooChanges.recentChanges[0][2], igloo.iglooChanges.recentChanges[0][3], igloo.iglooChanges.recentChanges[0][4], igloo.iglooChanges.recentChanges[0][11]);
}
break;
case key ['q']: // q
if ( typeof igloo.iglooDiff.currentDiff[0] != 'undefined' ) {
igloo.iglooControls.action_revertDiff();
}
break;
case key ['f5']: // F5
igloo.iglooControls.getPermission ( 'You just pressed the F5 key. By default, this causes the page to refresh in most browsers. To prevent you losing your work, igloo therefore agressively blocks this key. Do you wish to reload the page?', function () { location.reload (); } );
break;
default: // if the key is unrecognised, do nothing
return true;
break;
}
break;
case 'browsebar':
switch ( code ) {
case key ['enter']: // enter
igloo.iglooControls.action_browseBarDo ();
break;
case key ['f5']: // F5
igloo.iglooControls.getPermission ( 'You just pressed the F5 key. By default, this causes the page to refresh in most browsers. To prevent you losing your work, igloo therefore agressively blocks this key. Do you wish to reload the page?', function () { location.reload (); } );
break;
default: // if the key is unrecognised, do nothing
return true;
break;
}
break;
case 'settings':
switch ( code ) {
case key ['f5']: // F5
igloo.iglooControls.getPermission ( 'You just pressed the F5 key. By default, this causes the page to refresh in most browsers. To prevent you losing your work, igloo therefore agressively blocks this key. Do you wish to reload the page?', function () { location.reload (); } );
break;
default: // if the key is unrecognised, do nothing
return true;
break;
}
break;
}
return false;
}
this.getPermission = function ( message, escalateFunction, nobuttons, owntitle ) {
this.blockActions = true;
if ( ! nobuttons ) {
var button = '<br /><br /><div style="width: 100%; text-align: center;"><span id="igloo-permission-challenge-cont" style="cursor: pointer;">continue</span> | <span id="igloo-permission-challenge-canc" style="cursor: pointer;">cancel</span></div>';
} else { var button = ''; }
if ( ! owntitle ) {
var title = 'igloo needs your permission to continue...';
} else { var title = owntitle; }
if ( ! this.userMessage ) {
this.userMessage = new wa_window ();
this.userMessage.win_alpha = 0.7;
this.userMessage.win_bg = '#000000';
this.userMessage.win_fill = true;
this.userMessage.applyAll ();
} else {
this.userMessage.show ();
}
if ( ! this.userMessageContent ) {
this.userMessageContent = new wa_window ();
this.userMessageContent.win_bg = '#ccccff';
this.userMessageContent.win_width = 500;
this.userMessageContent.win_height = 130;
this.userMessageContent.win_padding = 5;
this.userMessageContent.win_fontsize = 10;
this.userMessageContent.win_alpha = 1;
this.userMessageContent.win_bd = '2px solid #666688';
this.userMessageContent.win_content = '<div><span style="width: 100%; border-bottom: 1px solid #000;"><strong>' + title + '</strong></span><br /><div style="text-align: left; margin-left: 10px; width: 90%; color: #222222;">' + message + '</div>' + button + '</div>';
this.userMessageContent.applyAll ();
this.userMessageContent.center ( 'both', true );
} else {
this.userMessageContent.show ();
this.userMessageContent.win_content = '<div><span style="width: 100%; border-bottom: 1px solid #000;"><strong>' + title + '</strong></span><br /><div style="text-align: left; margin-left: 10px; width: 90%; color: #222222;">' + message + '</div>' + button + '</div>';
this.userMessageContent.applyAll ();
this.userMessageContent.center ( 'both', true );
}
if ( ! nobuttons ) {
document.getElementById ( 'igloo-permission-challenge-cont' ).onclick = function () { igloo.iglooControls.blockActions = false; igloo.iglooControls.userMessage.hide(); igloo.iglooControls.userMessageContent.hide(); escalateFunction(); }
document.getElementById ( 'igloo-permission-challenge-canc' ).onclick = function () { igloo.iglooControls.blockActions = false; igloo.iglooControls.userMessage.hide(); igloo.iglooControls.userMessageContent.hide(); };
}
}
this.action_historyBack = function () {
if ( igloo.iglooControls.blockActions ) return false;
igloo.iglooDiff.goBack ( 1 );
}
this.action_historyForward = function () {
if ( igloo.iglooControls.blockActions ) return false;
igloo.iglooDiff.goForward ( 1 );
}
this.action_revertDiff = function () {
if ( igloo.iglooControls.blockActions ) return false;
igloo.iglooActions.revertDiff ();
}
this.action_block = function () {
if ( igloo.iglooControls.blockActions ) return false;
iglooSettings.dynamicBlockKeys = 'settings';
var user = ( typeof igloo.iglooDiff.currentDiff [1] !== 'undefined' ) ? igloo.iglooDiff.currentDiff [1] : '';
var tb = new iglooRevert ( 0, user );
tb.blockUser ( 5 );
}
this.action_loadFromFeed = function ( a, b, c, d, e, f ) {
if ( igloo.iglooControls.blockActions ) return false;
igloo.iglooActions.reversionEnabled = 'pause';
igloo.iglooDiff.display ( a, b, c, d, e, f );
igloo.iglooChanges.markViewed ( c );
}
this.action_browseBarDo = function () {
if ( igloo.iglooControls.blockActions ) return false;
igloo.iglooActions.reversionEnabled = 'pause';
var browseTo = document.getElementById ( 'igloo-browse-to' ).value;
document.getElementById ( 'igloo-browse-to' ).value = '';
igloo.iglooDiff.display ( browseTo );
}
this.action_browseFocus = function () {
iglooSettings.dynamicBlockKeys = 'browsebar'; // stop blocking/overwriting key actions when we activate the text box
}
this.action_browseBlur = function () {
iglooSettings.dynamicBlockKeys = 'default'; // start blocking/overwriting key actions when we activate the text box
}
this.destroy = function () { // calling this will destroy the interface and connections of this object.
this.controlDisplay.hide ();
}
}
function iglooActions () {
// the iglooActions module handles the actual editing of the wiki, such as reversions and warnings
this.reversionEnabled = 'yes';
this.lastRevertedRevision = false;
this.revertedPage = false;
this.warnWho = false;
this.warningLevel = false;
this.revertDiff = function () {
this.lastRevertedRevision = igloo.iglooDiff.currentDiff [2];
var page = igloo.iglooDiff.currentDiff [0];
var user = igloo.iglooDiff.currentDiff [1];
var revid = igloo.iglooDiff.currentDiff [2];
var rev = new iglooRevert ( page, user, revid );
}
this.sendLinkToParent = function ( linkText, activateAfter ) {
if ( activateAfter == null ) activateAfter = true;
if ( ( window.opener != null ) && ( ! window.opener.closed ) ) {
window.opener.location.href = linkText;
window.opener.focus ();
return true;
}
return false;
}
this.cancelActivity = function () {
}
}
function iglooRevert ( page, user, revid ) {
var thisRevert = this;
this.revertPage = page;
this.revertUser = user;
this.revertRevid = revid;
this.performRollback = function ( callback, details ) {
switch ( callback ) {
default: case 0:
// check that reversion is switched on
if ( igloo.iglooActions.reversionEnabled == 'no' ) { alert ( 'You cannot revert this edit to ' + this.revertPage + ', because you made it using igloo' ); return false; }
if ( igloo.iglooActions.reversionEnabled == 'pause' ) { alert ( 'You cannot revert this edit to ' + this.revertPage + ', because a diff is still loading' ); return false; }
// notify user
igloo.iglooStatus.addStatus ( 'Attempting to revert the change to <strong>' + thisRevert.revertPage + '</strong> made by <strong>' + thisRevert.revertUser + '</strong>...' );
// prevent interference with this page while we are reverting it
igloo.iglooActions.reversionEnabled = 'pause';
// let the user know we're working...
document.getElementById ( 'iglooPageTitle' ).innerHTML = document.getElementById ( 'iglooPageTitle' ).innerHTML + ' - reverting edit...';
// build the reversion summary
var summary = iglooSettings.rollbackSummary;
// attempt the actual rollback
var thisReversion = new wa_mediawikiApi ();
thisReversion.onCompleteAction = function ( success ) { thisRevert.performRollback ( 1, success ); };
thisReversion.rollbackPage ( this.revertPage, this.revertUser, summary );
// mark the edit we're reverting as bad
var url = iglooSettings.remoteHost + 'main.php?action=markbad&session=' + igloo.iglooSession.session + '&me=' + encodeURIComponent ( wgUserName ) +'&user=' + this.revertUser + '&revid=' + this.revertRevid;
iglooImport ( url, true, 'iglooMark' );
break;
case 1:
if ( details == false ) {
igloo.iglooStatus.addStatus ( 'Will not revert the edit to <strong>' + thisRevert.revertPage + '</strong> by <strong>' + thisRevert.revertUser + '</strong> because another user has already done so.' );
//alert('igloo will not revert the edit to '+this.revertPage+', because another user has already done so');
if ( this.revertPage == igloo.iglooDiff.currentDiff[0] ) {
igloo.iglooDiff.display ( this.revertPage, true );
igloo.iglooActions.reversionEnabled = 'no';
}
} else {
var thisReversion = new wa_mediawikiApi ();
thisReversion.onCompleteAction = function ( data ) { thisRevert.performRollback ( 2, data ); };
thisReversion.getPage ( this.revertPage, 1, 'ids' );
}
break;
case 2:
// retrieve page ID, so we do not redisplay in the feed
igloo.iglooChanges.addToViewed ( details['page']['revisions'][0]['id'] );
if ( this.revertPage == igloo.iglooDiff.currentDiff[0] ) igloo.iglooDiff.display ( this.revertPage, wgUserName );
// notify user
igloo.iglooStatus.addStatus ( 'Successfully reverted the change to <strong>' + thisRevert.revertPage + '</strong> made by <strong>' + thisRevert.revertUser + '</strong>!' );
this.warnUser();
break;
}
}
this.warnUser = function( callback, details ) {
switch ( callback ) {
default: case 0:
// don't warn self
if ( thisRevert.revertUser == wgUserName ) break;
// notify user
igloo.iglooStatus.addStatus( 'Attempting to warn <strong>' + thisRevert.revertUser + '</strong> for vandalism on <strong>' + thisRevert.revertPage + '</strong>...' );
// get the user talk page
var getUserPage = new wa_mediawikiApi ();
getUserPage.onCompleteAction = function ( data ) { thisRevert.warnUser ( 1, data ); };
getUserPage.getPage ( 'User_talk:' + this.revertUser, 1, 'content' );
break;
case 1:
// set up the time management systems
var months = new Array ( 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' );
var currentDate = new Date ();
var currentMonth = currentDate.getMonth ();
var currentYear = currentDate.getFullYear ();
var currentTime = currentDate.getTime ();
// check for warnings on the user's talk page
var warnings = [];
// if the page already exists, we must analyse it for warnings
if ( typeof details['page']['revisions'] != 'undefined' ) {
var pageData = thisRevert.userTalk = details['page']['revisions'][0]['content'];
var regTest = /<!-- ?(?:template:?)?uw-([a-z]+?)([0-9](?:im)?)? ?-->(?:.+?([0-9]{2}):([0-9]{2}), ([0-9]{1,2}) ([a-z]+?) ([0-9]{4}))?/gi;
// get all the warnings on the page
var i = 0;
while ( true ) {
var t = regTest.exec ( pageData );
if ( t == null ) break;
warnings[i] = [];
warnings[i][0] = t[1]; // template
warnings[i][1] = t[2]; // level
warnings[i][2] = t[3]; // hour
warnings[i][3] = t[4]; // minute
warnings[i][4] = t[5]; // day
warnings[i][5] = t[6]; // month
warnings[i][6] = t[7]; // year
//alert(t[1]);
i ++;
}
// we are only interested in the latest one
if ( typeof warnings[0] == 'undefined' ) { warnings[0] = []; warnings[0][0] = false; warnings[0][1] = 0; }
var useWarning = warnings.length-1;
if ( typeof warnings[useWarning][0] === 'string' ) {
var t = warnings[useWarning][0];
if ( t.indexOf ( 'block' ) > -1 ) { useWarning --; warnings[useWarning][1] = 0; }
}
// check when this warning was given
for ( var compareMonth = 0; compareMonth < months.length; compareMonth ++ ) {
if ( months[compareMonth] == warnings[useWarning][5] ) break;
}
var compareDate = new Date ();
compareDate.setFullYear ( parseInt ( warnings[useWarning][6] ), compareMonth, parseInt ( warnings[useWarning][4] ) );
compareDate.setHours ( parseInt ( warnings[useWarning][2] ) );
compareDate.setMinutes ( parseInt ( warnings[useWarning][3] ) );
var compareTime = compareDate.getTime ();
// check if it is old enough to ignore for the purposes of incremental warnings
var timeDiff = ( currentTime + ( currentDate.getTimezoneOffset () * 60 * 1000 ) ) - compareTime;
if ( timeDiff > ( iglooSettings.warningsOldAfter * 24 * 60 * 60 * 1000 ) ) { warnings[useWarning][1] = 0; }
// check whether a header already exists for the current month. if not, create one
var currentHeader = new RegExp ( '={2,4} *' + months[currentMonth] + ' *' + currentYear + ' *={2,4}', 'gi' );
if ( currentHeader.test ( pageData ) != true ) { var header = '== '+months[currentMonth]+' '+currentYear+' =='; } else { var header = false; }
}
// if the page does not exist, we can simply set warnings at the default (lowest) levels
else {
// set up the warning and date header for addition to the user's page
warnings[0] = []; warnings[0][0] = false; warnings[0][1] = 0;
var header = '== '+months[currentMonth]+' '+currentYear+' ==';
var useWarning = 0;
}
// decide upon which warning level to issue
switch ( warnings[useWarning][1] ) {
default: case 0:
// use first level warning
this.warningLevel = 1; break;
case '1':
// use second level warning
this.warningLevel = 2; break;
case '2':
// use third level warning
this.warningLevel = 3; break;
case '3':
// use final warning
this.warningLevel = 4; break;
case '4': case '4im':
// perform report/block logic
igloo.iglooStatus.addStatus ( 'Will not warn <strong>' + thisRevert.revertUser + '</strong> because they have already recieved a final warning.' );
this.handleFinalWarning ();
this.warningLevel = false; break;
}
// add the message to their talk page
if (this.warningLevel == false) return false;
var userPage = 'User_talk:' + this.revertUser;
var message = iglooSettings.warningMessage;
message = message.replace ( /%LEVEL%/g, this.warningLevel );
message = message.replace ( /%PAGE%/g, this.revertPage );
message = message.replace ( /%DIFF%/g, mw.config.get('wgServer') + mw.config.get('wgScript') + '?diff=' + this.revertRevid + '' );
message = message.replace ( /%MESSAGE%/g, iglooSettings.vandalTemplate );
var summary = iglooSettings.warningSummary;
summary = summary.replace ( /%LEVEL%/g, this.warningLevel );
summary = summary.replace ( /%PAGE%/g, this.revertPage );
if ( header != false ) message = header + '\n' + message;
var userWarning = new wa_mediawikiApi ();
if ( iglooSettings.notifyWarningDone == true ) userWarning.onCompleteAction = function () { igloo.iglooStatus.addStatus( 'Successfully issued a level <strong>' + thisRevert.warningLevel + '</strong> warning to <strong>' + thisRevert.revertUser + '</strong> for vandalism on <strong>' + thisRevert.revertPage + '</strong>!' ); };
userWarning.editPage ( userPage, message, summary, false, 'appendtext' );
break;
case 2:
igloo.iglooStatus.addStatus ( 'Notifying <strong>' + thisRevert.revertUser + '</strong> of block (duration: ' + thisRevert.useduration + ')...' );
var message = thisRevert.usetemplate;
message = message.replace ( /%DURATION%/g, thisRevert.useduration );
message = '\n\n{{' + message + '}}';
var summary = 'Notifying user of block (['+'['+iglooSettings.localBase.substr(0, iglooSettings.localBase.length-1)+'|GLOO]'+'])';
wa ( ':api' ).edit ( 'notifyblock', 'User_talk:' + thisRevert.revertUser, 0, message, summary, 'append' ).wait ( function () {
igloo.iglooStatus.addStatus ( 'Successfully notified <strong>' + thisRevert.revertUser + '</strong> of block!' );
} ).run ();
break;
}
}
this.reportUser = function( callback, details ) {
// handle reporting of the user to AIV
//return false;
switch ( callback ) {
default: case 0:
// notify user
igloo.iglooStatus.addStatus ( 'Attempting to report <strong>' + thisRevert.revertUser + '</strong> to <strong>' + iglooSettings.aiv + '</strong> for vandalism after final warning...' );
// get the aiv page
var getAivPage = new wa_mediawikiApi ();
getAivPage.onCompleteAction = function ( data ) { thisRevert.reportUser ( 1, data ); };
getAivPage.getPage ( iglooSettings.aiv.replace ( / /g, '_' ), 1, 'content' );
break;
case 1:
// check whether they are already reported (by a human)
if ( typeof details['page']['revisions'] == 'undefined' ) {
igloo.iglooStatus.addStatus ( 'Will not report <strong>' + thisRevert.revertUser + '</strong> because the report page does not appear to exist.' );
return false; // error
}
var pageData = details['page']['revisions'][0]['content'];
if ( pageData.indexOf ( '|' + thisRevert.revertUser + '}}' ) > -1 ) {
igloo.iglooStatus.addStatus ( 'Will not report <strong>' + thisRevert.revertUser + '</strong> because they have already been reported.' );
return false; // error
}
// check bots
var getAivPage = new wa_mediawikiApi ();
getAivPage.onCompleteAction = function ( data ) { thisRevert.reportUser ( 2, data ); };
getAivPage.getPage ( iglooSettings.aiv.replace ( / /g, '_' ), 1, 'content' );
break;
case 2:
// check whether they are already reported (by a bot)
if ( typeof details['page']['revisions'] == 'undefined' ) {
igloo.iglooStatus.addStatus( 'Will not report <strong>' + thisRevert.revertUser + '</strong> because the report page does not appear to exist.' );
return false; // error
}
var pageData = details['page']['revisions'][0]['content'];
if ( pageData.indexOf ( '|' + thisRevert.revertUser + '}}' ) > -1 ) {
igloo.iglooStatus.addStatus( 'Will not report <strong>' + thisRevert.revertUser + '</strong> because they have already been reported.' );
return false; // error
}
// build page link
var aivLink = iglooSettings.aiv.replace ( / /g, '_' );
// build the report
var myReport = iglooSettings.aivMessage;
if ( thisRevert.isIp === true ) { myReport = myReport.replace ( /%TEMPLATE%/g, iglooSettings.aivIp ); } else { myReport = myReport.replace ( /%TEMPLATE%/g, iglooSettings.aivUser ); }
myReport = myReport.replace ( /%USER%/g, thisRevert.revertUser );
// build the summary
var mySummary = iglooSettings.aivSummary;
mySummary = mySummary.replace ( /%USER%/g, thisRevert.revertUser );
// perform the edit
var userReport = new wa_mediawikiApi ();
userReport.onCompleteAction = function () { igloo.iglooStatus.addStatus ( 'Successfully reported <strong>' + thisRevert.revertUser + '</strong> to AIV!' ); };
userReport.editPage ( aivLink, myReport, mySummary, false, iglooSettings.aivWhere );
break;
}
}
this.blockUser = function ( callback, details ) {
// handle blocking of users
if ( typeof thisRevert.customsettings === 'undefined' ) thisRevert.customsettings = false;
if ( iglooSettings.mesysop === false ) return false;
switch ( callback ) {
default: case 0:
// notify user
igloo.iglooStatus.addStatus( 'Attempting to block <strong>' + thisRevert.revertUser + '</strong> for vandalism after final warning...' );
// analyse user
wa ( ':api' ).command ( 'getblocks' , 'format=xml&action=query&list=logevents&letype=block&letitle=User:' + thisRevert.revertUser ).wait ( function ( details ) { thisRevert.blockUser ( 1, details ); } ).run ();
break;
case 1:
// we now have access to the talk page data and the block log - redirect depending on whether we're autoblocking or not.
if ( details ) if ( details === 'standard' ) { thisRevert.blockUser ( 5, 'userlock' ); break; }
if ( thisRevert.isIp !== true ) { thisRevert.checked = { 'auto': 'checked ','talk': '','anon': '','email': '','create': 'checked ' }; thisRevert.useduration = 'indefinite'; thisRevert.usetemplate = 'subst:uw-voablock|time=%DURATION%|sig=yes'; thisRevert.blockReason = '[[WP:Vandalism-only account|Vandalism-only account]]'; thisRevert.blockUser ( 5, 'userlock' ); break; }
thisRevert.blockUser ( 2 );
break;
case 2:
// autoblocking - decide on the best warning
// pick the best warning length
var lastlength = 'neverblocked';
thisRevert.useduration = iglooSettings.blockIncrement [ iglooSettings.blockDefault ];
if ( wa ( ':api' ).results['getblocks']['query']['logevents'] !== null ) {
if ( wa ( ':api' ).results['getblocks']['query']['logevents']['item'].length === undefined ) {
// one result
//alert('oneresult');
if ( wa ( ':api' ).results['getblocks']['query']['logevents']['item-attr']['action'] == 'block' ) {
lastlength = wa ( ':api' ).results['getblocks']['query']['logevents']['item']['block-attr']['duration'];
} else { /* use default */ }
} else {
// many results
//alert('many results');
for ( var i = 0, l = wa ( ':api' ).results['getblocks']['query']['logevents']['item-attr'].length; i < l; i ++ ) {
if ( wa ( ':api' ).results['getblocks']['query']['logevents']['item-attr'][i]['action'] == 'block' ) break;
}
if ( i === l ) { /* failed alert('faaiiilllled');*/ thisRevert.blockUser ( 5, 'error' ); return false; }
lastlength = wa ( ':api' ).results['getblocks']['query']['logevents']['item'][i]['block-attr']['duration'];
//alert('check done, ll: ' + lastlength);
}
} else { /* use default */ }
if ( lastlength !== 'neverblocked' ) {
//alert('valid last length');
var u = iglooSettings.blockIncrement.getPosition ( lastlength );
if ( u !== false ) {
if ( u < iglooSettings.blockDefault ) {
thisRevert.useduration = iglooSettings.blockIncrement [ iglooSettings.blockDefault ];
} else {
if ( u >= ( iglooSettings.blockIncrement.length - 1 ) ) u = iglooSettings.blockIncrement.length - 2;
thisRevert.useduration = iglooSettings.blockIncrement [ u + 1 ];
}
} else { /* failed */ thisRevert.blockUser ( 5, 'error' ); return false; }
}
thisRevert.lastlength = lastlength;
//alert('last length done');
thisRevert.blockReason = '[[WP:Vandalism|Vandalism]]';
// check for relevant templates on the user page
thisRevert.usetemplate = iglooSettings.blockTypes ['default'];
for ( var i in iglooSettings.blockTypes ) {
if ( typeof i !== 'string' ) continue;
var regTest = new RegExp ( '{{ *' + i, 'ig' );
if ( ( thisRevert.userTalk !== undefined ) && ( regTest.test ( thisRevert.userTalk ) === true ) && ( i !== 'default' /* just in case there's a weird default template O_o */ ) ) {
// show an error is misconfigured OR if the duration doesn't exist and hasn't caused an error yet
if ( ( iglooSettings.blockIncrement.getPosition ( thisRevert.useduration ) === false ) || ( iglooSettings.blockIncrement.getPosition ( iglooSettings.blockSpecTemp ) === false ) ) { thisRevert.blockUser ( 5, 'error' ); return false; }
if ( iglooSettings.blockIncrement.getPosition ( thisRevert.useduration ) >= iglooSettings.blockIncrement.getPosition ( iglooSettings.blockSpecTemp ) ) {
//alert('using special template!');
thisRevert.usetemplate = iglooSettings.blockTypes [i];
if ( thisRevert.usetemplate.indexOf ( '|' ) > -1 ) {
thisRevert.blockReason = '{{' + thisRevert.usetemplate.substr ( 0, thisRevert.usetemplate.indexOf ( '|' ) ) + '}}';
} else { thisRevert.blockReason = '{{' + thisRevert.usetemplate + '}}'; }
break;
} else { /*alert('NOT using special template, as the block is too short!');*/ break; }
}
}
// we now know the template to use, and we know the block length to use.
//alert ( "igloo would block this user!!!\n\nduration: " + thisRevert.useduration + "\ntemplate: " + thisRevert.usetemplate );
// manage the prompt
var message = 'This user has already received a final warning. igloo intends to block the user with the following settings:<br /><br /> ' +
'<span style="padding-left: 10px;">user: ' + thisRevert.revertUser + '<br />duration: ' + thisRevert.useduration + ' (last blocked for: ' + lastlength + ')<br />block template: ' + thisRevert.usetemplate +
'</span><br /><br /><span id="igloo-just-do-block" style="cursor: pointer;">perform this block (recommended)</span> | <span id="igloo-adjust-block" style="cursor: pointer;">adjust block settings</span> | <span id="igloo-abort-block" style="cursor: pointer;">abort block (report user)</span>'
igloo.iglooControls.getPermission ( message, false, true );
// set the functions
document.getElementById( 'igloo-just-do-block' ).onclick = function () { igloo.iglooControls.blockActions = false; igloo.iglooControls.userMessage.hide (); igloo.iglooControls.userMessageContent.hide(); thisRevert.blockUser ( 6 ); }
document.getElementById( 'igloo-adjust-block' ).onclick = function () { igloo.iglooControls.blockActions = false; igloo.iglooControls.userMessage.hide (); igloo.iglooControls.userMessageContent.hide(); thisRevert.blockUser ( 5, 'adjusting' ); igloo.iglooStatus.addStatus( 'Adjusting block of <strong>' + thisRevert.revertUser + '</strong>: launching block interface...' ); }
document.getElementById( 'igloo-abort-block' ).onclick = function () { igloo.iglooControls.blockActions = false; igloo.iglooControls.userMessage.hide (); igloo.iglooControls.userMessageContent.hide(); thisRevert.reportUser (); igloo.iglooStatus.addStatus( 'Aborted block of <strong>' + thisRevert.revertUser + '</strong>: user aborted! Will now report...' ); }
break;
case 5:
if ( details === 'error' ) {
// something went wrong. Abort and report user.
igloo.iglooStatus.addStatus ( 'Aborted block of <strong>' + thisRevert.revertUser + '</strong>: an error occurred! Will now report...' );
thisRevert.reportUser ();
break;
}
// nothing went wrong. Display the adjust block system.
// generate the dispaly elements
if ( details === 'adjusting' ) {
var disabled = 'disabled', lastlength = ' (last blocked for <strong>' + thisRevert.lastlength + '</strong>)';
thisRevert.checked = { 'auto': '','talk': '','anon': 'checked','email': '','create': 'checked' };
} else {
var disabled = '', duration = '', lastlength = '';
if ( thisRevert.revertUser == null ) thisRevert.revertUser = '';
if ( thisRevert.useduration == null ) thisRevert.useduration = '';
if ( thisRevert.usetemplate == null ) thisRevert.usetemplate = 'subst:uw-block|time=%DURATION%|sig=yes';
if ( typeof thisRevert.blockReason == 'undefined' ) thisRevert.blockReason = '[[WP:Vandalism|Vandalism]]';
}
if ( details === 'userlock' ) disabled = 'disabled';
var t = ''; // duration select
for ( var i = 0; i < iglooSettings.blockIncrement.length; i ++ ) {
t += '<option ';
if ( iglooSettings.blockIncrement [i] == thisRevert.useduration ) t += 'selected ';
t += 'value="' + iglooSettings.blockIncrement [i] + '">' + iglooSettings.blockIncrement [i] + '</option>';
}
var t2 = '';
if ( typeof thisRevert.checked === 'undefined' ) { thisRevert.checked = { 'auto': '','talk': '','anon': '','email': '','create': '' }; }
// output the display
var content = '';
content += '<div style="padding-left: 15px;"><span style="width: 100%; border-bottom: 1px solid #000; font-size: 16px; font-weight: bold;">Block user</span><br />You are blocking a user - select the block options from below. Remember that you are responsible for all blocks made using your account.';
content += '<br /><br />';
//content += '<div style="float: right; width: 200px; height: 100px;">' + t2 + '</div>';
content += '<table style="border: none; width: 700px; background-color: #ccccff;">';
content += '<tr><td width="140px">Username:</td><td><input id="iglooBlock-username" style="width: 200px;" type="text" ' + disabled + ' value="' + thisRevert.revertUser + '" />' + lastlength + '</td></tr>';
content += '<tr><td width="140px">Duration:</td><td><select style="width: 205px;" id="iglooBlock-duration-a">' + t + '</select> (or type) <input id="iglooBlock-duration-b" style="width: 200px;" type="text" /></td></tr>';
content += '<tr><td width="140px">Reason:</td><td><input id="iglooBlock-reason" style="width: 200px;" type="text" value="' + thisRevert.blockReason + '" /></td></tr>';
content += '<tr><td width="140px">Notify with template (igloo will automatically add \'{{\' and \'}}\'): </td><td><input id="iglooBlock-template" style="width: 200px;" type="text" value="' + thisRevert.usetemplate + '" /></td></tr>';
content += '<tr><td colspan="2" height="30px" style="margin-top: 30px; font-weight: bold;">Details:</td></tr>';
content += '<tr><td colspan="2">';
content += '<table width="150px" style="margin-left: 10px; background-color: #ccccff;"><tr>';
content += '<td width="120px">Autoblock: </td><td><input ' + thisRevert.checked ['auto'] + ' id="iglooBlock-autoblock" type="checkbox" /></td></tr><tr><td width="120px">Anon only: </td><td><input ' + thisRevert.checked ['anon'] + ' id="iglooBlock-anononly" type="checkbox" /></td></tr><tr><td width="120px">Block acc create: </td><td><input ' + thisRevert.checked ['create'] + ' id="iglooBlock-blockcreate" type="checkbox" /></td></tr><tr>';
content += '<td width="120px">Block talk: </td><td><input ' + thisRevert.checked ['talk'] + ' id="iglooBlock-blocktalk" type="checkbox" /></td></tr><tr><td width="120px">Block email: </td><td><input ' + thisRevert.checked ['email'] + ' id="iglooBlock-blockemail" type="checkbox" /></td>';
content += '</tr></table>';
content += '</td></tr>';
content += '<tr><td colspan="2" height="50px" style="margin-top: 50px; font-weight: bold;"><input id="igloo-finish-block" type="button" value="Block" onclick="igloo.iglooPopup.hide(); iglooSettings.dynamicBlockKeys = \'default\';" /> | <input type="button" value="Cancel" onclick="igloo.iglooPopup.hide(); iglooSettings.dynamicBlockKeys = \'default\';" /></td></tr>';
content += '</table></span>';
igloo.iglooPopup.show ( content );
wa_attach ( document.getElementById ( 'igloo-finish-block' ), 'click', function () {
// set settings
if ( document.getElementById ( 'iglooBlock-duration-b' ).value === '' ) { thisRevert.useduration = document.getElementById ( 'iglooBlock-duration-a' ).value; } else { thisRevert.useduration = document.getElementById ( 'iglooBlock-duration-b' ).value; }
thisRevert.revertUser = document.getElementById ( 'iglooBlock-username' ).value;
thisRevert.usetemplate = document.getElementById ( 'iglooBlock-template' ).value;
thisRevert.blockReason = document.getElementById ( 'iglooBlock-reason' ).value;
thisRevert.customsettings = '';
if ( document.getElementById ( 'iglooBlock-autoblock' ).checked == true ) thisRevert.customsettings += '&autoblock=';
if ( document.getElementById ( 'iglooBlock-blocktalk' ).checked != true ) thisRevert.customsettings += '&allowusertalk=';
if ( document.getElementById ( 'iglooBlock-anononly' ).checked == true ) thisRevert.customsettings += '&anononly=';
if ( document.getElementById ( 'iglooBlock-blockemail' ).checked == true ) thisRevert.customsettings += '&noemail=';
if ( document.getElementById ( 'iglooBlock-blockcreate' ).checked == true ) thisRevert.customsettings += '&nocreate=';
thisRevert.blockUser ( 6 );
return true; // done!
} );
break;
case 6:
// DO THE BLOCK! Note that this function can be called even without reverting any page.
if ( ( ! thisRevert.useduration ) || ( ! thisRevert.usetemplate ) || ( ! thisRevert.revertUser ) ) { if ( ! thisRevert.revertUser ) thisRevert.revertUser = 'no user supplied'; igloo.iglooStatus.addStatus( 'Aborted block of <strong>' + thisRevert.revertUser + '</strong>: an error occurred!' ); return false; }
//alert (thisRevert.customsettings);
if ( thisRevert.customsettings === false ) { // the block 'settings' haven't been altered (e.g. autoblock, block talk etc.), so use the default block settings.
thisRevert.customsettings = ( thisRevert.isIp === true ) ? iglooSettings.anonBlockSettings : iglooSettings.userBlockSettings;
}
// do the actual block!
igloo.iglooStatus.addStatus( 'Performing block of <strong>' + thisRevert.revertUser + '</strong>...' );
wa ( ':api' ).block ( 'ig_doblock', thisRevert.revertUser, 0, thisRevert.useduration, thisRevert.blockReason, thisRevert.customsettings ).wait ( function () {
var result = wa ( ':api' ).results['ig_doblock'];
if ( typeof result['block'] !== 'undefined' ) { // success
igloo.iglooStatus.addStatus( 'Successfully blocked <strong>' + thisRevert.revertUser + '</strong>!' );
thisRevert.warnUser ( 2 );
} else { // failure
igloo.iglooStatus.addStatus( 'Failed to block <strong>' + thisRevert.revertUser + '</strong> - reason: ' + result['error']['info'] );
return false;
}
}).run ();
return true;
break;
}
}
this.handleFinalWarning = function ( callback ) {
// this helper function is called when a user who already has a final warning is reverted. It decides what to do based on the user settings, and
// is able to prompt for input if it is unsure.
switch ( callback ) {
default: case 0:
// If we reach a final warning, remember that no further action is required if the user is already blocked!
wa ( ':api' ).command ( 'currentlyblocked' , 'format=xml&action=query&list=blocks&bkusers=' + thisRevert.revertUser ).wait ( function () { thisRevert.handleFinalWarning ( 1 ); } ).run ();
break;
case 1:
// If already blocked, tell and exit.
if ( wa ( ':api' ).results['currentlyblocked']['query']['blocks'] !== null ) {
igloo.iglooStatus.addStatus( 'igloo will take no further action because <strong>' + thisRevert.revertUser + '</strong> is currently blocked.' );
return false;
}
// If you're not an admin, igloo won't let you choose. :) Also report if that's the preferred setting.
if ( ( iglooSettings.mesysop === false ) || ( iglooSettings.blockAction === 'report' ) ) { thisRevert.reportUser (); return true; }
// handle settings
if ( iglooSettings.blockAction === 'prompt' ) {
iglooSettings.blockAction = 'report'; // temporarily, so we don't see this screen again this session
// manage the prompt
var title = 'igloo needs you to choose your block settings';
var message = 'Because you are an administrator, igloo can automatically block users on your behalf when you revert someone who has received a final warning. ' +
'The igloo autoblocker will automatically choose and block with the most appropriate settings based on the user in question (you will still be prompted for permission to continue). ' +
'If you want more control, the standard block setting will show you relevant data about the user and allow you to make the block yourself. Alternatively, igloo can simply report the user to AIV. What do you want to do?<br /><br />' +
'>> <span id="igloo-set-block-auto" style="cursor: pointer;">igloo autoblock (recommended)</span> | <span id="igloo-set-block-standard" style="cursor: pointer;">standard block</span> | <span id="igloo-set-block-report" style="cursor: pointer;">report</span>'
igloo.iglooControls.getPermission ( message, false, true, title );
// set the functions
document.getElementById( 'igloo-set-block-auto' ).onclick = function () { igloo.iglooControls.blockActions = false; igloo.iglooControls.userMessage.hide (); igloo.iglooControls.userMessageContent.hide(); thisRevert.blockUser (); iglooSettings.blockAction = 'auto'; var url = iglooSettings.remoteHost + 'main.php?action=settings&do=set&session=' + igloo.iglooSession.session + '&me=' + encodeURIComponent ( wgUserName ) + '&setting=blockAction&value=auto'; iglooImport( url, true, 'iglooSettings' ); }
document.getElementById( 'igloo-set-block-standard' ).onclick = function () { igloo.iglooControls.blockActions = false; igloo.iglooControls.userMessage.hide (); igloo.iglooControls.userMessageContent.hide(); thisRevert.blockUser ( 0, 'standard' ); iglooSettings.blockAction = 'standard'; var url = iglooSettings.remoteHost + 'main.php?action=settings&do=set&session=' + igloo.iglooSession.session + '&me=' + encodeURIComponent ( wgUserName ) + '&setting=blockAction&value=standard'; iglooImport( url, true, 'iglooSettings' ); }
document.getElementById( 'igloo-set-block-report' ).onclick = function () { igloo.iglooControls.blockActions = false; igloo.iglooControls.userMessage.hide (); igloo.iglooControls.userMessageContent.hide(); thisRevert.reportUser (); iglooSettings.blockAction = 'report'; var url = iglooSettings.remoteHost + 'main.php?action=settings&do=set&session=' + igloo.iglooSession.session + '&me=' + encodeURIComponent ( wgUserName ) + '&setting=blockAction&value=report'; iglooImport( url, true, 'iglooSettings' ); }
} else if ( iglooSettings.blockAction === 'standard' ) {
this.blockUser ( 0, 'standard' ); return true;
} else if ( iglooSettings.blockAction === 'auto' ) {
this.blockUser (); return true;
}
return false;
break;
}
}
// score object
var userScore = igloo.iglooNet.scoreObject ( this.revertUser );
// check whether this user is an IP address, or a registered user
if ( this.revertUser.match ( /^[0-9]+\.[0-9]+\.[0-9]+\.?[0-9]*$/i ) !== null ) { this.isIp = true; this.checked = { 'auto': '','talk': '','anon': 'checked','email': '','create': 'checked' }; } else { this.isIp = false; this.checked = { 'auto': 'checked','talk': '','anon': '','email': '','create': 'checked' }; }
// if we're using this for blocking, for example, don't perform default actions
if ( this.revertPage === 0 ) return true;
// checks
if ( userScore[0] === false ) userScore[0] = iglooSettings.defaultUserScore;
if ( ( this.revertUser == wgUserName ) && ( iglooSettings.promptRevertSelf === true ) ) {
igloo.iglooControls.getPermission ( 'You are attempting to revert yourself. Ensure you wish to perform this action. igloo will not warn or report users who are reverting themselves.', function ( thisRevert ) { thisRevert.performRollback ( 0, 'cont' ); } );
} else if ( userScore[0] < 0.4 ) {
igloo.iglooControls.getPermission ( 'You are attempting to revert a change that iglooNet believes is free from vandalism. Remember that igloo should only be used to revert <strong>blatant</strong> vandalism.', function ( page, user ) { thisRevert.performRollback ( page, user ); } );
} else if ( igloo.iglooDiff.haschanged === true ) {
igloo.iglooControls.getPermission ( 'The page you are viewing has changed since it was first loaded. Ensure that the change you were reverting has not already been fixed.', function ( page, user ) { thisRevert.performRollback ( page, user ); } );
} else { this.performRollback ( page, this.revertUser ); }
}
function iglooPopup () {
// igloo popup handles the general background interace for internal windows, such as the settings window, block adjustment window, custom warnings window, deletion window etc.
this.start = function () {
this.popupMenu = new wa_window ();
this.popupMenu.win_alpha = 0.7;
this.popupMenu.win_bg = '#000000';
this.popupMenu.win_disp = 'none';
this.popupMenu.win_maintfill = false;
this.popupMenu.win_fill = true;
this.popupMenu.applyAll ();
if ( igloo.canDebug === true ) console.log ( 'igloo: created popup background' );
this.popupMenuContent = new wa_window ();
this.popupMenuContent.win_bg = '#ccccff';
this.popupMenuContent.win_width = 800;
this.popupMenuContent.win_height = 400;
this.popupMenuContent.win_padding = 0;
this.popupMenuContent.win_disp = 'none';
this.popupMenuContent.win_bd = '#000000';
this.popupMenuContent.win_bd_wd = 2;
this.popupMenuContent.win_content = '<div>POPUP INIT</div>';
this.popupMenuContent.applyAll ();
if ( igloo.canDebug === true ) console.log ( 'igloo: created popup main' );
return true;
}
this.show = function ( content ) {
if ( content !== null ) {
// content
this.popupMenuContent.win_content = '<div>' + content + '</div>';
this.popupMenuContent.applyAll ();
}
// show
this.popupMenu.show ();
this.popupMenuContent.show ();
// center
this.popupMenuContent.center ( 'both' );
}
this.hide = function () {
this.popupMenu.hide ();
this.popupMenuContent.hide ();
}
}
function iglooStatus () {
// the iglooStatus module handles the display and updating of the status window where we keep track of the actions we've taken for the user
this.idCounter = 1;
this.start = function() {
this.startInterface();
}
this.startInterface = function() {
var iglooCount = igloo.iglooNet.iglooCount;
var iglooLoadTime = igloo.endload - igloo.startload;
if ( iglooSettings.lastConnectIp !== 0 ) { var iglooLastConnection = 'You last connected from ' + iglooSettings.lastConnectIp + ', ' + iglooSettings.lastConnectTime; } else { var iglooLastConnection = ''; }
this.intDisplay = new wa_window(igloo.iglooInterface);
this.intDisplay.win_left = 190;
this.intDisplay.win_top = parseInt(igloo.iglooInterface.win_obj.style.height) - 150;
this.intDisplay.win_width = parseInt(igloo.iglooInterface.win_obj.style.width) - 200;
this.intDisplay.win_height= 140;
this.intDisplay.win_bg = '#ddddee'; // #'ededff';
this.intDisplay.win_bd_tp = '1px solid #000000'; this.intDisplay.win_bd_lf = '1px solid #000000';
this.intDisplay.win_padding = 5;
this.intDisplay.win_content = '<div id="iglooStatusDisplay" style="width: 100%; height: 100%; overflow: auto; font-size: 12px;"><div id="statusObj_0" class="statusObj">Welcome to igloo! This is your status window, where you see the actions that igloo is taking on your behalf.<br /> <strong>stats:</strong> iglooNet currently has data on ' + iglooCount + ' unique entities.<br /> <strong>stats:</strong> igloo loaded in: ' + ( iglooLoadTime / 1000 ) + ' seconds.<br /> <strong>stats:</strong> ' + iglooLastConnection + '</div></div>'; //
this.intDisplay.applyAll();
}
this.destroy = function() {
this.intDisplay.hide();
}
this.addStatus = function(message) {
var curDate = new Date();
var sec = curDate.getSeconds();
if ( sec < 10 ) sec = '0' + sec;
var mins = curDate.getMinutes();
if ( mins < 10 ) mins = '0' + mins;
var hours = curDate.getHours();
if ( hours < 10 ) hours = '0' + hours;
var dateString = hours + ':' + mins + ':' + sec;
var statusId = this.idCounter; this.idCounter ++;
var newStatus = document.createElement('div');
newStatus.id = 'statusObj_' + statusId;
newStatus.className = 'statusObj';
newStatus.innerHTML = '<span>' + dateString + ' - ' + message + '</span>';
//var newStatusText = document.createTextNode(dateString + ' - ' + message);
//newStatus.appendChild(newStatusText);
var statusObj = document.getElementById('iglooStatusDisplay');
statusObj.insertBefore(newStatus, statusObj.firstChild);
return statusId;
}
this.updateStatus = function(id, message, action) { // action = 'append', 'prepend', 'overwrite' or 'destroy' - default 'append'
if (document.getElementById('statusObj_' + id)) { var statusObj = document.getElementById('statusObj_' + id); } else { return false; }
switch (action) {
default: case 'append':
statusObj.innerHTML = statusObj.innerHTML + message;
return statusObj.innerHTML;
break;
case 'prepend':
statusObj.innerHTML = message + statusObj.innerHTML ;
return statusObj.innerHTML;
break;
case 'overwrite':
statusObj.innerHTML = message;
return statusObj.innerHTML;
break;
case 'destroy':
statusObj.parentElement.removeChild(statusObj);
return true;
break;
}
}
}
// launch!
var igloo = new iglooMain();
igloo.launch();
// </nowiki>