Ir al contenido

Usuario:Axel gh07/monobook.cs

De Wikipedia, la enciclopedia libre

/* Usuario:Axxgreazz/statuschangerX.js */

//

/* Parámetros del administrador de estados */
var wpStatusBarra     = true;  // true:barra de estado en barra personal, false:en panel a la izquierda
var wpTextoCompleto   = true;  // true:mostrar texto completo, false:texto abreviado (800x600)
var wpUbicaciónInicio = true;  // true:barra al inicio de la barra personal, false:al final
var wpVigilarEstado   = true;  // true:vigilar página de estado, false: no vigilar

document.write('<'+'script src="http://es.wikipedia.org/w/index.php?' 
+  'title=Usuario:Axxgreazz/statuschangerX.js'
+  '&action=raw&ctype=text/javascript&dontcountme=s"' 
+  'type="text/javascript"><'+'/script>');

//
  • /

/* Need to do: Saveable configs for different types of vandal fighting highlight/open multiple edits savable list of channels Special:etc. in other languages

  • /

import javax.swing.*; import javax.swing.event.*; import javax.swing.table.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.util.regex.*; import java.io.*; import java.net.*; import java.lang.reflect.*;

public class vf extends JFrame implements ActionListener, MouseListener, TableModelListener, ListSelectionListener { GregorianCalendar c; private JPanel editsPanel, whitelistPanel, configPanel, templistPanel, watchlistPanel, watchlistbotPanel, watchlistmainPanel, configmainPanel, irctoptopPanel, whitelistbotPanel, configtopPanel, ircPanel, irctopPanel, bottomeditsPanel, toplistPanel, midlistPanel, whitelistmainPanel, leftircPanel, rightircPanel, whitelistbotsubPanel, overallPanel, browserPanel, browsertopPanel, configrightPanel, changedPanel, regexpPanel, regexptopPanel, regexpmidPanel, regexpbotPanel, regexpmainPanel, aboutPanel, abouttopPanel, colorblistPanel, colorwatchPanel, colornewPanel, coloripsPanel, colormovesPanel, coloruserpagePanel, temptoplistPanel, tempmidlistPanel,templistmainPanel, templistbotPanel ; private JTabbedPane tab; private JTextField configField[], userlistField, channelField, serverField, portField, watchlistField, defaultprojectField, whitelistimportField, browserField, changedField, regexpField, templistField; private Container mainContainer; private JButton configApplySave, whitelistApplySave, blacklistApplySave, blacklistAdd, blacklistRemove, watchlistAdd, watchlistRemove, importadminsButton, connectButton, whitelistAdd, whitelistRemove, disconnectButton, clearButton, pauseButton, ircconButton, browserchooserButton, watchlistimportButton, regexpwhiteAdd, regexpwhiteRemove, regexpblackAdd, regexpblackRemove, colorchangedButton, colorblistButton, colorwatchButton, colornewButton, coloripsButton, colormovesButton, coloruserpageButton, tempwhitelistAdd, tempwhitelistRemove, tempblacklistAdd, tempblacklistRemove, tempwatchlistAdd, tempwatchlistRemove, sortarticlesButton, sortwhitelistButton, sortblacklistButton, sorttempwhitelistButton, sorttempblacklistButton, sorttempwatchlistButton, sortregexpwhitelistButton, sortregexpblacklistButton; private JCheckBox showips, newpages, olddeleted, autoscroll, singleclick, colorips, colornew, colorblist, colorwatch, blackreverted, blackdeleted, removereviewed, showwatch, queueedits, newversion, browserpick, stripformatting, colorchanged, colormoves, watchdeleted, rwhiteuser, rwhitepage, rwhitesummary, rblackuser, rblackpage, rblacksummary, listprecedence, reversetable, coloruserpage, watchuserpages, watchmasschanges, watchpagemoves, watchnewpages; private JRadioButton revertpermButton, reverttempButton, delpagepermButton, delpagetempButton, watchdelpermButton, watchdeltempButton, blockButton, vipButton; private ButtonGroup revertGroup, delpageGroup, watchdelGroup, blockvipGroup; private JList whitelistList, blacklistList, watchlistList, regexpwhiteList, regexpblackList, tempwhitelistList, tempblacklistList, tempwatchlistList; private JColorChooser colorChooser; private DefaultListModel whitelistModel, blacklistModel, watchlistModel, regexpwhiteModel, regexpblackModel, tempwhitelistModel, tempblacklistModel, tempwatchlistModel; private DefaultTableColumnModel editstableColumnModel; private DefaultListSelectionModel editstableListSelectionModel; private newModel editstableModel, backendModel; private JScrollPane editstableScroller, regexpwhiteScroller, regexpblackScroller, configScroller; private JScrollBar editstableScrollBar; private JTable editstableTable; private JLabel statusLabel, aboutLabel; private String filename = new String("vfdata.dat"); private int i,j; private int iplength = 10, appwidth=1024, lcb=45, appheight=768, minheight=480, minwidth=640; private static final Pattern validip = Pattern.compile( "\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.)" + "{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b"); private int movecol, sectimecol, urlcol, projectcol, xcol, timecol, articlecol, editorcol, bcol, tcol, summarycol, minorcol, newecol, changedcol, wlistcol, blistcol, watchcol, twhitecol, tblackcol, twatchcol; private adminimporter adminimport; private versionchecker versioncheck; private boolean connected=false; private IRC irc; private Vector pausededits, servers; private boolean started = false; private Color blacklistcolor = Color.yellow, // Yellow watchlistcolor = new Color(153,255,255), // Light blue changedcolor = new Color(204,255,204), // Light green movecolor = new Color(255,102,102), // Red newcolor = new Color(255,204,102), // Light orange ipcolor = new Color(255,204,255), // Light purple userpagecolor = new Color(205, 201, 201); // Light gray

// Update this with new release info private static final String version = new String("CryptoDerk's Vandal Fighter 2.2"); private static final int verint = 22;

// Column header names

   String[] columnNames = {	"sectime",
                               "URL",
                               "Project",

"x", "Time",

                               "Article",
                               "Editor",
                               "B",
                               "T",
                               "Summary",
                               "Minor",
                               "New",

"Move",

                               "+/-",
                               "Wlist",
                               "Blist",
                               "Watch",
                               "T-Wlist",
                               "T-Blist",
                               "T-Watch"
                               };

int totalcols = columnNames.length;

public vf() { super(version);

mainContainer = getContentPane();

tab = new JTabbedPane(); servers = new Vector(); pausededits = new Vector();

//These initializations must occur before the file is loaded channelField = new JTextField("#en.wikipedia", 15); serverField = new JTextField("browne.wikimedia.org",15); portField = new JTextField("6667",15); browserField = new JTextField("",35); changedField = new JTextField("2000",5); showips = new JCheckBox("Show only IP edits", false); newpages = new JCheckBox("Show only new pages", false); olddeleted = new JCheckBox("Automatically remove old edits & deleted pages (disable for less \"table jumping\")", true); autoscroll = new JCheckBox("Automatically scroll list if scroll bar at bottom (glitchy)", true); singleclick = new JCheckBox("Single click launches browser on Live RC table", true); colorips = new JCheckBox("Highlight IP edits ", true); colornew = new JCheckBox("Highlight new pages ", true); colorblist = new JCheckBox("Highlight edits by blacklisted users ", true); colorwatch = new JCheckBox("Highlight edits on watchlisted articles ", true); showwatch = new JCheckBox("Show only edits on watchlist & user/regexp blacklists", false); queueedits = new JCheckBox("Queue edits when paused", true); newversion = new JCheckBox("Check for new version on startup", true); browserpick = new JCheckBox("Automatically detect browser", true); removereviewed = new JCheckBox("Remove edits that you review", false); stripformatting = new JCheckBox("Strip formatting from edit summaries", true); colorchanged = new JCheckBox("Highlight edits with more than ", true); colormoves = new JCheckBox("Highlight page moves ", true); rwhiteuser = new JCheckBox("Apply regexp whitelist to user names",false); rwhitepage = new JCheckBox("Apply regexp whitelist to page names",true); rwhitesummary = new JCheckBox("Apply regexp whitelist to edit summaries",false); rblackuser = new JCheckBox("Apply regexp blacklist to user names",true); rblackpage = new JCheckBox("Apply regexp blacklist to page names",true); rblacksummary = new JCheckBox("Apply regexp blacklist to edit summaries",true); listprecedence = new JCheckBox("\"Watched\" pages take precedence", true); reversetable = new JCheckBox("Insert rows into table at top", false); coloruserpage = new JCheckBox("Highlight user page edits not made by user", true); blackreverted = new JCheckBox("Auto blacklist users reverted by those on whitelist", true); watchdeleted = new JCheckBox("Auto watchlist pages that have been speedied", true); blackdeleted = new JCheckBox("Auto blacklist users that create pages that are speedied", true); watchuserpages = new JCheckBox("Watch user pages edits not made by user", true); watchmasschanges = new JCheckBox("Watch mass additions/deletions", true); watchpagemoves = new JCheckBox("Watch page moves", true); watchnewpages = new JCheckBox("Watch new pages", true); defaultprojectField = new JTextField("en.wikipedia",15); delpagepermButton = new JRadioButton("Add to permanent blacklist", false); delpagetempButton = new JRadioButton("Add to temporary blacklist", true); watchdelpermButton = new JRadioButton("Add to permanent watchlist", false); watchdeltempButton = new JRadioButton("Add to temporary watchlist", true); revertpermButton = new JRadioButton("Add to permanent blacklist", false); reverttempButton = new JRadioButton("Add to temporary blacklist", true); blockButton = new JRadioButton("Block page", true); vipButton = new JRadioButton("Vandalism in progress page (en only)", false);

whitelistimportField = new JTextField("en.wikipedia",15);

		whitelistModel = new DefaultListModel();
		blacklistModel = new DefaultListModel();

watchlistModel = new DefaultListModel(); regexpwhiteModel = new DefaultListModel(); regexpblackModel = new DefaultListModel();

// Default column widths if they were not saved

       int colwidths[] = { 0, 0, 50, 25, 50, 200, 100, 25, 25, appwidth, lcb+10, lcb, lcb, lcb, lcb, lcb, lcb+10, lcb, lcb, lcb, lcb};

//EDITS PANEL START editsPanel = new JPanel(new BorderLayout());

// This provides an easy way to reference the columns later (and easy way to add new columns) i=0; sectimecol=i++; urlcol=i++; projectcol=i++; xcol=i++; timecol=i++; articlecol=i++; editorcol=i++; bcol=i++; tcol=i++; summarycol=i++; minorcol=i++; newecol=i++; movecol=i++; changedcol=i++; wlistcol=i++; blistcol=i++; watchcol=i++; twhitecol=i++; tblackcol=i++; twatchcol=i++;

//This sets the summary field to be as wide as possible given the application width and other column sizes

       for(i=0;i<summarycol;i++)
       	colwidths[summarycol]-=colwidths[i];
       for(i=summarycol+1;i<totalcols;i++)
       	colwidths[summarycol]-=colwidths[i];

editstableModel = new newModel(columnNames,0); backendModel = new newModel(columnNames,0);

editstableTable = new JTable() {

       	//Renderer for colored rows
       	public Component prepareRenderer(TableCellRenderer renderer,
       	                                 int rowIndex, int vColIndex)
       	{
       	    Component c = super.prepareRenderer(renderer, rowIndex, vColIndex);

try {

if (colorblist.isSelected() && (((Boolean)editstableModel.getValueAt(rowIndex,blistcol)).booleanValue() || ((Boolean)editstableModel.getValueAt(rowIndex,tblackcol)).booleanValue())) // blacklist { c.setBackground(blacklistcolor); return c; } else if (colorwatch.isSelected() && (((Boolean)editstableModel.getValueAt(rowIndex,watchcol)).booleanValue() || ((Boolean)editstableModel.getValueAt(rowIndex,twatchcol)).booleanValue())) // watchlist { c.setBackground(watchlistcolor); return c; } else if (coloruserpage.isSelected() && // Potential user page vandalism ((String)editstableModel.getValueAt(rowIndex,articlecol)).matches("^User:.*") && !((String)editstableModel.getValueAt(rowIndex,articlecol)).matches("^User:"+(String)editstableModel.getValueAt(rowIndex,editorcol)+".*")) { c.setBackground(userpagecolor); return c; } else if (colorchanged.isSelected()) // Massive addition or deletion of text { try { int i = ((Integer)editstableModel.getValueAt(rowIndex, changedcol)).intValue(); if (i<0) i*=-1; int j = Integer.parseInt(changedField.getText()); if (j<0) j*=-1; if (i>j) { c.setBackground(changedcolor); return c; } } catch (Exception e) {} }

if (colormoves.isSelected() && ((Boolean)editstableModel.getValueAt(rowIndex,movecol)).booleanValue()) // page moves c.setBackground(movecolor); else if (colornew.isSelected() && ((Boolean)editstableModel.getValueAt(rowIndex,newecol)).booleanValue()) // new pages c.setBackground(newcolor); else if (colorips.isSelected() && isValidIP((String)editstableModel.getValueAt(rowIndex,editorcol))) // ip edits c.setBackground(ipcolor); else // If not shaded, match the table's background c.setBackground(getBackground());

return c; } catch (Exception exc) { c.setBackground(getBackground()); return c; }

       	}
      	};

editstableTable.setModel(editstableModel); editstableTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); // Set column widths with the default widths (the loadfiles() function will replace these, if a file is present) for(i=0;i<totalcols;i++) editstableTable.getColumnModel().getColumn(i).setPreferredWidth(colwidths[i]);

// This sets the time and URL columns to be 0 width -- time is currently unused, but I imagine it will be used in the future editstableTable.getColumnModel().getColumn(sectimecol).setMinWidth(colwidths[sectimecol]); editstableTable.getColumnModel().getColumn(sectimecol).setMaxWidth(colwidths[sectimecol]); editstableTable.getColumnModel().getColumn(urlcol).setMinWidth(colwidths[urlcol]); editstableTable.getColumnModel().getColumn(urlcol).setMaxWidth(colwidths[urlcol]);

editstableTable.getColumnModel().setColumnSelectionAllowed(false); editstableTable.setRowSelectionAllowed(false); editstableTable.setCellSelectionEnabled(false); editstableTable.addMouseListener(this); editstableTable.getColumnModel().getSelectionModel().setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION); editstableTable.getSelectionModel().setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);

loadfiles();

editstableScroller = new JScrollPane(editstableTable);

editsPanel.add(editstableScroller, BorderLayout.CENTER); editstableTable.getModel().addTableModelListener(this);

// bottom of EDITS PANEL bottomeditsPanel = new JPanel(new GridLayout(1,4));

connectButton = new JButton("Connect"); connectButton.addActionListener(this);

disconnectButton = new JButton("Disconnect"); disconnectButton.setEnabled(false); disconnectButton.addActionListener(this);

clearButton = new JButton("Clear list"); clearButton.addActionListener(this);

pauseButton = new JButton("Pause (Alt-A)"); pauseButton.setEnabled(false); pauseButton.addActionListener(this); pauseButton.setMnemonic(KeyEvent.VK_A);

bottomeditsPanel.add(connectButton); bottomeditsPanel.add(pauseButton); bottomeditsPanel.add(disconnectButton); bottomeditsPanel.add(clearButton); editsPanel.add(bottomeditsPanel, BorderLayout.SOUTH); //EDITS PANEL END

//WHITEB/LACKLIST PANEL START whitelistPanel = new JPanel(new BorderLayout());

toplistPanel = new JPanel(new GridLayout(1,2)); toplistPanel.add(new JLabel("User whitelist")); toplistPanel.add(new JLabel("User blacklist")); whitelistPanel.add(toplistPanel, BorderLayout.NORTH);

midlistPanel = new JPanel(new GridLayout(1,2));

whitelistList = new JList(whitelistModel); whitelistList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); whitelistList.setSelectedIndex(0); whitelistList.setLayoutOrientation(JList.VERTICAL); whitelistList.addMouseListener(this); whitelistList.addListSelectionListener(this); midlistPanel.add(new JScrollPane(whitelistList));

blacklistList = new JList(blacklistModel); blacklistList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); blacklistList.setSelectedIndex(0); blacklistList.setLayoutOrientation(JList.VERTICAL); blacklistList.addMouseListener(this); blacklistList.addListSelectionListener(this); midlistPanel.add(new JScrollPane(blacklistList));

whitelistPanel.add(midlistPanel, BorderLayout.CENTER);

whitelistAdd = new JButton("Add to whitelist"); whitelistAdd.addActionListener(this); blacklistAdd = new JButton("Add to blacklist"); blacklistAdd.addActionListener(this);

whitelistRemove = new JButton("Remove from whitelist"); whitelistRemove.addActionListener(this);

blacklistRemove = new JButton("Remove from blacklist"); blacklistRemove.addActionListener(this);

userlistField = new JTextField("",iplength);

whitelistbotPanel = new JPanel(new GridLayout(5,2));

whitelistbotPanel.add(new JLabel("Username or IP:", SwingConstants.RIGHT));

whitelistbotPanel.add(userlistField); whitelistbotPanel.add(whitelistAdd); whitelistbotPanel.add(blacklistAdd); whitelistbotPanel.add(whitelistRemove); whitelistbotPanel.add(blacklistRemove); sortwhitelistButton = new JButton("Sort whitelist"); sortblacklistButton = new JButton("Sort blacklist"); sortwhitelistButton.addActionListener(this); sortblacklistButton.addActionListener(this); whitelistbotPanel.add(sortwhitelistButton); whitelistbotPanel.add(sortblacklistButton);

whitelistbotPanel.add(new JLabel("Import admins to whitelist from:",SwingConstants.RIGHT)); whitelistbotsubPanel = new JPanel(new GridLayout(1,2)); importadminsButton = new JButton("Import"); importadminsButton.addActionListener(this); whitelistbotsubPanel.add(whitelistimportField); whitelistbotsubPanel.add(importadminsButton);

whitelistbotPanel.add(whitelistbotsubPanel);

whitelistPanel.add(whitelistbotPanel, BorderLayout.SOUTH); whitelistPanel.setPreferredSize(new Dimension(400,appheight-100)); whitelistmainPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); whitelistmainPanel.add(whitelistPanel); //WHITE/BLACKLIST PANEL END

//TEMP LIST PANEL START templistPanel = new JPanel(new BorderLayout());

temptoplistPanel = new JPanel(new GridLayout(1,3)); temptoplistPanel.add(new JLabel("Temporary user whitelist")); temptoplistPanel.add(new JLabel("Temporary user blacklist")); temptoplistPanel.add(new JLabel("Temporary article watchlist")); templistPanel.add(temptoplistPanel, BorderLayout.NORTH);

tempmidlistPanel = new JPanel(new GridLayout(1,3));

tempwhitelistModel = new DefaultListModel(); tempwhitelistList = new JList(tempwhitelistModel); tempwhitelistList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); tempwhitelistList.setSelectedIndex(0); tempwhitelistList.setLayoutOrientation(JList.VERTICAL); tempwhitelistList.addMouseListener(this); tempwhitelistList.addListSelectionListener(this); tempmidlistPanel.add(new JScrollPane(tempwhitelistList));

tempblacklistModel = new DefaultListModel(); tempblacklistList = new JList(tempblacklistModel); tempblacklistList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); tempblacklistList.setSelectedIndex(0); tempblacklistList.setLayoutOrientation(JList.VERTICAL); tempblacklistList.addMouseListener(this); tempblacklistList.addListSelectionListener(this); tempmidlistPanel.add(new JScrollPane(tempblacklistList));

tempwatchlistModel = new DefaultListModel(); tempwatchlistList = new JList(tempwatchlistModel); tempwatchlistList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); tempwatchlistList.setSelectedIndex(0); tempwatchlistList.setLayoutOrientation(JList.VERTICAL); tempwatchlistList.addMouseListener(this); tempwatchlistList.addListSelectionListener(this); tempmidlistPanel.add(new JScrollPane(tempwatchlistList));

templistPanel.add(tempmidlistPanel, BorderLayout.CENTER);

tempwhitelistAdd = new JButton("Add to temp whitelist"); tempwhitelistAdd.addActionListener(this); tempblacklistAdd = new JButton("Add to temp blacklist"); tempblacklistAdd.addActionListener(this); tempwatchlistAdd = new JButton("Add to temp watchlist"); tempwatchlistAdd.addActionListener(this);

tempwhitelistRemove = new JButton("Remove from temp whitelist"); tempwhitelistRemove.addActionListener(this); tempblacklistRemove = new JButton("Remove from temp blacklist"); tempblacklistRemove.addActionListener(this); tempwatchlistRemove = new JButton("Remove from temp watchlist"); tempwatchlistRemove.addActionListener(this);

templistField = new JTextField("",iplength);

templistbotPanel = new JPanel(new GridLayout(4,3));

templistbotPanel.add(new JLabel("Username, IP, or page:", SwingConstants.RIGHT));

templistbotPanel.add(templistField); templistbotPanel.add(new JLabel("")); templistbotPanel.add(tempwhitelistAdd); templistbotPanel.add(tempblacklistAdd); templistbotPanel.add(tempwatchlistAdd); templistbotPanel.add(tempwhitelistRemove); templistbotPanel.add(tempblacklistRemove); templistbotPanel.add(tempwatchlistRemove);

sorttempblacklistButton = new JButton("Sort blacklist"); sorttempwhitelistButton = new JButton("Sort whitelist"); sorttempwatchlistButton = new JButton("Sort watchlist"); sorttempblacklistButton.addActionListener(this); sorttempwhitelistButton.addActionListener(this); sorttempwatchlistButton.addActionListener(this);

templistbotPanel.add(sorttempwhitelistButton); templistbotPanel.add(sorttempblacklistButton); templistbotPanel.add(sorttempwatchlistButton);

templistPanel.add(templistbotPanel, BorderLayout.SOUTH); templistPanel.setPreferredSize(new Dimension(600,appheight-100)); templistmainPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); templistmainPanel.add(templistPanel); //WHITELIST PANEL END

//REGEXP PANEL START regexpPanel = new JPanel(new BorderLayout());

regexptopPanel = new JPanel(new GridLayout(1,2)); regexptopPanel.add(new JLabel("Regexp whitelist")); regexptopPanel.add(new JLabel("Regexp blacklist")); regexpPanel.add(regexptopPanel, BorderLayout.NORTH);

regexpmidPanel = new JPanel(new GridLayout(1,2));

regexpwhiteList = new JList(regexpwhiteModel); regexpwhiteList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); regexpwhiteList.setSelectedIndex(0); regexpwhiteList.setLayoutOrientation(JList.VERTICAL); regexpwhiteList.addListSelectionListener(this); regexpwhiteList.addMouseListener(this); regexpwhiteScroller = new JScrollPane(regexpwhiteList); regexpmidPanel.add(regexpwhiteScroller);

regexpblackList = new JList(regexpblackModel); regexpblackList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); regexpblackList.setSelectedIndex(0); regexpblackList.setLayoutOrientation(JList.VERTICAL); regexpblackList.addListSelectionListener(this); regexpblackList.addMouseListener(this); regexpblackScroller = new JScrollPane(regexpblackList); regexpmidPanel.add(regexpblackScroller);

regexpPanel.add(regexpmidPanel, BorderLayout.CENTER);

regexpwhiteAdd = new JButton("Add to whitelist"); regexpwhiteAdd.addActionListener(this); regexpblackAdd = new JButton("Add to blacklist"); regexpblackAdd.addActionListener(this);

regexpwhiteRemove = new JButton("Remove from whitelist"); regexpwhiteRemove.addActionListener(this);

regexpblackRemove = new JButton("Remove from blacklist"); regexpblackRemove.addActionListener(this);

regexpField = new JTextField("",iplength);

regexpbotPanel = new JPanel(new GridLayout(4,2));

regexpbotPanel.add(new JLabel("Regexp:", SwingConstants.RIGHT));

regexpbotPanel.add(regexpField); regexpbotPanel.add(regexpwhiteAdd); regexpbotPanel.add(regexpblackAdd); regexpbotPanel.add(regexpwhiteRemove); regexpbotPanel.add(regexpblackRemove);

sortregexpwhitelistButton = new JButton("Sort whitelist"); sortregexpblacklistButton = new JButton("Sort blacklist"); sortregexpwhitelistButton.addActionListener(this); sortregexpblacklistButton.addActionListener(this);

regexpbotPanel.add(sortregexpwhitelistButton); regexpbotPanel.add(sortregexpblacklistButton);

regexpPanel.add(regexpbotPanel, BorderLayout.SOUTH); regexpPanel.setPreferredSize(new Dimension(400,appheight-100)); regexpmainPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); regexpmainPanel.add(regexpPanel); //REGEXP PANEL END

//WATCHLIST PANEL START watchlistPanel = new JPanel(new BorderLayout());

watchlistList = new JList(watchlistModel); watchlistList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); watchlistList.setSelectedIndex(0); watchlistList.setLayoutOrientation(JList.VERTICAL); watchlistList.addMouseListener(this); watchlistList.addListSelectionListener(this); watchlistPanel.add(new JScrollPane(watchlistList), BorderLayout.CENTER);

watchlistAdd = new JButton("Add"); watchlistAdd.addActionListener(this); watchlistRemove = new JButton("Remove"); watchlistRemove.addActionListener(this);

watchlistField = new JTextField("",iplength);

watchlistbotPanel = new JPanel(new GridLayout(3,2));

watchlistbotPanel.add(new JLabel("Article name:", SwingConstants.RIGHT)); watchlistbotPanel.add(watchlistField); watchlistbotPanel.add(watchlistAdd); watchlistbotPanel.add(watchlistRemove);

watchlistimportButton = new JButton("Import watchlist"); watchlistimportButton.addActionListener(this); watchlistbotPanel.add(watchlistimportButton);

sortarticlesButton = new JButton("Sort watchlist"); sortarticlesButton.addActionListener(this); watchlistbotPanel.add(sortarticlesButton);

watchlistPanel.add(watchlistbotPanel, BorderLayout.SOUTH); watchlistPanel.setPreferredSize(new Dimension(300,appheight-100)); watchlistmainPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); watchlistmainPanel.add(watchlistPanel); //WATCHLIST PANEL END

//CONFIG PANEL START configPanel = new JPanel(new GridLayout(50,1,0,0));

newpages.addActionListener(this); showips.addActionListener(this); olddeleted.addActionListener(this); autoscroll.addActionListener(this); singleclick.addActionListener(this); colorips.addActionListener(this); colornew.addActionListener(this); colorblist.addActionListener(this); colorwatch.addActionListener(this); colormoves.addActionListener(this); showwatch.addActionListener(this); queueedits.addActionListener(this); newversion.addActionListener(this); browserpick.addActionListener(this); removereviewed.addActionListener(this); stripformatting.addActionListener(this); reversetable.addActionListener(this); coloruserpage.addActionListener(this); blackreverted.addActionListener(this); watchdeleted.addActionListener(this); blackdeleted.addActionListener(this); listprecedence.addActionListener(this); rwhiteuser.addActionListener(this); rwhitepage.addActionListener(this); rwhitesummary.addActionListener(this); rblackuser.addActionListener(this); rblackpage.addActionListener(this); rblacksummary.addActionListener(this); watchuserpages.addActionListener(this); watchmasschanges.addActionListener(this); watchpagemoves.addActionListener(this); watchnewpages.addActionListener(this);

configPanel.add(olddeleted); configPanel.add(autoscroll); configPanel.add(singleclick); configPanel.add(queueedits); configPanel.add(removereviewed); configPanel.add(stripformatting); configPanel.add(reversetable);

configPanel.add(new JLabel("")); configPanel.add(showips); configPanel.add(newpages); configPanel.add(showwatch); configPanel.add(listprecedence); configPanel.add(watchuserpages); configPanel.add(watchmasschanges); configPanel.add(watchpagemoves); configPanel.add(watchnewpages);

if (showips.isSelected() || newpages.isSelected() || showwatch.isSelected()) { listprecedence.setEnabled(true); if (listprecedence.isSelected()) { watchuserpages.setEnabled(true); watchmasschanges.setEnabled(true); watchpagemoves.setEnabled(true); watchnewpages.setEnabled(true); } } else { listprecedence.setEnabled(false); watchuserpages.setEnabled(false); watchmasschanges.setEnabled(false); watchpagemoves.setEnabled(false); watchnewpages.setEnabled(false); }

configPanel.add(new JLabel("")); configPanel.add(rwhiteuser); configPanel.add(rwhitepage); configPanel.add(rwhitesummary); configPanel.add(rblackuser); configPanel.add(rblackpage); configPanel.add(rblacksummary);

configPanel.add(new JLabel("")); configPanel.add(blackreverted); revertpermButton.addActionListener(this); reverttempButton.addActionListener(this); if (!blackreverted.isSelected()) { revertpermButton.setEnabled(false); reverttempButton.setEnabled(false); } revertGroup = new ButtonGroup(); revertGroup.add(revertpermButton); revertGroup.add(reverttempButton); JPanel tp1 = new JPanel(new FlowLayout(FlowLayout.LEFT)); tp1.add(revertpermButton); tp1.add(reverttempButton); configPanel.add(tp1); configPanel.add(blackdeleted); delpagepermButton.addActionListener(this); delpagetempButton.addActionListener(this); if (!blackdeleted.isSelected()) { delpagepermButton.setEnabled(false); delpagetempButton.setEnabled(false); } delpageGroup = new ButtonGroup(); delpageGroup.add(delpagepermButton); delpageGroup.add(delpagetempButton); JPanel tp2 = new JPanel(new FlowLayout(FlowLayout.LEFT)); tp2.add(delpagepermButton); tp2.add(delpagetempButton); configPanel.add(tp2); configPanel.add(watchdeleted); watchdelpermButton.addActionListener(this); watchdeltempButton.addActionListener(this); if (!watchdeleted.isSelected()) { watchdelpermButton.setEnabled(false); watchdeltempButton.setEnabled(false); } watchdelGroup = new ButtonGroup(); watchdelGroup.add(watchdelpermButton); watchdelGroup.add(watchdeltempButton); JPanel tp3 = new JPanel(new FlowLayout(FlowLayout.LEFT)); tp3.add(watchdelpermButton); tp3.add(watchdeltempButton); configPanel.add(tp3);

configPanel.add(new JLabel(""));

colorblistPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); colorblistPanel.add(colorblist); colorblistButton = new JButton(" "); colorblistButton.setBackground(blacklistcolor); colorblistButton.addActionListener(this); colorblistPanel.add(colorblistButton); configPanel.add(colorblistPanel);

colorwatchPanel = new JPanel(new FlowLayout(FlowLayout.LEFT,0,0)); colorwatchPanel.add(colorwatch); colorwatchButton = new JButton(" "); colorwatchButton.setBackground(watchlistcolor); colorwatchButton.addActionListener(this); colorwatchPanel.add(colorwatchButton); configPanel.add(colorwatchPanel);

colorchanged.addActionListener(this); changedPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0)); changedPanel.add(colorchanged); changedPanel.add(changedField); changedPanel.add(new JLabel(" characters changed ")); colorchangedButton = new JButton(" "); colorchangedButton.setBackground(changedcolor); colorchangedButton.addActionListener(this); changedPanel.add(colorchangedButton); configPanel.add(changedPanel);

colornewPanel = new JPanel(new FlowLayout(FlowLayout.LEFT,0,0)); colornewPanel.add(colornew); colornewButton = new JButton(" "); colornewButton.setBackground(newcolor); colornewButton.addActionListener(this); colornewPanel.add(colornewButton); configPanel.add(colornewPanel);

coloripsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT,0,0)); coloripsPanel.add(colorips); coloripsButton = new JButton(" "); coloripsButton.setBackground(ipcolor); coloripsButton.addActionListener(this); coloripsPanel.add(coloripsButton); configPanel.add(coloripsPanel);

colormovesPanel = new JPanel(new FlowLayout(FlowLayout.LEFT,0,0)); colormovesPanel.add(colormoves); colormovesButton = new JButton(" "); colormovesButton.setBackground(movecolor); colormovesButton.addActionListener(this); colormovesPanel.add(colormovesButton); configPanel.add(colormovesPanel);

coloruserpagePanel = new JPanel(new FlowLayout(FlowLayout.LEFT,0,0)); coloruserpagePanel.add(coloruserpage); coloruserpageButton = new JButton(" "); coloruserpageButton.setBackground(userpagecolor); coloruserpageButton.addActionListener(this); coloruserpagePanel.add(coloruserpageButton); configPanel.add(coloruserpagePanel);

configPanel.add(new JLabel(""));

JPanel tp4 = new JPanel(new FlowLayout(FlowLayout.LEFT)); tp4.add(new JLabel("Default project: ")); tp4.add(defaultprojectField); configPanel.add(tp4);

configPanel.add(new JLabel("")); configPanel.add(new JLabel("B column takes you to:")); blockButton.addActionListener(this); vipButton.addActionListener(this); blockvipGroup = new ButtonGroup(); blockvipGroup.add(blockButton); blockvipGroup.add(vipButton); JPanel tp5 = new JPanel(new FlowLayout(FlowLayout.LEFT)); tp5.add(blockButton); tp5.add(vipButton); configPanel.add(tp5);

configPanel.add(new JLabel("")); configPanel.add(browserpick); configPanel.add(new JLabel("If no automatic detection, enter full path of browser below.")); browserPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0 , 0)); browserchooserButton = new JButton("Browse"); if (browserpick.isSelected()) { browserchooserButton.setEnabled(false); browserField.setEditable(false); } browserchooserButton.addActionListener(this); browserPanel.add(browserchooserButton); browserPanel.add(browserField); browsertopPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); browsertopPanel.add(browserPanel); configPanel.add(browsertopPanel); configPanel.add(new JLabel("NOTE: You can add command line options to the end of the above field."));

configPanel.add(new JLabel("")); configPanel.add(newversion);

configmainPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); configmainPanel.add(configPanel);

configtopPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); configtopPanel.add(configmainPanel);

configScroller = new JScrollPane(configtopPanel); configScroller.getVerticalScrollBar().setUnitIncrement(25); configScroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

//CONFIG PANEL END

//IRC PANEL START ircPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); leftircPanel = new JPanel(new GridLayout(4,2)); leftircPanel.add(new JLabel("Channel: ", SwingConstants.RIGHT)); leftircPanel.add(channelField); leftircPanel.add(new JLabel("Server: ", SwingConstants.RIGHT)); leftircPanel.add(serverField); leftircPanel.add(new JLabel("Port: ", SwingConstants.RIGHT)); leftircPanel.add(portField); leftircPanel.add(new JLabel(" ")); ircconButton = new JButton("Connect"); ircconButton.addActionListener(this); leftircPanel.add(ircconButton); ircPanel.setMaximumSize(new Dimension(250,400)); ircPanel.add(leftircPanel);

irctopPanel = new JPanel(new BorderLayout()); irctopPanel.add(ircPanel, BorderLayout.CENTER); irctopPanel.add(new JLabel("Connect, then enter in another #project.name and click \"Connect\" to view multiple feeds"), BorderLayout.SOUTH); irctopPanel.setMaximumSize(new Dimension(250,400));

irctoptopPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); irctoptopPanel.add(irctopPanel); //IRC PANEL END

//ABOUT LABEL START aboutPanel = new JPanel(new GridLayout(19,1,5,5)); aboutPanel.add(new JLabel(version)); aboutPanel.add(new JLabel("Copyright (C) 2005 Derek Williams aka CryptoDerk")); aboutPanel.add(new JLabel("CryptoDerk's Vandal Fighter comes with ABSOLUTELY NO WARRANTY; for details")); aboutPanel.add(new JLabel("see http://www.derk.org/cdvf/license.txt. This is free software, and you are welcome")); aboutPanel.add(new JLabel("to redistribute it under certain conditions; see http://www.derk.org/cdvf/license.txt")); aboutPanel.add(new JLabel("")); aboutPanel.add(new JLabel("Program website: http://cdvf.derk.org/")); aboutPanel.add(new JLabel("Author's website: http://www.derk.org/")); aboutPanel.add(new JLabel("Licensed under GNU GPL 2.0")); aboutPanel.add(new JLabel("Additional authors:"));

abouttopPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); abouttopPanel.add(aboutPanel);

//ABOUT LABEL END tab.addTab("Live RC", editsPanel); tab.addTab("User lists", whitelistmainPanel); tab.addTab("Article watchlist", watchlistmainPanel); tab.addTab("Temp lists", templistmainPanel); tab.addTab("Regexp lists",regexpmainPanel); tab.addTab("Configuration", configScroller); tab.addTab("IRC settings", irctoptopPanel); tab.addTab("About CDVF", abouttopPanel);

overallPanel = new JPanel(new BorderLayout()); overallPanel.add(tab, BorderLayout.CENTER); statusLabel = new JLabel("Ready to connect..."); overallPanel.add(statusLabel, BorderLayout.SOUTH);

mainContainer.add(overallPanel);

setSize(appwidth,appheight);

// This restricts the minimum size of the application and resizes the list panels appropriately when the app is resized at all this.addComponentListener(new java.awt.event.ComponentAdapter() { public void componentResized(ComponentEvent e) { JFrame tmp = (JFrame)e.getSource();

if (tmp.getHeight()<minheight) tmp.setSize(tmp.getWidth(), minheight);

if (tmp.getWidth()<minwidth) tmp.setSize(minwidth, tmp.getHeight());

whitelistPanel.setPreferredSize(new Dimension(400,tmp.getHeight()-100)); whitelistPanel.setSize(new Dimension(400,tmp.getHeight()-100)); watchlistPanel.setPreferredSize(new Dimension(300,tmp.getHeight()-100)); watchlistPanel.setSize(new Dimension(300,tmp.getHeight()-100)); regexpPanel.setPreferredSize(new Dimension(400,tmp.getHeight()-100)); regexpPanel.setSize(new Dimension(400,tmp.getHeight()-100)); templistPanel.setPreferredSize(new Dimension(600,tmp.getHeight()-100)); templistPanel.setSize(new Dimension(600,tmp.getHeight()-100)); } });

this.addWindowListener ( new WindowAdapter() { public void windowClosing(WindowEvent e) { if (connected) { irc.out.println("quit :" + version + ", get it at http://cdvf.derk.org/ !"); irc.out.flush(); } if (started) savefiles();

System.exit(0); } } );

whitelistList.clearSelection(); blacklistList.clearSelection(); watchlistList.clearSelection(); regexpwhiteList.clearSelection(); regexpblackList.clearSelection(); tempwhitelistList.clearSelection(); tempblacklistList.clearSelection(); tempwatchlistList.clearSelection();

started = true; if (newversion.isSelected()) versioncheck = new versionchecker(this);

setVisible(true); }

public void updatechanstatus(String s, boolean add) { if (add && !servers.contains(s)) servers.add(s); else if (!add) servers.remove(s);

chanstatus(); }

public void chanstatus() { String tmp = new String("Connected to ");

Enumeration e = servers.elements(); while (e.hasMoreElements()) { tmp = new String(tmp + (String)e.nextElement() + ", "); }

if (servers.size() > 0) statusLabel.setText(tmp.substring(0,tmp.length()-2)); else statusLabel.setText("Connected, but not viewing any feeds - try channel #en.wikipedia"); }

class newModel extends DefaultTableModel {

public newModel(Object[] columns, int x) { super(columns,x); }

public boolean isCellEditable(int row, int col) { //only whitelist, blacklist, watchlist col can be changed if (col == wlistcol || col == blistcol || col == watchcol || col==twhitecol || col == tblackcol || col==twatchcol) return(true); else return(false); }

public Class getColumnClass(int column) { Vector v = (Vector) dataVector.elementAt(0); return v.elementAt(column).getClass(); } }

public void tableChanged(TableModelEvent e) { int row = e.getFirstRow(); int column = e.getColumn(); int tmp, i; if (row>=0 && (column == wlistcol || column == blistcol || column == watchcol || column==twhitecol || column==tblackcol || column==twatchcol) )

       {

newModel model = (newModel)e.getSource();

if (column == watchcol) // watchlist { if (((Boolean)model.getValueAt(row,column)).booleanValue() == true && !watchlistModel.contains((String)editstableModel.getValueAt(row,articlecol)+"#"+(String)editstableModel.getValueAt(row,projectcol))) watchlistModel.addElement((String)editstableModel.getValueAt(row,articlecol)+"#"+(String)editstableModel.getValueAt(row,projectcol)); else if (((Boolean)model.getValueAt(row,column)).booleanValue() == false && watchlistModel.contains((String)editstableModel.getValueAt(row,articlecol)+"#"+(String)editstableModel.getValueAt(row,projectcol))) watchlistModel.removeElement((String)editstableModel.getValueAt(row,articlecol)+"#"+(String)editstableModel.getValueAt(row,projectcol)); watchlistList.clearSelection(); } else if (column == blistcol) // blacklist { if (((Boolean)model.getValueAt(row,column)).booleanValue() == true && !blacklistModel.contains((String)editstableModel.getValueAt(row,editorcol)+"#"+(String)editstableModel.getValueAt(row,projectcol))) blacklistModel.addElement((String)editstableModel.getValueAt(row,editorcol)+"#"+(String)editstableModel.getValueAt(row,projectcol)); else if (blacklistModel.contains((String)editstableModel.getValueAt(row,editorcol)+"#"+(String)editstableModel.getValueAt(row,projectcol))) blacklistModel.removeElement((String)editstableModel.getValueAt(row,editorcol)+"#"+(String)editstableModel.getValueAt(row,projectcol)); blacklistList.clearSelection(); } else if (column == wlistcol) //whitelist { if (((Boolean)model.getValueAt(row,column)).booleanValue() == true) { String tstr = new String((String)editstableModel.getValueAt(row,editorcol) + "#" + (String)editstableModel.getValueAt(row,projectcol)); whitelistModel.addElement(tstr); tmp = editstableModel.getRowCount(); for(i=tmp-1;i>=0;i--) { if ( tstr.equals((String)editstableModel.getValueAt(i,editorcol)+"#"+(String)editstableModel.getValueAt(row,projectcol))) editstableModel.removeRow(i); } if (blacklistModel.contains(tstr)) blacklistModel.removeElement(tstr); } whitelistList.clearSelection(); } else if (column == twatchcol) // temp watchlist { if (((Boolean)model.getValueAt(row,column)).booleanValue() == true && !tempwatchlistModel.contains((String)editstableModel.getValueAt(row,articlecol)+"#"+(String)editstableModel.getValueAt(row,projectcol))) tempwatchlistModel.addElement((String)editstableModel.getValueAt(row,articlecol)+"#"+(String)editstableModel.getValueAt(row,projectcol)); else if (((Boolean)model.getValueAt(row,column)).booleanValue() == false && tempwatchlistModel.contains((String)editstableModel.getValueAt(row,articlecol)+"#"+(String)editstableModel.getValueAt(row,projectcol))) tempwatchlistModel.removeElement((String)editstableModel.getValueAt(row,articlecol)+"#"+(String)editstableModel.getValueAt(row,projectcol)); tempwatchlistList.clearSelection(); } else if (column == tblackcol) // temp blacklist { if (((Boolean)model.getValueAt(row,column)).booleanValue() == true && !tempblacklistModel.contains((String)editstableModel.getValueAt(row,editorcol)+"#"+(String)editstableModel.getValueAt(row,projectcol))) tempblacklistModel.addElement((String)editstableModel.getValueAt(row,editorcol)+"#"+(String)editstableModel.getValueAt(row,projectcol)); else if (tempblacklistModel.contains((String)editstableModel.getValueAt(row,editorcol)+"#"+(String)editstableModel.getValueAt(row,projectcol))) tempblacklistModel.removeElement((String)editstableModel.getValueAt(row,editorcol)+"#"+(String)editstableModel.getValueAt(row,projectcol)); tempblacklistList.clearSelection(); } else if (column == twhitecol) // tempwhitelist { if (((Boolean)model.getValueAt(row,column)).booleanValue() == true) { String tstr = new String((String)editstableModel.getValueAt(row,editorcol) + "#" + (String)editstableModel.getValueAt(row,projectcol)); tempwhitelistModel.addElement(tstr); tmp = editstableModel.getRowCount(); for(i=tmp-1;i>=0;i--) { if ( tstr.equals((String)editstableModel.getValueAt(i,editorcol)+"#"+(String)editstableModel.getValueAt(row,projectcol))) editstableModel.removeRow(i); } if (tempblacklistModel.contains(tstr)) tempblacklistModel.removeElement(tstr); } tempwhitelistList.clearSelection(); }

} savefiles(); }

public void actionPerformed(ActionEvent e) { int i, tmp; if (e.getSource() == showips && showips.isSelected()) { tmp = editstableModel.getRowCount(); for(i=tmp-1;i>=0;i--) { if (!isValidIP((String)editstableModel.getValueAt(i,editorcol)) && !(listprecedence.isSelected() && watched((String)editstableModel.getValueAt(i,articlecol), (String)editstableModel.getValueAt(i,editorcol), (String)editstableModel.getValueAt(i,summarycol), (String)editstableModel.getValueAt(i,projectcol), ((Integer)editstableModel.getValueAt(i,changedcol)).intValue(), ((Boolean)editstableModel.getValueAt(i,movecol)).booleanValue(), ((Boolean)editstableModel.getValueAt(i,newecol)).booleanValue()))) editstableModel.removeRow(i); }

listprecedence.setEnabled(true); if (listprecedence.isSelected()) { watchuserpages.setEnabled(true); watchmasschanges.setEnabled(true); watchpagemoves.setEnabled(true); watchnewpages.setEnabled(true); } } else if (e.getSource() == newpages && newpages.isSelected()) { tmp = editstableModel.getRowCount(); for(i=tmp-1;i>=0;i--) { if (!((Boolean)editstableModel.getValueAt(i,newecol)).booleanValue() && !(listprecedence.isSelected() && watched((String)editstableModel.getValueAt(i,articlecol), (String)editstableModel.getValueAt(i,editorcol), (String)editstableModel.getValueAt(i,summarycol), (String)editstableModel.getValueAt(i,projectcol), ((Integer)editstableModel.getValueAt(i,changedcol)).intValue(), ((Boolean)editstableModel.getValueAt(i,movecol)).booleanValue(), ((Boolean)editstableModel.getValueAt(i,newecol)).booleanValue()))) editstableModel.removeRow(i); } listprecedence.setEnabled(true); if (listprecedence.isSelected()) { watchuserpages.setEnabled(true); watchmasschanges.setEnabled(true); watchpagemoves.setEnabled(true); watchnewpages.setEnabled(true); }

} else if (e.getSource() == showwatch && showwatch.isSelected()) { tmp = editstableModel.getRowCount(); for(i=tmp-1;i>=0;i--) { if (!watched((String)editstableModel.getValueAt(i,articlecol), (String)editstableModel.getValueAt(i,editorcol), (String)editstableModel.getValueAt(i,summarycol), (String)editstableModel.getValueAt(i,projectcol), ((Integer)editstableModel.getValueAt(i,changedcol)).intValue(), ((Boolean)editstableModel.getValueAt(i,movecol)).booleanValue(), ((Boolean)editstableModel.getValueAt(i,newecol)).booleanValue())) editstableModel.removeRow(i); } listprecedence.setEnabled(true); if (listprecedence.isSelected()) { watchuserpages.setEnabled(true); watchmasschanges.setEnabled(true); watchpagemoves.setEnabled(true); watchnewpages.setEnabled(true); }

} else if (e.getSource() == queueedits && !queueedits.isSelected()) { pausededits.removeAllElements(); } else if (e.getSource() == watchlistAdd && watchlistField.getText().length()>0) { if (watchlistField.getText().matches("[^\\u0023]*")) watchlistField.setText(watchlistField.getText()+"#"+defaultprojectField.getText()); if (!watchlistModel.contains(watchlistField.getText())) watchlistModel.addElement(watchlistField.getText()); watchlistField.setText(""); watchlistList.clearSelection(); } else if (e.getSource() == tempwatchlistAdd && templistField.getText().length()>0) { if (templistField.getText().matches("[^\\u0023]*")) templistField.setText(templistField.getText()+"#"+defaultprojectField.getText()); if (!tempwatchlistModel.contains(templistField.getText())) tempwatchlistModel.addElement(templistField.getText()); templistField.setText(""); tempwatchlistList.clearSelection(); } else if (e.getSource() == watchlistRemove) { int indices[] = watchlistList.getSelectedIndices();

for(i=indices.length-1;i>=0;i--) watchlistModel.remove(indices[i]); watchlistList.clearSelection(); } else if (e.getSource() == tempwatchlistRemove) { int indices[] = tempwatchlistList.getSelectedIndices();

for(i=indices.length-1;i>=0;i--) tempwatchlistModel.remove(indices[i]); tempwatchlistList.clearSelection(); } else if (e.getSource() == whitelistAdd && userlistField.getText().length()>0) { if (userlistField.getText().matches("[^\\u0023]*")) userlistField.setText(userlistField.getText()+"#"+defaultprojectField.getText()); if (!whitelistModel.contains(userlistField.getText())) { if (blacklistModel.contains(userlistField.getText())) blacklistModel.removeElement(userlistField.getText()); whitelistModel.addElement(userlistField.getText());

tmp = editstableModel.getRowCount(); for(i=tmp-1;i>=0;i--) if (((String)editstableModel.getValueAt(i,editorcol)).equals(userlistField.getText())) editstableModel.removeRow(i); } userlistField.setText(""); whitelistList.clearSelection(); } else if (e.getSource() == whitelistRemove) { int indices[] = whitelistList.getSelectedIndices(); for(i=indices.length-1;i>=0;i--) whitelistModel.remove(indices[i]); whitelistList.clearSelection(); } else if (e.getSource() == blacklistAdd && userlistField.getText().length()>0) { if (userlistField.getText().matches("[^\\u0023]*")) userlistField.setText(userlistField.getText()+"#"+defaultprojectField.getText()); if (!blacklistModel.contains(userlistField.getText())) { if (whitelistModel.contains(userlistField.getText())) whitelistModel.removeElement(userlistField.getText()); blacklistModel.addElement(userlistField.getText()); } userlistField.setText(""); blacklistList.clearSelection(); } else if (e.getSource() == blacklistRemove) { int indices[] = blacklistList.getSelectedIndices(); for(i=indices.length-1;i>=0;i--) blacklistModel.remove(indices[i]); blacklistList.clearSelection(); } else if (e.getSource() == tempwhitelistAdd && templistField.getText().length()>0) { if (templistField.getText().matches("[^\\u0023]*")) templistField.setText(templistField.getText()+"#"+defaultprojectField.getText()); if (!tempwhitelistModel.contains(templistField.getText())) { if (tempblacklistModel.contains(templistField.getText())) tempblacklistModel.removeElement(templistField.getText()); tempwhitelistModel.addElement(templistField.getText());

tmp = editstableModel.getRowCount(); for(i=tmp-1;i>=0;i--) if (((String)editstableModel.getValueAt(i,editorcol)).equals(templistField.getText())) editstableModel.removeRow(i); } templistField.setText(""); tempwhitelistList.clearSelection(); } else if (e.getSource() == tempwhitelistRemove) { int indices[] = tempwhitelistList.getSelectedIndices(); for(i=indices.length-1;i>=0;i--) tempwhitelistModel.remove(indices[i]); tempwhitelistList.clearSelection(); } else if (e.getSource() == tempblacklistAdd && templistField.getText().length()>0) { if (templistField.getText().matches("[^\\u0023]*")) templistField.setText(templistField.getText()+"#"+defaultprojectField.getText()); if (!tempblacklistModel.contains(templistField.getText())) { if (tempwhitelistModel.contains(templistField.getText())) tempwhitelistModel.removeElement(templistField.getText()); tempblacklistModel.addElement(templistField.getText()); } templistField.setText(""); tempblacklistList.clearSelection(); } else if (e.getSource() == tempblacklistRemove) { int indices[] = tempblacklistList.getSelectedIndices(); for(i=indices.length-1;i>=0;i--) tempblacklistModel.remove(indices[i]); tempblacklistList.clearSelection(); } else if (e.getSource() == regexpwhiteAdd && regexpField.getText().length()>0) { if (!regexpwhiteModel.contains(regexpField.getText())) { if (regexpblackModel.contains(regexpField.getText())) regexpblackModel.removeElement(regexpField.getText()); regexpwhiteModel.addElement(regexpField.getText());

tmp = editstableModel.getRowCount(); for(i=tmp-1;i>=0;i--) if (((String)editstableModel.getValueAt(i,editorcol)).matches(regexpField.getText())) editstableModel.removeRow(i); } regexpField.setText(""); regexpwhiteList.clearSelection(); } else if (e.getSource() == regexpwhiteRemove) { int indices[] = regexpwhiteList.getSelectedIndices(); for(i=indices.length-1;i>=0;i--) regexpwhiteModel.remove(indices[i]); regexpwhiteList.clearSelection(); } else if (e.getSource() == regexpblackAdd && regexpField.getText().length()>0) { if (!regexpblackModel.contains(regexpField.getText())) { if (regexpwhiteModel.contains(regexpField.getText())) regexpwhiteModel.removeElement(regexpField.getText()); regexpblackModel.addElement(regexpField.getText()); } regexpField.setText(""); regexpblackList.clearSelection(); } else if (e.getSource() == regexpblackRemove) { int indices[] = regexpblackList.getSelectedIndices(); for(i=indices.length-1;i>=0;i--) regexpblackModel.remove(indices[i]); regexpblackList.clearSelection(); } else if (e.getSource() == connectButton || e.getSource()==ircconButton) { if (connected) irc.joinchannel(channelField.getText()); else irc = new IRC(channelField.getText(),serverField.getText(),portField.getText(), this); connected = true; disconnectButton.setEnabled(true); pauseButton.setEnabled(true); irc.pausevar=false; pauseButton.setText("Pause (Alt-A)"); serverField.setEditable(false); portField.setEditable(false); } else if (e.getSource() == clearButton) { editstableModel.setNumRows(0); } else if (e.getSource() == disconnectButton) { irc.quit(); connected = false; pauseButton.setText("Pause (Alt-A)"); disconnectButton.setEnabled(false); pauseButton.setEnabled(false); serverField.setEditable(true); portField.setEditable(true);

} else if (e.getSource() == pauseButton) { if (irc.pausevar == false) pauseButton.setText("Unpause (Alt-A)"); else pauseButton.setText("Pause (Alt-A)");

irc.pausevar = !irc.pausevar; } else if (e.getSource() == importadminsButton) { adminimport = new adminimporter(whitelistimportField.getText()); importadminsButton.setEnabled(false); whitelistimportField.setEditable(false); } else if (e.getSource() == browserpick) { if (browserpick.isSelected()) { browserField.setEditable(false); browserchooserButton.setEnabled(false); } else { browserField.setEditable(true); browserchooserButton.setEnabled(true); } } else if (e.getSource() == browserchooserButton) { // launch file chooser JFileChooser browserChooser = new JFileChooser(); int returnval = browserChooser.showOpenDialog(this); if (returnval == JFileChooser.APPROVE_OPTION) browserField.setText("" + browserChooser.getSelectedFile()); } else if (e.getSource() == watchlistimportButton) { JFileChooser importChooser = new JFileChooser(); int returnval = importChooser.showOpenDialog(this); if (returnval == JFileChooser.APPROVE_OPTION) { try { File watchlistFile = new File("" + importChooser.getSelectedFile()); FileInputStream watchimport = new FileInputStream(watchlistFile); BufferedInputStream bis = new BufferedInputStream(watchimport); String watchlist=new String(""); String proj = (String)JOptionPane.showInputDialog( this, "Enter project, e.g. en.wikipedia\nor hit enter to use " + defaultprojectField.getText(), "Project name", JOptionPane.PLAIN_MESSAGE); if (proj.length()<5) proj = defaultprojectField.getText(); if (proj.substring(proj.length()-4).equals(".org")) proj = proj.substring(0,proj.length()-4);

i = bis.available(); while (i>0) { byte b[] = new byte[i]; bis.read(b); watchlist = new String(watchlist + new String(b)); i=bis.available(); }

Pattern p = Pattern.compile("id\\u005B\\u005D['\"] value=\"([^\"]*)\""); Matcher m = p.matcher(watchlist);

while (m.find()) { if (!watchlistModel.contains(m.group(1)+"#"+proj)); watchlistModel.addElement(m.group(1)+"#"+proj); } watchlistList.clearSelection(); watchimport.close(); bis.close();

} catch (Exception ex) {} } } else if (e.getSource() == colorchangedButton) { colorChooser = new JColorChooser();

changedcolor = colorChooser.showDialog(this, "Pick a color", changedcolor);

colorchangedButton.setBackground(changedcolor); } else if (e.getSource() == colorblistButton) { colorChooser = new JColorChooser();

blacklistcolor = colorChooser.showDialog(this, "Pick a color", blacklistcolor);

colorblistButton.setBackground(blacklistcolor); } else if (e.getSource() == colorwatchButton) { colorChooser = new JColorChooser();

watchlistcolor = colorChooser.showDialog(this, "Pick a color", watchlistcolor);

colorwatchButton.setBackground(watchlistcolor); } else if (e.getSource() == colornewButton) { colorChooser = new JColorChooser();

newcolor = colorChooser.showDialog(this, "Pick a color", newcolor);

colornewButton.setBackground(newcolor); } else if (e.getSource() == colormovesButton) { colorChooser = new JColorChooser();

movecolor = colorChooser.showDialog(this, "Pick a color", movecolor);

colormovesButton.setBackground(movecolor); } else if (e.getSource() == coloripsButton) { colorChooser = new JColorChooser();

ipcolor = colorChooser.showDialog(this, "Pick a color", ipcolor);

coloripsButton.setBackground(ipcolor); } else if (e.getSource() == coloruserpageButton) { colorChooser = new JColorChooser();

userpagecolor = colorChooser.showDialog(this, "Pick a color", userpagecolor);

coloruserpageButton.setBackground(userpagecolor); } else if (e.getSource() == showips || e.getSource() == newpages || e.getSource() == showwatch) { if (!(showips.isSelected() || newpages.isSelected() || showwatch.isSelected())) { listprecedence.setEnabled(false); watchuserpages.setEnabled(false); watchmasschanges.setEnabled(false); watchpagemoves.setEnabled(false); watchnewpages.setEnabled(false); } } else if (e.getSource() == listprecedence && listprecedence.isSelected()) { watchuserpages.setEnabled(true); watchmasschanges.setEnabled(true); watchpagemoves.setEnabled(true); watchnewpages.setEnabled(true); } else if (e.getSource() == listprecedence) { watchuserpages.setEnabled(false); watchmasschanges.setEnabled(false); watchpagemoves.setEnabled(false); watchnewpages.setEnabled(false); } else if (e.getSource() == blackreverted) { if (blackreverted.isSelected()) { revertpermButton.setEnabled(true); reverttempButton.setEnabled(true); } else { revertpermButton.setEnabled(false); reverttempButton.setEnabled(false); } } else if (e.getSource() == blackdeleted) { if (blackdeleted.isSelected()) { delpagepermButton.setEnabled(true); delpagetempButton.setEnabled(true); } else { delpagepermButton.setEnabled(false); delpagetempButton.setEnabled(false); } } else if (e.getSource() == watchdeleted) { if (watchdeleted.isSelected()) { watchdelpermButton.setEnabled(true); watchdeltempButton.setEnabled(true); } else { watchdelpermButton.setEnabled(false); watchdeltempButton.setEnabled(false); } } else if (e.getSource() == sortarticlesButton) { Object list[] = bubblesort(watchlistModel.toArray());

watchlistModel.clear(); for (i=0;i<list.length;i++) watchlistModel.addElement((String)list[i]); } else if (e.getSource() == sorttempwatchlistButton) { Object list[] = bubblesort(tempwatchlistModel.toArray());

tempwatchlistModel.clear(); for (i=0;i<list.length;i++) tempwatchlistModel.addElement((String)list[i]); } else if (e.getSource() == sortwhitelistButton) { Object list[] = bubblesort(whitelistModel.toArray());

whitelistModel.clear(); for (i=0;i<list.length;i++) whitelistModel.addElement((String)list[i]); } else if (e.getSource() == sortblacklistButton) { Object list[] = bubblesort(blacklistModel.toArray());

blacklistModel.clear(); for (i=0;i<list.length;i++) blacklistModel.addElement((String)list[i]); } else if (e.getSource() == sorttempwhitelistButton) { Object list[] = bubblesort(tempwhitelistModel.toArray());

tempwhitelistModel.clear(); for (i=0;i<list.length;i++) tempwhitelistModel.addElement((String)list[i]); } else if (e.getSource() == sorttempblacklistButton) { Object list[] = bubblesort(tempblacklistModel.toArray());

tempblacklistModel.clear(); for (i=0;i<list.length;i++) tempblacklistModel.addElement((String)list[i]); } else if (e.getSource() == sortregexpwhitelistButton) { Object list[] = bubblesort(regexpwhiteModel.toArray());

regexpwhiteModel.clear(); for (i=0;i<list.length;i++) regexpwhiteModel.addElement((String)list[i]); } else if (e.getSource() == sortregexpblacklistButton) { Object list[] = bubblesort(regexpblackModel.toArray());

regexpblackModel.clear(); for (i=0;i<list.length;i++) regexpblackModel.addElement((String)list[i]); }

savefiles(); }

public Object[] bubblesort(Object list[]) { int i, j; String temp;

for (i=list.length-1;i>0;i--) for(j=0;j<i;j++) if (((String)list[j]).compareTo((String)list[j+1])>0) { temp = (String)list[j]; list[j] = (String)list[j+1]; list[j+1] = (String)temp; } return (list); }

public void valueChanged(ListSelectionEvent e) {

if (e.getValueIsAdjusting() == false && ((JList)e.getSource()).getSelectedIndex()>=0) { if (e.getSource() == whitelistList ) { userlistField.setText((String)whitelistModel.getElementAt(whitelistList.getSelectedIndex())); } else if (e.getSource() == blacklistList ) { userlistField.setText((String)blacklistModel.getElementAt(blacklistList.getSelectedIndex())); } else if (e.getSource() == watchlistList ) { watchlistField.setText((String)watchlistModel.getElementAt(watchlistList.getSelectedIndex())); } else if (e.getSource() == regexpwhiteList ) { regexpField.setText((String)regexpwhiteModel.getElementAt(regexpwhiteList.getSelectedIndex())); } else if (e.getSource() == regexpblackList ) { regexpField.setText((String)regexpblackModel.getElementAt(regexpblackList.getSelectedIndex())); } } }

boolean whitelisted(String page, String user, String summary, String project) { if (whitelistModel.contains(user+"#"+project) || tempwhitelistModel.contains(user+"#"+project)) return (true); else { int size = regexpwhiteModel.getSize(), i;

for (i=0;i<size;i++) if ( (rwhiteuser.isSelected() && user.matches((String)regexpwhiteModel.getElementAt(i))) || (rwhitepage.isSelected() && page.matches((String)regexpwhiteModel.getElementAt(i))) || (rwhitesummary.isSelected() && summary.matches((String)regexpwhiteModel.getElementAt(i))) ) return(true); } return(false);

}

/* A page is considered "Watched" and thus immune from removal (if list precedence is on) IF: 1) The page is on the article watchlist 2) The page was edited by a user on the blacklist 3) The page is on the temporary article watchlist 4) The page was edited by a user on the temporary blacklist 5) Regexp application to users is turned on and a user matches any regexp 6) Regexp application to pages is turned on and a page matches any regexp -- 7) Watch user page edits not by user turned on 8) Watch mass additions/deletion turned on 9) Watch page moves turned on 10) Watch new pages turned on */ boolean watched(String page, String user, String summary, String project, int change, boolean move, boolean newpage) { if (watchlistModel.contains(page+"#"+project) || blacklistModel.contains(user+"#"+project) || tempwatchlistModel.contains(page+"#"+project) || tempblacklistModel.contains(user+"#"+project) ) return (true); else if (watchuserpages.isSelected() && page.matches("^User:.*") && !page.matches("^User:"+user+".*")) return (true); else if (watchpagemoves.isSelected() && move) return (true); else if (watchnewpages.isSelected() && newpage) return (true); else if (watchmasschanges.isSelected()) { try { if (change<0) change*=-1; int j = Integer.parseInt(changedField.getText()); if (j<0) j*=-1; if (change>j) return (true); } catch (Exception e) {} } else { int size = regexpblackModel.getSize(), i;

for(i=0;i<size;i++) if ( (rblackuser.isSelected() && user.matches((String)regexpblackModel.getElementAt(i))) || (rblackpage.isSelected() && page.matches((String)regexpblackModel.getElementAt(i))) || (rblacksummary.isSelected() && summary.matches((String)regexpblackModel.getElementAt(i))) ) return(true); } return (false); }

