Next: Bibliography
Up: Clients
Previous: Fetch.java
  Contents
//Java-based version of xbiff. Biff reads its data off a POP(3)
//server. When Biff is started it regularly contact the POP server and
//beeps when new mail has arrived. It shows the number of messages
//currently on the POP server at the bottom of the
//window. Control-clicking in the window shows a configuration panel
//which allows to change the user, host, password and
//frequency. Single-clicking shows a box with all headers.
//
// - indication of number of mails waiting on POP server
// - listing of headers by single-clicking on the Biff window
// - extension (MailResource) to allow access to a number of other mail
// resources (e.g. file, IMAP)
//
//Arguments can be seen by starting 'java Biff -help'.
//
//The subjects of all mail currently on the pop server can be looked at
//by clicking with the mouse on Biff's window. A control-mouse-click
//displays a configuration dialog.
//
// example command line:
//java Biff -user daly -pass burns -host pop.mail.net -delay 1000
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import java.util.*;
import java.util.Vector;
interface MailListener
{ public void NewMail(int new_msgs);
public void Reset();
public void Error(String msg);
public void OkAgain();
}
interface MailResource
{ public void AddMailListener(MailListener l);
public void RemoveMailListener(MailListener l);
public void StartPollingForMail();
public void StopPollingForMail();
public Vector GetHeaders() throws Exception;
public long GetSleepPeriod();
public void SetSleepPeriod(long msecs);
public String GetHost();
public void SetHost(String new_host);
public String GetUser();
public void SetUser(String new_user);
public String GetPass();
public void SetPass(String new_pass);
}
class PopServer implements MailResource, java.lang.Runnable
{ private Vector listeners=new Vector();
private long sleep_period=60000;
private int counter=0;
private String uid="";
private String pw="";
private String pop_host="popsrv";
private int num_msgs=-1;
private Vector headers=new Vector();
private boolean in_error=false;
private Thread poller=null;
public PopServer(long l, String userid, String password, String popsrv)
{ sleep_period=l;
uid=userid;
pw=password;
pop_host=popsrv;
ResetHeaders();
}
public long GetSleepPeriod() {return sleep_period;}
public void SetSleepPeriod(long msecs)
{ if(msecs > 0)
sleep_period=msecs;
}
public String GetHost() {return pop_host;}
public void SetHost(String new_host) {pop_host=new_host;}
public String GetUser() {return uid;}
public void SetUser(String new_user) {uid=new_user;}
public String GetPass() {return pw;}
public void SetPass(String new_pass) {pw=new_pass;}
public void AddMailListener(MailListener l)
{ listeners.addElement(l);
}
public void RemoveMailListener(MailListener l)
{ listeners.removeElement(l);
}
public void StartPollingForMail()
{ if(poller == null)
{ poller=new Thread(this);
poller.start();
}
}
public synchronized void StopPollingForMail()
{ if(poller != null)
{ poller.stop();
poller=null;
}
}
public Vector GetHeaders() throws Exception {return headers;}
private void ResetHeaders()
{ headers.removeAllElements();
headers.addElement(" --- No messages available --- ");
}
public void run()
{ MailListener l;
while(true)
{ try
{ num_msgs=CheckMail();
if(in_error == true)
{ in_error=false;
for(int i=0; i < listeners.size(); i++)
((MailListener)listeners.elementAt(i)).OkAgain();
}
if(num_msgs == 0)
{ if(counter > 0)
{ for(int i=0; i < listeners.size(); i++)
((MailListener)listeners.elementAt(i)).Reset();
counter=0;
ResetHeaders();
}
}
else
{ if(num_msgs > counter)
{ for(int i=0; i < listeners.size(); i++)
((MailListener)listeners.elementAt(i)).NewMail(num_msgs);
counter=num_msgs;
}
}
}
catch(Exception error)
{ for(int i=0; i < listeners.size(); i++)
{ in_error=true;
l=(MailListener)listeners.elementAt(i);
l.Error("POP server error: " + error);
}
}
try
{ Thread.currentThread().sleep(sleep_period);
}
catch(java.lang.InterruptedException ex)
{ break;
}
}
}
private String readLn(BufferedReader dis) throws IOException
{ String incoming;
StringTokenizer st;
incoming=dis.readLine();
return incoming;
}
private boolean popError(String incoming) throws Exception
{ StringTokenizer st=new StringTokenizer(incoming);
if((st.nextToken()).equals("-ERR"))
{ throw new Exception(incoming);
}
return false;
}
public synchronized int CheckMail() throws Exception
{ Socket talk=null;
BufferedReader inp=null;
DataOutputStream outs=null;
StringTokenizer st;
StringBuffer header;
int num_msgs=-1;
String toss, line;
try
{ talk=new Socket(pop_host,110);
inp=new BufferedReader(new InputStreamReader(talk.getInputStream()));
outs=new DataOutputStream(talk.getOutputStream());
PrintWriter p = new PrintWriter(talk.getOutputStream());
popError(readLn(inp));
Thread.currentThread().sleep(1000);
p.println("user "+uid); p.flush();
popError(readLn(inp));
p.println("pass "+pw); p.flush();
popError(readLn(inp));
p.println("stat"); p.flush();
toss=readLn(inp);
popError(toss);
st=new StringTokenizer(toss);
st.nextToken();
num_msgs=Integer.parseInt(st.nextToken());
if(num_msgs > counter)
{ headers.removeAllElements();
for(int i=1; i < num_msgs+1; i++)
{ header=new StringBuffer();
outs.writeBytes("top " + i + " 0\n");
popError(readLn(inp));
while(true)
{ line=readLn(inp);
if(line.equals(".") || line == null)
break;
if(line.indexOf("From:") != -1)
{ header.append(line);
continue;
}
if(line.indexOf("Subject:") != -1)
{ header.append(" " + line);
continue;
}
}
if(header.length() > 0)
headers.addElement(header.toString());
}
}
outs.writeBytes("QUIT\n");
outs.flush();
outs.close();
outs=null;
}
catch (Exception e)
{ if(outs != null)
{ outs.writeBytes("QUIT\n");
outs.flush();
outs.close();
outs=null;
}
throw e;
}
finally
{ if(outs != null)
{ outs.writeBytes("QUIT\n");
outs.flush();
outs.close();
outs=null;
}
if(talk != null)
talk.close();
if(headers.size() == 0)
ResetHeaders();
}
return num_msgs;
}
}
class Headers extends Window
{
public Headers(Frame parent, Vector vec)
{ super(parent);
java.awt.List headers=new java.awt.List();
for(int i=0; i < vec.size(); i++)
{ headers.add((String)vec.elementAt(i));
}
headers.addMouseListener(
new MouseListener()
{ public void mouseClicked(MouseEvent e) {Close();}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
}
);
add(headers);
setSize(500,300);
Point parent_loc=parent.getLocation();
parent_loc.x=parent_loc.x-430;
setLocation(parent_loc);
setFont(new Font("TimesRoman",Font.BOLD,12));
show();
}
public void Close() {dispose();}
}
class bCanvas extends Canvas
{ Image one=null, two=null;
Toolkit tk;
Biff jb;
Graphics offgraph;
Image offscrn;
public bCanvas(Biff jb)
{ super();
File f1test, f2test;
this.jb = jb;
try
{ f1test = new File(this.jb.mail);
f2test = new File(this.jb.nomail);
tk=this.getToolkit();
if(f1test.exists())
one=tk.getImage(this.jb.mail);
if(f2test.exists())
two=tk.getImage(this.jb.nomail);
}
catch (NullPointerException e)
{ System.err.println("File is null");
}
}
public void paint(Graphics g)
{ Dimension dm;
FontMetrics fm;
dm=jb.size();
offscrn = createImage(this.size().width,this.size().height);
offgraph = offscrn.getGraphics();
offgraph.setColor(Color.lightGray);
if (one==null)
offgraph.draw3DRect(0,0,this.size().width,this.size().height, true);
offgraph.setColor(Color.black);
if(jb.ErrorOccurred())
{ offgraph.setColor(Color.red);
offgraph.setFont(new Font("TimesRoman",Font.BOLD,12));
fm=getFontMetrics(new Font("TimesRoman",Font.BOLD,12));
offgraph.drawString(" Error ",
(this.size().width - fm.stringWidth(" Error "))/2,
((this.size().height) - (fm.getHeight()/2)));
g.drawImage(offscrn,0,0,this);
return;
}
if(jb.num_msgs > 0)
{ if (one!=null)
{ offgraph.drawImage(one,0,0,dm.width,dm.height-50,this);
offgraph.setFont(new Font("TimesRoman",Font.BOLD,12));
fm=getFontMetrics(new Font("TimesRoman", Font.BOLD,12));
offgraph.drawString(" " + jb.num_msgs + " msg",
(this.size().width - fm.stringWidth(" "))/2-10,
((this.size().height) - (fm.getHeight()/2))+5);
}
else
{ offgraph.setColor(Color.blue);
offgraph.fillRect(0,0,dm.width,dm.height);
offgraph.setColor(Color.white);
offgraph.setFont(new Font("TimesRoman",Font.BOLD,12));
fm=getFontMetrics(new Font("TimesRoman", Font.BOLD,12));
offgraph.drawString(" " + jb.num_msgs + " msg",
(this.size().width - fm.stringWidth(" "))/2,
((this.size().height) - (fm.getHeight()/2)));
}
}
else
{ offgraph.setColor(Color.black);
if (two!=null)
{ offgraph.drawImage(two,0,0,dm.width,dm.height,this);
}
else
{ offgraph.setFont(new Font("TimesRoman",Font.BOLD,12));
fm=getFontMetrics(new Font("TimesRoman",Font.BOLD,12));
offgraph.drawString(" No Mail ",
(this.size().width - fm.stringWidth(" No Mail "))/2,
((this.size().height) - (fm.getHeight()/2)));
}
}
g.drawImage(offscrn,0,0,this);
}
public void update(Graphics g) {paint(g);}
public Dimension preferredSize() {return new Dimension(70,70);}
public Dimension minimumSize() {return preferredSize();}
}
class bInfoBox extends Frame
{ Biff caller;
public bInfoBox(String title,String message, Biff caller)
{ super(title);
this.caller = caller;
add("Center",new Label(message,Label.CENTER));
Button okay = new Button("Okay");
add("South",okay);
pack();
show();
}
public boolean handleEvent(Event evt)
{ if ( evt.target instanceof Button)
{ this.dispose();
caller.killjberror();
return true;
}
return super.handleEvent(evt);
}
}
class bSetup extends Frame
{ TextField mailhost,user,pass,freq;
Button close,reset,quit;
Biff jb;
bInfoBox info;
public bSetup(Biff jb)
{ super("Biff Configure");
this.jb= jb;
setLayout(new GridLayout(5,1,10,10));
Panel line1 = new Panel();
Panel line2 = new Panel();
Panel line3 = new Panel();
Panel line4 = new Panel();
Panel line5 = new Panel();
line1.setLayout(new GridLayout(1,2,5,5));
line2.setLayout(new GridLayout(1,2,5,5));
line3.setLayout(new GridLayout(1,2,5,5));
line4.setLayout(new GridLayout(1,3,5,5));
line5.setLayout(new GridLayout(1,2,5,5));
line1.add(new Label("Mailhost:",Label.RIGHT));
mailhost = new TextField(jb.GetHost(),30);
line1.add(mailhost);
line2.add(new Label("User Name:",Label.RIGHT));
user = new TextField(jb.GetUser(),30);
line2.add(user);
line3.add(new Label("Password:",Label.RIGHT));
pass = new TextField(jb.GetPass(),15);
pass.setEchoCharacter('*');
line3.add(pass);
line5.add(new Label("Frequency (milliseconds):",Label.RIGHT));
freq = new TextField(Long.toString(jb.GetDelay()),2);
line5.add(freq);
close = new Button("Set Values");
quit = new Button("Quit");
line4.add(close);
line4.add(quit);
add(line1);
add(line2);
add(line3);
add(line5);
add(line4);
pack();
}
public boolean handleEvent (Event evt)
{ if (evt.target == close)
{ jb.SetUser(user.getText());
jb.SetPass(pass.getText());
jb.SetHost(mailhost.getText());
try
{ jb.SetDelay(Integer.parseInt(freq.getText()));
}
catch (NumberFormatException e) {};
setVisible(false);
return true;
}
if (evt.target == reset)
{ jb.jbcanvas.repaint();
return true;
}
if (evt.target == quit)
{ System.exit(0);
return true;
}
return false;
}
}
public class Biff extends Frame implements MailListener, WindowListener
{ bSetup jbsetup;
bCanvas jbcanvas;
String nomail,mail;
bInfoBox jberror;
int num_msgs=0;
MailResource mail_resource=null;
Headers headers=null;
boolean error_occurred=false;
public Biff(String title,String m,String n, MailResource res)
{ super(title);
mail = m;
nomail =n;
mail_resource=res;
jbsetup = new bSetup(this);
jbcanvas = new bCanvas(this);
add("Center",jbcanvas);
pack();
setSize(70,90);
mail_resource.AddMailListener(this);
mail_resource.StartPollingForMail();
addWindowListener(this);
show();
}
public long GetDelay() {return mail_resource.GetSleepPeriod();}
public void SetDelay(long msecs) {mail_resource.SetSleepPeriod(msecs);}
public String GetHost() {return mail_resource.GetHost();}
public void SetHost(String new_host) {mail_resource.SetHost(new_host);}
public String GetUser() {return mail_resource.GetUser();}
public void SetUser(String new_user) {mail_resource.SetUser(new_user);}
public String GetPass() {return mail_resource.GetPass();}
public void SetPass(String new_pass) {mail_resource.SetPass(new_pass);}
public boolean ErrorOccurred() {return error_occurred;}
public void killjberror(){jberror=null;}
public boolean handleEvent (Event evt)
{ if (evt.id == Event.MOUSE_DOWN)
{ if(evt.controlDown())
{ jbsetup.show();
return true;
}
else
{ try
{ headers=new Headers(this, mail_resource.GetHeaders());
}
catch(Exception e) {}
return true;
}
}
return super.handleEvent(evt);
}
public void NewMail(int num_new_msgs)
{ error_occurred=false;
Toolkit.getDefaultToolkit().beep();
num_msgs=num_new_msgs;
jbcanvas.repaint();
}
public void Reset()
{ error_occurred=false;
num_msgs=0;
jbcanvas.repaint();
}
public void Error(String msg)
{ error_occurred=true;
System.err.println(msg);
jbcanvas.repaint();
}
public void OkAgain()
{ error_occurred=false;
jbcanvas.repaint();
}
public void windowOpened(WindowEvent e) {}
public void windowClosing(WindowEvent e)
{ mail_resource.RemoveMailListener(this);
mail_resource.StopPollingForMail();
System.exit(1);
}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
public static void main(String args[])
{ Biff master;
long d=60000;
String m ="";
String n ="";
String p ="";
String u ="user";
String h ="host";
for(int i = 0; i < args.length; i++)
{ if (args[i].equals("-mail")) m =args[i+1];
if (args[i].equals("-nomail")) n =args[i+1];
if (args[i].equals("-pass")) p = args[i+1];
if (args[i].equals("-user")) u = args[i+1];
if (args[i].equals("-host")) h = args[i+1];
if (args[i].equals("-delay")) d = new Long(args[i+1]).longValue();
if (args[i].equals("-help")){
System.out.println("\nBiff -- Biff for Java");
System.out.println("Mouse click -- see headers");
System.out.println("Control-mouse click -- change parameters/quit");
System.out.println(" -mail filename ");
System.out.println(" -nomail filename ");
System.out.println(" -user username");
System.out.println(" -pass password");
System.out.println(" -host mailhost");
System.out.println(" -delay milliseconds");
System.out.println(" --help\n\n");
System.exit(0);
}
}
MailResource res=new PopServer(d, u, p, h);
master = new Biff("Biff",m,n,res);
Dimension dim=Toolkit.getDefaultToolkit().getScreenSize();
master.setLocation(dim.width-70, 65);
}
}
root
2004-03-16