/*
** j###t ########## #### ####
** j###t ########## #### ####
** j###T "###L J###"
** ######P' ########## #########
** ######k, ########## T######T
** ####~###L ####
** #### q###L ########## .#####
** #### \###L ########## #####"
**
** $Id$
**
** Class History
**
** Date Name Description
** ---------|------------|-----------------------------------------------
** 19Aug98 subtle start of recorded history
**
*/
package key;
import key.primitive.*;
import java.util.Enumeration;
import java.io.*;
import java.util.StringTokenizer;
/**
* It's too hard to give sites a unique name, but its useful to
* store them in a container to save us writing custom load/save
* routines. It also means if you *do* know a sites 'number' on
* the program, you have a chance ;)
*/
public class Site extends Atom implements Subnet
{
private static final long serialVersionUID = 7084061282031417477L;
public static final AtomicElement[] ELEMENTS =
{
AtomicElement.construct( Site.class, Paragraph.class, "notes",
AtomicElement.PUBLIC_FIELD,
"some comments about this site" ),
AtomicElement.construct( Site.class, String.class, "banType",
AtomicElement.PUBLIC_FIELD,
"the type of the ban on this site: N, C, or O" ),
AtomicElement.construct( Site.class, Player.class, "bannedBy",
AtomicElement.PUBLIC_FIELD,
"the player who banned this site" ),
AtomicElement.construct( Site.class, DateTime.class, "bannedAt",
AtomicElement.PUBLIC_FIELD,
"when this site was banned" ),
AtomicElement.construct( Site.class, DateTime.class, "bannedUntil",
AtomicElement.PUBLIC_FIELD,
"when this site will be un-banned" ),
AtomicElement.construct( Site.class, TimeStatistics.class, "connectionStats",
AtomicElement.PUBLIC_FIELD,
"information about who connects from this site" ),
AtomicElement.construct( Site.class, String.class, "alpha",
AtomicElement.PUBLIC_FIELD | AtomicElement.READ_ONLY,
"the domain name of this site" ),
AtomicElement.construct( Site.class, String.class, "reasonBanned",
AtomicElement.PUBLIC_FIELD,
"the reason this site was banned" )
};
public static final AtomicStructure STRUCTURE = new AtomicStructure( Atom.STRUCTURE, ELEMENTS );
public Paragraph notes = new TextParagraph( TextParagraph.CENTERALIGNED, "" );
/**
* The type of ban that is on the site:
* N for newbie
* C for siteban
* 0 length string for no ban at all
*/
public String banType = "O";
public Reference bannedBy = Reference.EMPTY;
public DateTime bannedAt = null;
public DateTime bannedUntil = null;
public final TimeStatistics connectionStats = (TimeStatistics) Factory.makeAtom( TimeStatistics.class, "connectionStats" );
public String reasonBanned = "";
/**
* The IP mask. This is basically
* the array that was returned by InetAddress
*/
public int[] mask;
/**
* The alpha for this site. For instance,
* UTS is uts.edu.au (thats the whole site
* name). (Can be null if no DNS entry)
*/
public String alpha;
private final String SITE_LOG = "site";
public Site()
{
}
public AtomicStructure getDeclaredStructure()
{
return( STRUCTURE );
}
public final boolean newbiesAllowed()
{
checkBans();
return( !banType.equals( "N" ) );
}
public final boolean connectionsAllowed()
{
checkBans();
return( !banType.equals( "C" ) );
}
public final TimeStatistics connectionStats()
{
return( connectionStats );
}
/*
public final TimeStatistics connectionStatistics()
{
return( connectionStats );
}
*/
/**
* The passed in string MUST be lowercase
*/
protected void resetTrailer( String newT )
{
if( alpha != null && !alpha.equals( newT ) )
((Network)getParent()).unRegisterTrailer( alpha );
alpha = newT;
((Network)getParent()).registerTrailer( this );
}
/**
* You can construct a Site with any IP, but
* only the relevant IP's will be stored.
*/
public Site( int[] ip )
{
setMask( ip );
}
public void setMask( int[] ip )
{
if( ip[0] < 128 )
mask = new int[1];
else if( ip[0] < 192 )
mask = new int[2];
else if( ip[0] < 224 )
mask = new int[3];
else
mask = new int[4];
for( int i = 0; i < mask.length; i++ )
mask[i] = ip[i];
alpha = null;
setKey( new Integer( mask[ mask.length - 1 ] ) );
}
public int[] getMask()
{
return( mask );
}
public String getTrailer()
{
return( alpha );
}
/**
* Some sites will have dns entries for certain IP's
* within them, and not have entries for others. We
* also need this code to find the 'lowest common
* denominator' in the site alpha.
*/
public void registerSite( String dns )
{
if( dns != null )
{
if( alpha == null )
resetTrailer( dns.toLowerCase() );
else
{
dns = dns.toLowerCase();
String newTrailer = alpha;
while( !dns.endsWith( newTrailer ) )
{
// okay, we need to find the common parts of these
// two strings, from the end. For instance, the
// alpha might currently be 'progsoc.uts.edu.au',
// as we've only had connections from 138.25. from
// within progsoc. However, when we get a connection
// from say, socs: 'charlie.socs.uts.edu.au', then
// the tailer is known to be inaccurate.
int tIndex = newTrailer.indexOf( '.' );
if( tIndex == -1 )
{
Log.log( SITE_LOG, "ran out of trail sections trying to find a common DNS section" );
return;
}
try
{
newTrailer = newTrailer.substring( tIndex+1 );
}
catch( StringIndexOutOfBoundsException e )
{
Log.log( SITE_LOG, "got a trailing period in a alpha '" + alpha + "'. aborting registerSite()" );
return;
}
}
resetTrailer( newTrailer );
}
}
//Log.log( SITE_LOG, "DNS entry '" + dns + "' registered inside " + toString() );
}
public String toString()
{
StringBuffer sb = new StringBuffer();
for( int i = 0; i < mask.length; i++ )
{
sb.append( mask[i] );
sb.append( "." );
}
if( alpha != null )
return( alpha + " [" + sb.toString() + "]" );
else
return( sb.toString() );
}
private void checkBans()
{
DateTime now = new DateTime();
if( bannedUntil == null )
return;
long diff = now.getTime() - bannedUntil.getTime();
if( diff >= 0 )
{
//Ban has expired
banType = "";
bannedBy = null;
bannedAt = now;
bannedUntil = null;
reasonBanned = "Site ban expired";
}
}
public final void setBan( String banType, Player p, DateTime now, DateTime until, String reason )
{
permissionList.check( modifyAction );
banType = banType;
bannedBy = p.getThis();
bannedAt = now;
bannedUntil = until;
reasonBanned = reason;
}
}