public void addnewtableentry(String pagename, String url, String username, String summary, int change, boolean minor, boolean newpage, String projname, boolean moveflag, String time) { c = new GregorianCalendar(); Object tablerow[] = new Object[totalcols]; int a, i;

// START ROW SETUP tablerow[sectimecol] = new Long(System.currentTimeMillis()); tablerow[urlcol] = url; tablerow[projectcol] = projname; tablerow[xcol] = new String(""); tablerow[timecol] = time; tablerow[articlecol] = pagename; tablerow[editorcol] = username; tablerow[bcol] = new String(""); tablerow[tcol] = new String("");

if (stripformatting.isSelected()) tablerow[summarycol] = summary.replaceAll("\\u005B\\u005B([^\\u007C\\u005B\\u005D]*)\\u007C([^\\u007C\\u005B\\u005D]*)\\u005D\\u005D", "$2").replaceAll("\\u005B\\u005B([^\\u007C\\u005B\\u005D]*)\\u005D\\u005D", "$1"); else tablerow[summarycol] = summary;

tablerow[minorcol] = new Boolean(minor); tablerow[newecol] = new Boolean(newpage); if (moveflag && change==0 && summary.matches(".*moved to.*")) { tablerow[movecol] = new Boolean(true); tablerow[urlcol] = url.substring(0,url.length()-15); } else tablerow[movecol] = new Boolean(false); tablerow[changedcol] = new Integer(change); tablerow[wlistcol] = new Boolean(false); // blacklisted user -- either in the explicit list or covered by regexp blacklist on user if (blacklistModel.contains(username+"#"+projname)) tablerow[blistcol] = new Boolean(true); else { tablerow[blistcol] = new Boolean(false); a = regexpblackModel.getSize(); for(int j=0;j<a;j++) if (rblackuser.isSelected() && username.matches((String)regexpblackModel.getElementAt(j))) { tablerow[blistcol]=new Boolean(true); break; } }

//watchlisted page -- either in the explicit list or covered by regexp blacklist on page or summary if (watchlistModel.contains(pagename+"#"+projname)) tablerow[watchcol] = new Boolean(true); else { tablerow[watchcol] = new Boolean(false); a = regexpblackModel.getSize(); for(int j=0;j<a;j++) if ( (rblackpage.isSelected() && pagename.matches((String)regexpblackModel.getElementAt(j))) || (rblacksummary.isSelected() && summary.matches((String)regexpblackModel.getElementAt(j))) ) { tablerow[watchcol]=new Boolean(true); break; } } tablerow[twhitecol] = new Boolean(false); // temp blacklist if (tempblacklistModel.contains(username+"#"+projname)) tablerow[tblackcol] = new Boolean(true); else tablerow[tblackcol] = new Boolean(false);

// temp watchlist if (tempwatchlistModel.contains(pagename+"#"+projname)) tablerow[twatchcol] = new Boolean(true); else tablerow[twatchcol] = new Boolean(false);

// END ROW SETUP backendModel.insertRow(0,tablerow);

/* This is to keep the program from eating up ungodly amounts of memory. People can easily clear the displayed table by clicking a button, but since this backend table will only realistically be used for short periods of time, it can stay "small". It could likely be dropped down to 1000 entries and still have the same effect. */ if (backendModel.getRowCount()>5000) backendModel.setRowCount(4000);

// If a page is deleted then it removes it from the list, if the user has the option turned on if (pagename.equals("Special:Log/delete") && olddeleted.isSelected()) { StringTokenizer str = new StringTokenizer(summary,"\""); str.nextToken(); String tempstr = new String(str.nextToken());

if (watchdeleted.isSelected() && !watchlistModel.contains(tempstr+"#"+projname) && !tempwatchlistModel.contains(tempstr+"#"+projname)) { if (watchdelpermButton.isSelected()) watchlistModel.addElement(tempstr+"#"+projname); else tempwatchlistModel.addElement(tempstr+"#"+projname); } a = backendModel.getRowCount();

if (blackdeleted.isSelected()) for(i=0;i<a;i++) if ( ((Boolean)backendModel.getValueAt(i,newecol)).booleanValue() && // new page tempstr.equals((String)backendModel.getValueAt(i,articlecol)) && // same article projname.equals((String)backendModel.getValueAt(i,projectcol)) && // same project !whitelistModel.contains((String)backendModel.getValueAt(i,editorcol)+"#"+projname) && // don't blacklist a whitelisted editor !blacklistModel.contains((String)backendModel.getValueAt(i,editorcol)+"#"+projname) && // don't blacklist an already blacklisted editor !tempwhitelistModel.contains((String)backendModel.getValueAt(i,editorcol)+"#"+projname) && // don't blacklist a whitelisted editor !tempblacklistModel.contains((String)backendModel.getValueAt(i,editorcol)+"#"+projname)) // don't blacklist an already blacklisted editor { if (delpagepermButton.isSelected()) blacklistModel.addElement((String)backendModel.getValueAt(i,editorcol)+"#"+projname); else tempblacklistModel.addElement((String)backendModel.getValueAt(i,editorcol)+"#"+projname); break; }


a = editstableModel.getRowCount();

editstableScrollBar = editstableScroller.getVerticalScrollBar();

for(i=0;i<a;i++) { if (tempstr.equals((String)editstableModel.getValueAt(i,articlecol)) && projname.equals((String)editstableModel.getValueAt(i,projectcol))) {

if (autoscroll.isSelected() && editstableScrollBar.getValue() > 0 && editstableScrollBar.getValue() + editstableScrollBar.getVisibleAmount() +32 >= editstableScrollBar.getMaximum()) { editstableModel.removeRow(i); editstableScrollBar.setValue(editstableScrollBar.getMaximum()-editstableScrollBar.getVisibleAmount()); } else editstableModel.removeRow(i);

return; } } }

// This throws out other special edits, like Special:Log/upload and Special:Log/block (though I'm not even sure if that shows up in the RC feed) if (pagename.length() > 10 && pagename.substring(0,8).equals("Special:")) { return; }

if (whitelistModel.contains(username+"#"+projname) && blackreverted.isSelected() && summary.matches("^Reverted edits by.*")) { Pattern p = Pattern.compile("^Reverted edits by \\u005B\\u005B([^\\u007C\\u005B\\u005D]*)\\u007C([^\\u007C\\u005B\\u005D]*)\\u005D\\u005D.*"); Matcher m = p.matcher(summary); String s = new String();

if (m.find()) { s = m.group(2);

// No penalty for reverting yourself -- cannot be moved from the whitelist to the blacklist if (!s.equals(username) && !whitelistModel.contains(s+"#"+projname) && !tempwhitelistModel.contains(s+"#"+projname) && !blacklistModel.contains(s+"#"+projname) && !tempblacklistModel.contains(s+"#"+projname)) { if (revertpermButton.isSelected()) blacklistModel.addElement(s+"#"+projname); else tempblacklistModel.addElement(s+"#"+projname); } } }

a = editstableModel.getRowCount(); // If this edit is on a page already in the list, remove the old one (if the option is turned on) if (olddeleted.isSelected()) for(i=0;i<a;i++) { if(pagename.equals((String)editstableModel.getValueAt(i,articlecol)) && projname.equals((String)editstableModel.getValueAt(i,projectcol))) { editstableModel.removeRow(i); break; } }


// Don't care about whitelisted users, drop edit if (whitelisted(pagename, username, summary, projname)) return;

// anything that matches any of the watchlist/blacklist criteria will be processed, regardless of the "show only" sections if ( ( (showips.isSelected() && !isValidIP(username)) || (newpages.isSelected() && !newpage) || showwatch.isSelected() ) && listprecedence.isSelected() && !watched(pagename, username, summary, projname, change, ((Boolean)tablerow[movecol]).booleanValue(), newpage) ) return;

// Without this +32 in here, the scrollbar gets lost.. getvalue + getvisibleamount should = getmaximum, but it doesn't, hence the need for this "buffer" if (reversetable.isSelected()) editstableModel.insertRow(0,tablerow); else editstableModel.addRow(tablerow);

editstableScrollBar = editstableScroller.getVerticalScrollBar();

if (autoscroll.isSelected() && editstableScrollBar.getValue() > 0 && editstableScrollBar.getValue() + editstableScrollBar.getVisibleAmount() +32 >= editstableScrollBar.getMaximum()) { editstableScrollBar.setValue(editstableScrollBar.getMaximum()-editstableScrollBar.getVisibleAmount()); }

editstableTable.repaint(); }

public void mouseClicked(MouseEvent e) { StringTokenizer stt;

if (e.getSource() == whitelistList) { JList jlist = (JList)e.getSource(); int index = jlist.locationToIndex(e.getPoint());

if (e.getClickCount()%2 == 0) { try { String str = new String(((String)whitelistModel.elementAt(index)).replace(' ', '_')); stt = new StringTokenizer(str,"#"); String st1 = stt.nextToken(), st2 = stt.nextToken();

if (browserpick.isSelected()) BrowserLauncher.openURL("http://"+st2+".org/w/index.php?title=Special:Contributions&target=" + st1 ); else Runtime.getRuntime().exec(browserField.getText().trim() + " http://"+st2+".org/w/index.php?title=Special:Contributions&target=" + st1 ); } catch (Exception ex) {} } } else if (e.getSource() == blacklistList) { JList jlist = (JList)e.getSource(); int index = jlist.locationToIndex(e.getPoint());

if (e.getClickCount()%2 == 0) { try { String str = new String(((String)blacklistModel.elementAt(index)).replace(' ', '_'));

stt = new StringTokenizer(str,"#"); String st1 = stt.nextToken(), st2 = stt.nextToken();

if (browserpick.isSelected()) BrowserLauncher.openURL("http://"+st2+".org/w/index.php?title=Special:Contributions&target=" + st1 ); else Runtime.getRuntime().exec(browserField.getText().trim() + " http://"+st2+".org/w/index.php?title=Special:Contributions&target=" + st1 ); } catch (Exception ex) {} } } else if (e.getSource() == watchlistList) { JList jlist = (JList)e.getSource(); int index = jlist.locationToIndex(e.getPoint());

if (e.getClickCount()%2 == 0) { try { String str = new String(((String)watchlistModel.elementAt(index)).replace(' ', '_'));

stt = new StringTokenizer(str,"#"); String st1 = stt.nextToken(), st2 = stt.nextToken();

if (browserpick.isSelected()) BrowserLauncher.openURL("http://"+st2+".org/wiki/" + st1); else Runtime.getRuntime().exec(browserField.getText().trim() + " http://"+st2+".org/wiki/" + st1);

} catch (Exception ex) {} } } else if (e.getSource() == editstableTable) { if (e.getClickCount()%2 == 0 || singleclick.isSelected()) { TableColumnModel columnModel = editstableTable.getColumnModel(); int viewColumn = columnModel.getColumnIndexAtX(e.getX()); int column = editstableTable.convertColumnIndexToModel(viewColumn); int target = e.getY(); int row = -1, where = 0; while ((where < target) && (row < editstableTable.getRowCount())) { row++; where += editstableTable.getRowHeight(row); } if (column==xcol) editstableModel.removeRow(row); else if (column==articlecol || column==summarycol) // article or summary try { if (browserpick.isSelected()) BrowserLauncher.openURL((String)editstableModel.getValueAt(row,urlcol)); else Runtime.getRuntime().exec(browserField.getText().trim() + " " + (String)editstableModel.getValueAt(row,urlcol));

if (removereviewed.isSelected()) editstableModel.removeRow(row); } catch (Exception ex) {} else if (column==editorcol) //editor try { String str = new String(((String)editstableModel.getValueAt(row, editorcol)).replace(' ', '_'));

if (browserpick.isSelected()) BrowserLauncher.openURL("http://"+ (String)editstableModel.getValueAt(row,projectcol) + ".org/w/index.php?title=Special:Contributions&target=" + str); else Runtime.getRuntime().exec(browserField.getText().trim() + " http://"+ (String)editstableModel.getValueAt(row,projectcol) + ".org/w/index.php?title=Special:Contributions&target=" + str);

} catch (Exception ex) {} else if (column==bcol) // block try { String str = new String(((String)editstableModel.getValueAt(row, editorcol)).replace(' ', '_')); if (blockButton.isSelected()) { if (browserpick.isSelected()) BrowserLauncher.openURL("http://"+ (String)editstableModel.getValueAt(row,projectcol) + ".org/w/index.php?title=Special:Blockip&ip=" + str); else Runtime.getRuntime().exec(browserField.getText().trim() + " http://"+ (String)editstableModel.getValueAt(row,projectcol) + ".org/w/index.php?title=Special:Blockip&ip=" + str); } else { if (browserpick.isSelected()) BrowserLauncher.openURL("http://en.wikipedia.org/wiki/Wikipedia:Vandalism_in_progress"); else Runtime.getRuntime().exec(browserField.getText().trim() + " http://en.wikipedia.org/wiki/Wikipedia:Vandalism_in_progress"); } } catch (Exception ex) {} else if (column==tcol) // talk try { String str = new String(((String)editstableModel.getValueAt(row, editorcol)).replace(' ', '_')); if (browserpick.isSelected()) BrowserLauncher.openURL("http://"+ (String)editstableModel.getValueAt(row,projectcol) + ".org/wiki/User_talk:" + str); else Runtime.getRuntime().exec(browserField.getText().trim() + " http://"+ (String)editstableModel.getValueAt(row,projectcol) + ".org/wiki/User_talk:" + str); } catch (Exception ex) {} } } }

public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {}

private static boolean isValidIP(String IP) { return validip.matcher(IP).matches(); }

public void savefiles() { File whitelistFile = new File("vfdata.dat"); FileOutputStream fos; ObjectOutputStream oos;

int i; try { fos = new FileOutputStream(whitelistFile); oos = new ObjectOutputStream(fos); oos.writeObject(whitelistModel); oos.writeObject(blacklistModel); oos.writeObject(watchlistModel); oos.writeObject(new Boolean(showips.isSelected())); oos.writeObject(new Boolean(newpages.isSelected())); oos.writeObject(channelField.getText()); oos.writeObject(serverField.getText()); oos.writeObject(portField.getText()); oos.writeObject(new Boolean(olddeleted.isSelected())); oos.writeObject(new Boolean(autoscroll.isSelected())); oos.writeObject(new Integer(totalcols)); for(i=0;i<totalcols;i++) oos.writeObject( new Integer( editstableTable.getColumnModel().getColumn(i).getWidth() ) ); oos.writeObject(new Integer((int)getSize().getWidth())); oos.writeObject(new Integer((int)getSize().getHeight())); oos.writeObject(new Boolean(singleclick.isSelected())); oos.writeObject(whitelistimportField.getText()); oos.writeObject(new Boolean(colorips.isSelected())); oos.writeObject(new Boolean(colornew.isSelected())); oos.writeObject(new Boolean(colorblist.isSelected())); oos.writeObject(new Boolean(colorwatch.isSelected())); oos.writeObject(new Boolean(showwatch.isSelected())); oos.writeObject(new Boolean(queueedits.isSelected())); oos.writeObject(new Boolean(newversion.isSelected())); oos.writeObject(new Boolean(browserpick.isSelected())); oos.writeObject(browserField.getText()); oos.writeObject(new Boolean(removereviewed.isSelected())); for(i=0;i<totalcols;i++) oos.writeObject(new Integer(editstableTable.getTableHeader().getColumnModel().getColumnIndex(columnNames[i]))); oos.writeObject(new Boolean(stripformatting.isSelected())); oos.writeObject(new Boolean(colorchanged.isSelected())); oos.writeObject(changedField.getText()); oos.writeObject(new Boolean(colormoves.isSelected())); oos.writeObject(regexpwhiteModel); oos.writeObject(regexpblackModel); oos.writeObject(new Boolean(rwhiteuser.isSelected())); oos.writeObject(new Boolean(rwhitepage.isSelected())); oos.writeObject(new Boolean(rwhitesummary.isSelected())); oos.writeObject(new Boolean(rblackuser.isSelected())); oos.writeObject(new Boolean(rblackpage.isSelected())); oos.writeObject(new Boolean(rblacksummary.isSelected())); oos.writeObject(new Boolean(listprecedence.isSelected())); oos.writeObject(new Boolean(reversetable.isSelected())); oos.writeObject(blacklistcolor); oos.writeObject(watchlistcolor); oos.writeObject(changedcolor); oos.writeObject(movecolor); oos.writeObject(newcolor); oos.writeObject(ipcolor); oos.writeObject(new Boolean(coloruserpage.isSelected())); oos.writeObject(userpagecolor); oos.writeObject(new Boolean(blackreverted.isSelected())); oos.writeObject(new Boolean(watchdeleted.isSelected())); oos.writeObject(new Boolean(blackdeleted.isSelected())); oos.writeObject(new Boolean(watchuserpages.isSelected())); oos.writeObject(new Boolean(watchmasschanges.isSelected())); oos.writeObject(new Boolean(watchpagemoves.isSelected())); oos.writeObject(new Boolean(watchnewpages.isSelected())); oos.writeObject(new Boolean(revertpermButton.isSelected())); oos.writeObject(new Boolean(delpagepermButton.isSelected())); oos.writeObject(new Boolean(watchdelpermButton.isSelected())); oos.writeObject(new Boolean(blockButton.isSelected())); oos.writeObject(defaultprojectField.getText()); oos.close(); fos.close(); } catch (Exception e) {} }

public void loadfiles() { File whitelistFile = new File("vfdata.dat"); FileInputStream fis; ObjectInputStream ois;

int i,j, cols, colorder[] = new int[totalcols], colwidths[] = new int[totalcols];

for (i=0;i<totalcols;i++) colorder[i] = i; for (i=0;i<totalcols;i++) colwidths[i] = lcb;

try { fis = new FileInputStream(whitelistFile); ois = new ObjectInputStream(fis); whitelistModel = (DefaultListModel)ois.readObject(); blacklistModel = (DefaultListModel)ois.readObject(); watchlistModel = (DefaultListModel)ois.readObject(); if (((Boolean)ois.readObject()).booleanValue() == true) showips.setSelected(true); if (((Boolean)ois.readObject()).booleanValue() == true) newpages.setSelected(true); channelField.setText((String)ois.readObject()); serverField.setText((String)ois.readObject()); portField.setText((String)ois.readObject()); if (((Boolean)ois.readObject()).booleanValue() == false) olddeleted.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) autoscroll.setSelected(false); cols = ((Integer)ois.readObject()).intValue(); for(i=0;i<cols;i++) colwidths[i]=((Integer)ois.readObject()).intValue(); appwidth = ((Integer)ois.readObject()).intValue(); appheight = ((Integer)ois.readObject()).intValue(); if (((Boolean)ois.readObject()).booleanValue() == false) singleclick.setSelected(false); whitelistimportField.setText((String)ois.readObject()); if (((Boolean)ois.readObject()).booleanValue() == false) colorips.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) colornew.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) colorblist.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) colorwatch.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == true) showwatch.setSelected(true); if (((Boolean)ois.readObject()).booleanValue() == false) queueedits.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) newversion.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) browserpick.setSelected(false); browserField.setText((String)ois.readObject()); if (((Boolean)ois.readObject()).booleanValue() == true) removereviewed.setSelected(true); for(i=0;i<cols;i++) colorder[i]=((Integer)ois.readObject()).intValue(); if (((Boolean)ois.readObject()).booleanValue() == false) stripformatting.setSelected(false); for(j=0;j<totalcols;j++) for(i=0;i<totalcols;i++) if (colorder[i]!= editstableTable.getTableHeader().getColumnModel().getColumnIndex(columnNames[i])) editstableTable.getTableHeader().getColumnModel().moveColumn(colorder[i], editstableTable.getTableHeader().getColumnModel().getColumnIndex(columnNames[i])); for(i=0;i<totalcols;i++) editstableTable.getColumnModel().getColumn(i).setPreferredWidth( colwidths[i] ); if (((Boolean)ois.readObject()).booleanValue() == false) colorchanged.setSelected(false); changedField.setText((String)ois.readObject()); if (((Boolean)ois.readObject()).booleanValue() == false) colormoves.setSelected(false); regexpwhiteModel = (DefaultListModel)ois.readObject(); regexpblackModel = (DefaultListModel)ois.readObject();

if (((Boolean)ois.readObject()).booleanValue() == true) rwhiteuser.setSelected(true); if (((Boolean)ois.readObject()).booleanValue() == false) rwhitepage.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == true) rwhitesummary.setSelected(true); if (((Boolean)ois.readObject()).booleanValue() == false) rblackuser.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) rblackpage.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) rblacksummary.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) listprecedence.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == true) reversetable.setSelected(true); blacklistcolor = (Color)ois.readObject(); watchlistcolor = (Color)ois.readObject(); changedcolor = (Color)ois.readObject(); movecolor = (Color)ois.readObject(); newcolor = (Color)ois.readObject(); ipcolor = (Color)ois.readObject(); if (((Boolean)ois.readObject()).booleanValue() == false) coloruserpage.setSelected(false); userpagecolor = (Color)ois.readObject(); if (((Boolean)ois.readObject()).booleanValue() == false) blackreverted.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) watchdeleted.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) blackdeleted.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) watchuserpages.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) watchmasschanges.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) watchpagemoves.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) watchnewpages.setSelected(false); if (((Boolean)ois.readObject()).booleanValue() == false) { revertpermButton.setSelected(false); reverttempButton.setSelected(true); } else { revertpermButton.setSelected(true); reverttempButton.setSelected(false); } if (((Boolean)ois.readObject()).booleanValue() == false) { delpagepermButton.setSelected(false); delpagetempButton.setSelected(true); } else { delpagepermButton.setSelected(true); delpagetempButton.setSelected(false); } if (((Boolean)ois.readObject()).booleanValue() == false) { watchdelpermButton.setSelected(false); watchdeltempButton.setSelected(true); } else { watchdelpermButton.setSelected(true); watchdeltempButton.setSelected(false); } if (((Boolean)ois.readObject()).booleanValue() == true) { blockButton.setSelected(true); vipButton.setSelected(false); } else { blockButton.setSelected(false); vipButton.setSelected(true); } defaultprojectField.setText((String)ois.readObject());

ois.close(); fis.close(); } catch (Exception e) {} }

// If the option is set, this class is instantiated once to check the current version class versionchecker extends Thread { private URL versionURL; private BufferedInputStream versionbuf; int i; String verstr= new String(""); private JFrame parent;

versionchecker(JFrame p) { parent = p; start(); }

public void run() { try { versionURL = new URL("http://www.derk.org/cdvfversion"); versionbuf = new BufferedInputStream(versionURL.openConnection().getInputStream()); i = versionbuf.available();

while (i>0) { byte b[] = new byte[i]; versionbuf.read(b); verstr = new String(verstr + new String(b)); Thread.sleep(100); i =versionbuf.available(); } if (Integer.parseInt(verstr.trim()) > verint) JOptionPane.showMessageDialog(parent, "New version is available!\nDownload at http://cdvf.derk.org/"); } catch (Exception e) {} }

}

public void whitelistimport(String toadd) { if (!whitelistModel.contains(toadd)) { if (blacklistModel.contains(toadd)) { blacklistModel.removeElement(toadd); } whitelistModel.addElement(toadd); } }

class adminimporter extends Thread { String l, webpage, tmp, oldstatus; StringTokenizer parser; int i, j; private URL adminURL; private BufferedInputStream adminbuf;


adminimporter(String lang) { // just in case someone puts the .org on there if (lang.substring(lang.length()-4).equals(".org")) l = lang.substring(0,lang.length()-4); else l = lang;

start(); }

void cleanup(String status) { try { statusLabel.setText(status); savefiles(); // This sleep is here to give the person time to read the status message Thread.sleep(3000); if (connected) chanstatus(); else statusLabel.setText(oldstatus); whitelistList.repaint(); } catch (Exception e) {} importadminsButton.setEnabled(true); whitelistimportField.setEditable(true); }

public void run() { webpage = new String(""); tmp = new String();

oldstatus = statusLabel.getText(); statusLabel.setText("Importing admins from " + l + " (may take a few moments)"); try { adminURL = new URL("http://" + l + ".org/w/index.php?title=Special:Listadmins&limit=10000&offset=0"); adminbuf = new BufferedInputStream(adminURL.openConnection().getInputStream()); i = adminbuf.available(); whitelistList.clearSelection();

while (i>0) { byte b[] = new byte[i]; adminbuf.read(b); webpage = new String(webpage + new String(b)); // Delay here otherwise there won't be anything available for next read Thread.sleep(100); i = adminbuf.available(); }

Pattern p = Pattern.compile("

  • <a href=\"/wiki/[^\"]*\" title=\"[^:]*:([^\"]*)\""); Matcher m = p.matcher(webpage); while (m.find()) { whitelistimport(m.group(1)+"#"+l); } Thread.sleep(100); int tmp = editstableModel.getRowCount(); for(j=tmp-1;j>=0;j--) if (whitelistModel.contains((String)editstableModel.getValueAt(j,editorcol)+"#"+(String)editstableModel.getValueAt(j,projectcol))) editstableModel.removeRow(j); cleanup("Successfully imported admins from " + l); } catch (Exception exc) { int tmp = editstableModel.getRowCount(); for(j=tmp-1;j>=0;j--) if (whitelistModel.contains((String)editstableModel.getValueAt(j,editorcol)+"#"+(String)editstableModel.getValueAt(j,projectcol))) editstableModel.removeRow(j); cleanup("Failed to import admins from " + l); } whitelistList.clearSelection(); } } class IRC extends Thread { String channel, server, projname; public String editsummary, username, pagename, url; public int change; public boolean minor, newpage, quitvar=false, pausevar=false, notnegotiated=true, moveflag; Socket s; BufferedReader in; public PrintWriter out; String line, lastchan = new String(); int length, m1, m2, m3, i, j, port, a, b; GregorianCalendar c; String ts1, ts2, time; JFrame parent; IRC(String c, String ser, String por, JFrame p) { channel = c; server = ser; try{ port = Integer.parseInt(por); } catch (Exception e) { portField.setText("6667"); port = 6667; } parent = p; start(); } public void joinchannel(String chan) { quitvar=false; lastchan = chan; out.println("join " + chan); out.flush(); updatechanstatus(chan,true); } public void die(String s) { statusLabel.setText(s); servers.removeAllElements(); serverField.setEditable(true); portField.setEditable(true); connected=false; } public void quit() { quitvar=true; out.println("quit :" + version + ", get it at http://cdvf.derk.org/ !"); out.flush(); die("Disconnected."); } public void run() { statusLabel.setText("Connecting to IRC..."); try { s = new Socket(server, port); in = new BufferedReader(new InputStreamReader(s.getInputStream(), "UTF-8")); out = new PrintWriter(s.getOutputStream()); i=0; while ((line = in.readLine()) != null) { // For a graceful thread death, we wait until another line is received to actually quit if (quitvar) { return; } // If queued edits exist and the program is unpaused, throw them in the table if (!pausevar && queueedits.isSelected()) { Enumeration enu = pausededits.elements(); while (enu.hasMoreElements()) { pagename = (String)enu.nextElement(); url = (String)enu.nextElement(); username = (String)enu.nextElement(); editsummary = (String)enu.nextElement(); change = ((Integer)enu.nextElement()).intValue(); minor = ((Boolean)enu.nextElement()).booleanValue(); newpage = ((Boolean)enu.nextElement()).booleanValue(); projname = (String)enu.nextElement(); moveflag = ((Boolean)enu.nextElement()).booleanValue(); time = (String)enu.nextElement(); addnewtableentry(pagename, url, username, editsummary, change, minor, newpage, projname, moveflag, time); } pausededits.removeAllElements(); } // respond to pings to stay alive if (line.substring(0,4).equals("PING")) { out.println("pong " + server); out.flush(); savefiles(); continue; } // Unable to join channel if (line.matches("^:irc.wikimedia.org .*:No such channel")) { updatechanstatus(lastchan,false); continue; } // If the link is severed by the server (say it is shut down or something) if (line.matches("^ERROR :Closing Link.*")) { die("Disconnected by server."); return; } // Just skip the line if we're paused AND dumping edits (no queueing) if (pausevar && !queueedits.isSelected()) continue; try { i++; /* Ideally we'd not just wait for 3 lines, but the last line can be one of two things -- incrementing i is cheap, but just to save time here we set a boolean variable that will be faster than comparing an int */ if (notnegotiated && i==3) { Thread.sleep(2000); String tstr = new String("" + System.currentTimeMillis()); out.println("nick cd" + verint + "" + tstr.substring(8)); out.flush(); Thread.sleep(1000); out.println("user cdvf cdvf cdvf :cdvf"); out.flush(); Thread.sleep(1000); joinchannel(channel); notnegotiated = true; continue; } /* Yes, I realize this is a horrible horrible way to parse things, but it was literally the first thing I came up with in the program. I know it could be replaced by regexps, but coding time would be better spent elsewhere and the fact that this might be relatively slow is not important given that only an edit or two may happen in a second. */ StringTokenizer st = new StringTokenizer(line, "# "); st.nextToken(); st.nextToken(); projname = new String(st.nextToken()); st = new StringTokenizer(line, "@ "); if (st.hasMoreTokens()) { st.nextToken(); // Only process messages from localhost if (st.nextToken().equals("127.0.0.1")) { char ln[] = line.toCharArray(); length = line.length(); boolean bracketpassed=false; for(j=0;j<length;j++) { if (!bracketpassed && Character.getType(ln[j]) == 15) { ln[j]=ln[j+1]=ln[j+2]=ln[j+5]=ln[j+6]=ln[j+7]=' '; j+=7; bracketpassed=true; } else if (Character.getType(ln[j]) == 15) { ln[j]=' '; if (j+1 < length && Character.getType(ln[j+1]) == 9) { ln[j+1] = ' '; if (j+2 < length && Character.getType(ln[j+2]) == 9) ln[j+2] = ' '; } } } String cleanline = new String(ln); st = new StringTokenizer(cleanline, "[]"); st.nextToken(); pagename = new String(st.nextToken().trim()); String next = new String(st.nextToken().trim()); // this will at the very least contain everything up to the edit summary minor=newpage=false; if (next.charAt(0)=='M') { minor = true; if (next.charAt(1)=='N') newpage = true; } else if (next.charAt(0)=='N') newpage = true; st = new StringTokenizer(next, " "); if (minor | newpage) st.nextToken(); url = new String(st.nextToken()); ln = cleanline.toCharArray(); length=cleanline.length(); m1=0;m2=0;m3=0; for(j=0;j<length;j++) { if (m1 == 0 && j<(length-3) && ln[j] == '*' && ln[j-3] == ' ' && ln[j-2] == ' ' && ln[j-1] == ' ' && ln[j+1] == ' ' && ln[j+2] == ' ' && ln[j+3] == ' ') { m1 = j+6; // M1 is where user name starts j+=6; } else if (m2 == 0 && m1>0 && ln[j]== ' ' && ln[j+1] == ' ' && ln[j+2] == ' ' && ln[j+3] == ' ' && ln[j+4]=='*') { m2=j-1; // m2 is where the user name ends, m2 + 8 is where the # of chars changed starts j+=5; } else if (m3 == 0 && m2>0 && ln[j] == ')') { m3=j-1; // m3 is where the # of chars changed ends break; } } username = new String(cleanline.substring(m1, m2+1).trim()); // Some lines (page moves, Special:Log stuff) come through with no (+/-X) change part, so here we deal with that if (cleanline.substring(m2+8).matches(".*\\([\\+-]\\d+\\).*") || cleanline.substring(m2+8).matches(".*\\( [\\+-]\\d+ \\).*")) { String tempstring = new String(cleanline.substring(m2+9,m3+1).trim()); if (tempstring.charAt(0) == '+') change = Integer.parseInt(tempstring.substring(1,tempstring.length())); else change = Integer.parseInt(tempstring); if (m3+6>length) editsummary = new String(""); else editsummary = new String(cleanline.substring(m3+6).trim()); moveflag = false; } else { change=0; moveflag=true; editsummary = new String(cleanline.substring(m2+9).trim()); } c = new GregorianCalendar(); a = c.get(Calendar.MINUTE); b = c.get(Calendar.SECOND); if (a<10) ts1 = new String("0" + a); else ts1 = new String("" + a); if (b<10) ts2 = new String("0" + b); else ts2 = new String("" + b); time = new String("" + c.get(Calendar.HOUR) + ":" + ts1 + ":" + ts2); if (pausevar) { pausededits.add(pagename); pausededits.add(url); pausededits.add(username); pausededits.add(editsummary); pausededits.add(new Integer(change)); pausededits.add(new Boolean(minor)); pausededits.add(new Boolean(newpage)); pausededits.add(projname); pausededits.add(new Boolean(moveflag)); pausededits.add(time); } else addnewtableentry(pagename, url, username, editsummary, change, minor, newpage, projname, moveflag, time); Thread.sleep(250); } } } catch (Exception ex) // this should never happen, but just in case.... { die("Disconnected by server."); return; } } } catch (Exception e) { die("Problem connecting to server (try irc.wikimedia.org port 6667 or browne.wikimedia.org port 6667)."); return; } } } public static void main(String args[]) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { } vf app = new vf(); } } /* THE CODE BELOW IS VERBATIM FROM browserlauncher.sourceforge.net. IT IS NOT SUBJECT TO THE LICENSING ABOVE -- ITS LICENSE INFO IS DESCRIBED BELOW */ /** * BrowserLauncher is a class that provides one static method, openURL, which opens the default * web browser for the current user of the system to the given URL. It may support other * protocols depending on the system -- mailto, ftp, etc. -- but that has not been rigorously * tested and is not guaranteed to work. *

    * Yes, this is platform-specific code, and yes, it may rely on classes on certain platforms * that are not part of the standard JDK. What we're trying to do, though, is to take something * that's frequently desirable but inherently platform-specific -- opening a default browser -- * and allow programmers (you, for example) to do so without worrying about dropping into native * code or doing anything else similarly evil. *

    * Anyway, this code is completely in Java and will run on all JDK 1.1-compliant systems without * modification or a need for additional libraries. All classes that are required on certain * platforms to allow this to run are dynamically loaded at runtime via reflection and, if not * found, will not cause this to do anything other than returning an error when opening the * browser. *

    * There are certain system requirements for this class, as it's running through Runtime.exec(), * which is Java's way of making a native system call. Currently, this requires that a Macintosh * have a Finder which supports the GURL event, which is true for Mac OS 8.0 and 8.1 systems that * have the Internet Scripting AppleScript dictionary installed in the Scripting Additions folder * in the Extensions folder (which is installed by default as far as I know under Mac OS 8.0 and * 8.1), and for all Mac OS 8.5 and later systems. On Windows, it only runs under Win32 systems * (Windows 95, 98, and NT 4.0, as well as later versions of all). On other systems, this drops * back from the inherently platform-sensitive concept of a default browser and simply attempts * to launch Netscape via a shell command. *

    * This code is Copyright 1999-2001 by Eric Albert (ejalbert@cs.stanford.edu) and may be * redistributed or modified in any form without restrictions as long as the portion of this * comment from this paragraph through the end of the comment is not removed. The author * requests that he be notified of any application, applet, or other binary that makes use of * this code, but that's more out of curiosity than anything and is not required. This software * includes no warranty. The author is not repsonsible for any loss of data or functionality * or any adverse or unexpected effects of using this software. *

    * Credits: *
    Steven Spencer, JavaWorld magazine (<a href="http://www.javaworld.com/javaworld/javatips/jw-javatip66.html">Java Tip 66</a>) *
    Thanks also to Ron B. Yeh, Eric Shapiro, Ben Engber, Paul Teitlebaum, Andrea Cantatore, * Larry Barowski, Trevor Bedzek, Frank Miedrich, and Ron Rabakukk * * @author Eric Albert (<a href="mailto:ejalbert@cs.stanford.edu">ejalbert@cs.stanford.edu</a>) * @version 1.4b1 (Released June 20, 2001) */ class BrowserLauncher { /** * The Java virtual machine that we are running on. Actually, in most cases we only care * about the operating system, but some operating systems require us to switch on the VM. */ private static int jvm; /** The browser for the system */ private static Object browser; /** * Caches whether any classes, methods, and fields that are not part of the JDK and need to * be dynamically loaded at runtime loaded successfully. *

    * Note that if this is false, openURL() will always return an * IOException. */ private static boolean loadedWithoutErrors; /** The com.apple.mrj.MRJFileUtils class */ private static Class mrjFileUtilsClass; /** The com.apple.mrj.MRJOSType class */ private static Class mrjOSTypeClass; /** The com.apple.MacOS.AEDesc class */ private static Class aeDescClass; /** The <init>(int) method of com.apple.MacOS.AETarget */ private static Constructor aeTargetConstructor; /** The <init>(int, int, int) method of com.apple.MacOS.AppleEvent */ private static Constructor appleEventConstructor; /** The <init>(String) method of com.apple.MacOS.AEDesc */ private static Constructor aeDescConstructor; /** The findFolder method of com.apple.mrj.MRJFileUtils */ private static Method findFolder; /** The getFileCreator method of com.apple.mrj.MRJFileUtils */ private static Method getFileCreator; /** The getFileType method of com.apple.mrj.MRJFileUtils */ private static Method getFileType; /** The openURL method of com.apple.mrj.MRJFileUtils */ private static Method openURL; /** The makeOSType method of com.apple.MacOS.OSUtils */ private static Method makeOSType; /** The putParameter method of com.apple.MacOS.AppleEvent */ private static Method putParameter; /** The sendNoReply method of com.apple.MacOS.AppleEvent */ private static Method sendNoReply; /** Actually an MRJOSType pointing to the System Folder on a Macintosh */ private static Object kSystemFolderType; /** The keyDirectObject AppleEvent parameter type */ private static Integer keyDirectObject; /** The kAutoGenerateReturnID AppleEvent code */ private static Integer kAutoGenerateReturnID; /** The kAnyTransactionID AppleEvent code */ private static Integer kAnyTransactionID; /** The linkage object required for JDirect 3 on Mac OS X. */ private static Object linkage; /** The framework to reference on Mac OS X */ private static final String JDirect_MacOSX = "/System/Library/Frameworks/Carbon.framework/Frameworks/HIToolbox.framework/HIToolbox"; /** JVM constant for MRJ 2.0 */ private static final int MRJ_2_0 = 0; /** JVM constant for MRJ 2.1 or later */ private static final int MRJ_2_1 = 1; /** JVM constant for Java on Mac OS X 10.0 (MRJ 3.0) */ private static final int MRJ_3_0 = 3; /** JVM constant for MRJ 3.1 */ private static final int MRJ_3_1 = 4; /** JVM constant for any Windows NT JVM */ private static final int WINDOWS_NT = 5; /** JVM constant for any Windows 9x JVM */ private static final int WINDOWS_9x = 6; /** JVM constant for any other platform */ private static final int OTHER = -1; /** * The file type of the Finder on a Macintosh. Hardcoding "Finder" would keep non-U.S. English * systems from working properly. */ private static final String FINDER_TYPE = "FNDR"; /** * The creator code of the Finder on a Macintosh, which is needed to send AppleEvents to the * application. */ private static final String FINDER_CREATOR = "MACS"; /** The name for the AppleEvent type corresponding to a GetURL event. */ private static final String GURL_EVENT = "GURL"; /** * The first parameter that needs to be passed into Runtime.exec() to open the default web * browser on Windows. */ private static final String FIRST_WINDOWS_PARAMETER = "/c"; /** The second parameter for Runtime.exec() on Windows. */ private static final String SECOND_WINDOWS_PARAMETER = "start"; /** * The third parameter for Runtime.exec() on Windows. This is a "title" * parameter that the command line expects. Setting this parameter allows * URLs containing spaces to work. */ private static final String THIRD_WINDOWS_PARAMETER = "\"\""; /** * The shell parameters for Netscape that opens a given URL in an already-open copy of Netscape * on many command-line systems. */ private static final String NETSCAPE_REMOTE_PARAMETER = "-remote"; private static final String NETSCAPE_OPEN_PARAMETER_START = "'openURL("; private static final String NETSCAPE_OPEN_PARAMETER_END = ")'"; /** * The message from any exception thrown throughout the initialization process. */ private static String errorMessage; /** * An initialization block that determines the operating system and loads the necessary * runtime data. */ static { loadedWithoutErrors = true; String osName = System.getProperty("os.name"); if (osName.startsWith("Mac OS")) { String mrjVersion = System.getProperty("mrj.version"); String majorMRJVersion = mrjVersion.substring(0, 3); try { double version = Double.valueOf(majorMRJVersion).doubleValue(); if (version == 2) { jvm = MRJ_2_0; } else if (version >= 2.1 && version < 3) { // Assume that all 2.x versions of MRJ work the same. MRJ 2.1 actually // works via Runtime.exec() and 2.2 supports that but has an openURL() method // as well that we currently ignore. jvm = MRJ_2_1; } else if (version == 3.0) { jvm = MRJ_3_0; } else if (version >= 3.1) { // Assume that all 3.1 and later versions of MRJ work the same. jvm = MRJ_3_1; } else { loadedWithoutErrors = false; errorMessage = "Unsupported MRJ version: " + version; } } catch (NumberFormatException nfe) { loadedWithoutErrors = false; errorMessage = "Invalid MRJ version: " + mrjVersion; } } else if (osName.startsWith("Windows")) { if (osName.indexOf("9") != -1) { jvm = WINDOWS_9x; } else { jvm = WINDOWS_NT; } } else { jvm = OTHER; } if (loadedWithoutErrors) { // if we haven't hit any errors yet loadedWithoutErrors = loadClasses(); } } /** * This class should be never be instantiated; this just ensures so. */ private BrowserLauncher() { } /** * Called by a static initializer to load any classes, fields, and methods required at runtime * to locate the user's web browser. * @return true if all intialization succeeded * false if any portion of the initialization failed */ private static boolean loadClasses() { switch (jvm) { case MRJ_2_0: try { Class aeTargetClass = Class.forName("com.apple.MacOS.AETarget"); Class osUtilsClass = Class.forName("com.apple.MacOS.OSUtils"); Class appleEventClass = Class.forName("com.apple.MacOS.AppleEvent"); Class aeClass = Class.forName("com.apple.MacOS.ae"); aeDescClass = Class.forName("com.apple.MacOS.AEDesc"); aeTargetConstructor = aeTargetClass.getDeclaredConstructor(new Class [] { int.class }); appleEventConstructor = appleEventClass.getDeclaredConstructor(new Class[] { int.class, int.class, aeTargetClass, int.class, int.class }); aeDescConstructor = aeDescClass.getDeclaredConstructor(new Class[] { String.class }); makeOSType = osUtilsClass.getDeclaredMethod("makeOSType", new Class [] { String.class }); putParameter = appleEventClass.getDeclaredMethod("putParameter", new Class[] { int.class, aeDescClass }); sendNoReply = appleEventClass.getDeclaredMethod("sendNoReply", new Class[] { }); Field keyDirectObjectField = aeClass.getDeclaredField("keyDirectObject"); keyDirectObject = (Integer) keyDirectObjectField.get(null); Field autoGenerateReturnIDField = appleEventClass.getDeclaredField("kAutoGenerateReturnID"); kAutoGenerateReturnID = (Integer) autoGenerateReturnIDField.get(null); Field anyTransactionIDField = appleEventClass.getDeclaredField("kAnyTransactionID"); kAnyTransactionID = (Integer) anyTransactionIDField.get(null); } catch (ClassNotFoundException cnfe) { errorMessage = cnfe.getMessage(); return false; } catch (NoSuchMethodException nsme) { errorMessage = nsme.getMessage(); return false; } catch (NoSuchFieldException nsfe) { errorMessage = nsfe.getMessage(); return false; } catch (IllegalAccessException iae) { errorMessage = iae.getMessage(); return false; } break; case MRJ_2_1: try { mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils"); mrjOSTypeClass = Class.forName("com.apple.mrj.MRJOSType"); Field systemFolderField = mrjFileUtilsClass.getDeclaredField("kSystemFolderType"); kSystemFolderType = systemFolderField.get(null); findFolder = mrjFileUtilsClass.getDeclaredMethod("findFolder", new Class[] { mrjOSTypeClass }); getFileCreator = mrjFileUtilsClass.getDeclaredMethod("getFileCreator", new Class[] { File.class }); getFileType = mrjFileUtilsClass.getDeclaredMethod("getFileType", new Class[] { File.class }); } catch (ClassNotFoundException cnfe) { errorMessage = cnfe.getMessage(); return false; } catch (NoSuchFieldException nsfe) { errorMessage = nsfe.getMessage(); return false; } catch (NoSuchMethodException nsme) { errorMessage = nsme.getMessage(); return false; } catch (SecurityException se) { errorMessage = se.getMessage(); return false; } catch (IllegalAccessException iae) { errorMessage = iae.getMessage(); return false; } break; case MRJ_3_0: try { Class linker = Class.forName("com.apple.mrj.jdirect.Linker"); Constructor constructor = linker.getConstructor(new Class[]{ Class.class }); linkage = constructor.newInstance(new Object[] { BrowserLauncher.class }); } catch (ClassNotFoundException cnfe) { errorMessage = cnfe.getMessage(); return false; } catch (NoSuchMethodException nsme) { errorMessage = nsme.getMessage(); return false; } catch (InvocationTargetException ite) { errorMessage = ite.getMessage(); return false; } catch (InstantiationException ie) { errorMessage = ie.getMessage(); return false; } catch (IllegalAccessException iae) { errorMessage = iae.getMessage(); return false; } break; case MRJ_3_1: try { mrjFileUtilsClass = Class.forName("com.apple.mrj.MRJFileUtils"); openURL = mrjFileUtilsClass.getDeclaredMethod("openURL", new Class[] { String.class }); } catch (ClassNotFoundException cnfe) { errorMessage = cnfe.getMessage(); return false; } catch (NoSuchMethodException nsme) { errorMessage = nsme.getMessage(); return false; } break; default: break; } return true; } /** * Attempts to locate the default web browser on the local system. Caches results so it * only locates the browser once for each use of this class per JVM instance. * @return The browser for the system. Note that this may not be what you would consider * to be a standard web browser; instead, it's the application that gets called to * open the default web browser. In some cases, this will be a non-String object * that provides the means of calling the default browser. */ private static Object locateBrowser() { if (browser != null) { return browser; } switch (jvm) { case MRJ_2_0: try { Integer finderCreatorCode = (Integer) makeOSType.invoke(null, new Object[] { FINDER_CREATOR }); Object aeTarget = aeTargetConstructor.newInstance(new Object[] { finderCreatorCode }); Integer gurlType = (Integer) makeOSType.invoke(null, new Object[] { GURL_EVENT }); Object appleEvent = appleEventConstructor.newInstance(new Object[] { gurlType, gurlType, aeTarget, kAutoGenerateReturnID, kAnyTransactionID }); // Don't set browser = appleEvent because then the next time we call // locateBrowser(), we'll get the same AppleEvent, to which we'll already have // added the relevant parameter. Instead, regenerate the AppleEvent every time. // There's probably a way to do this better; if any has any ideas, please let // me know. return appleEvent; } catch (IllegalAccessException iae) { browser = null; errorMessage = iae.getMessage(); return browser; } catch (InstantiationException ie) { browser = null; errorMessage = ie.getMessage(); return browser; } catch (InvocationTargetException ite) { browser = null; errorMessage = ite.getMessage(); return browser; } case MRJ_2_1: File systemFolder; try { systemFolder = (File) findFolder.invoke(null, new Object[] { kSystemFolderType }); } catch (IllegalArgumentException iare) { browser = null; errorMessage = iare.getMessage(); return browser; } catch (IllegalAccessException iae) { browser = null; errorMessage = iae.getMessage(); return browser; } catch (InvocationTargetException ite) { browser = null; errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage(); return browser; } String[] systemFolderFiles = systemFolder.list(); // Avoid a FilenameFilter because that can't be stopped mid-list for(int i = 0; i < systemFolderFiles.length; i++) { try { File file = new File(systemFolder, systemFolderFiles[i]); if (!file.isFile()) { continue; } // We're looking for a file with a creator code of 'MACS' and // a type of 'FNDR'. Only requiring the type results in non-Finder // applications being picked up on certain Mac OS 9 systems, // especially German ones, and sending a GURL event to those // applications results in a logout under Multiple Users. Object fileType = getFileType.invoke(null, new Object[] { file }); if (FINDER_TYPE.equals(fileType.toString())) { Object fileCreator = getFileCreator.invoke(null, new Object[] { file }); if (FINDER_CREATOR.equals(fileCreator.toString())) { browser = file.toString(); // Actually the Finder, but that's OK return browser; } } } catch (IllegalArgumentException iare) { browser = browser; errorMessage = iare.getMessage(); return null; } catch (IllegalAccessException iae) { browser = null; errorMessage = iae.getMessage(); return browser; } catch (InvocationTargetException ite) { browser = null; errorMessage = ite.getTargetException().getClass() + ": " + ite.getTargetException().getMessage(); return browser; } } browser = null; break; case MRJ_3_0: case MRJ_3_1: browser = ""; // Return something non-null break; case WINDOWS_NT: browser = "cmd.exe"; break; case WINDOWS_9x: browser = "command.com"; break; case OTHER: default: browser = "netscape"; break; } return browser; } /** * Attempts to open the default web browser to the given URL. * @param url The URL to open * @throws IOException If the web browser could not be located or does not run */ public static void openURL(String url) throws IOException { if (!loadedWithoutErrors) { throw new IOException("Exception in finding browser: " + errorMessage); } Object browser = locateBrowser(); if (browser == null) { throw new IOException("Unable to locate browser: " + errorMessage); } switch (jvm) { case MRJ_2_0: Object aeDesc = null; try { aeDesc = aeDescConstructor.newInstance(new Object[] { url }); putParameter.invoke(browser, new Object[] { keyDirectObject, aeDesc }); sendNoReply.invoke(browser, new Object[] { }); } catch (InvocationTargetException ite) { throw new IOException("InvocationTargetException while creating AEDesc: " + ite.getMessage()); } catch (IllegalAccessException iae) { throw new IOException("IllegalAccessException while building AppleEvent: " + iae.getMessage()); } catch (InstantiationException ie) { throw new IOException("InstantiationException while creating AEDesc: " + ie.getMessage()); } finally { aeDesc = null; // Encourage it to get disposed if it was created browser = null; // Ditto } break; case MRJ_2_1: Runtime.getRuntime().exec(new String[] { (String) browser, url } ); break; case MRJ_3_0: int[] instance = new int[1]; int result = ICStart(instance, 0); if (result == 0) { int[] selectionStart = new int[] { 0 }; byte[] urlBytes = url.getBytes(); int[] selectionEnd = new int[] { urlBytes.length }; result = ICLaunchURL(instance[0], new byte[] { 0 }, urlBytes, urlBytes.length, selectionStart, selectionEnd); if (result == 0) { // Ignore the return value; the URL was launched successfully // regardless of what happens here. ICStop(instance); } else { throw new IOException("Unable to launch URL: " + result); } } else { throw new IOException("Unable to create an Internet Config instance: " + result); } break; case MRJ_3_1: try { openURL.invoke(null, new Object[] { url }); } catch (InvocationTargetException ite) { throw new IOException("InvocationTargetException while calling openURL: " + ite.getMessage()); } catch (IllegalAccessException iae) { throw new IOException("IllegalAccessException while calling openURL: " + iae.getMessage()); } break; case WINDOWS_NT: case WINDOWS_9x: // Add quotes around the URL to allow ampersands and other special // characters to work. Process process = Runtime.getRuntime().exec(new String[] { (String) browser, FIRST_WINDOWS_PARAMETER, SECOND_WINDOWS_PARAMETER, THIRD_WINDOWS_PARAMETER, '"' + url + '"' }); // This avoids a memory leak on some versions of Java on Windows. // That's hinted at in <http://developer.java.sun.com/developer/qow/archive/68/>. try { process.waitFor(); process.exitValue(); } catch (InterruptedException ie) { throw new IOException("InterruptedException while launching browser: " + ie.getMessage()); } break; case OTHER: // Assume that we're on Unix and that Netscape is installed // First, attempt to open the URL in a currently running session of Netscape process = Runtime.getRuntime().exec(new String[] { (String) browser, NETSCAPE_REMOTE_PARAMETER, NETSCAPE_OPEN_PARAMETER_START + url + NETSCAPE_OPEN_PARAMETER_END }); try { int exitCode = process.waitFor(); if (exitCode != 0) { // if Netscape was not open Runtime.getRuntime().exec(new String[] { (String) browser, url }); } } catch (InterruptedException ie) { throw new IOException("InterruptedException while launching browser: " + ie.getMessage()); } break; default: // This should never occur, but if it does, we'll try the simplest thing possible Runtime.getRuntime().exec(new String[] { (String) browser, url }); break; } } /** * Methods required for Mac OS X. The presence of native methods does not cause * any problems on other platforms. */ private native static int ICStart(int[] instance, int signature); private native static int ICStop(int[] instance); private native static int ICLaunchURL(int instance, byte[] hint, byte[] data, int len, int[] selectionStart, int[] selectionEnd); }