2005-07-04 jrandom

* Within the tunnel, use xor(IV, msg[0:16]) as the flag to detect dups,
      rather than the IV by itself, preventing an attack that would let
      colluding internal adversaries tag a message to determine that they are
      in the same tunnel.  Thanks dvorak for the catch!
    * Drop long inactive profiles on startup and shutdown
    * /configstats.jsp: web interface to pick what stats to log
    * Deliver more session tags to account for wider window sizes
    * Cache some intermediate values in our HMACSHA256 and BC's HMAC
    * Track the client send rate (stream.sendBps and client.sendBpsRaw)
    * UrlLauncher: adjust the browser selection order
    * I2PAppContext: hooks for dummy HMACSHA256 and a weak PRNG
    * StreamSinkClient: add support for sending an unlimited amount of data
    * Migrate the tests out of the default build jars

2005-06-22  Comwiz
    * Migrate the core tests to junit
This commit is contained in:
jrandom
2005-07-04 20:44:17 +00:00
committed by zzz
parent 440cf2c983
commit 18d3f5d25d
80 changed files with 2398 additions and 958 deletions

View File

@ -1,239 +1,239 @@
/*
* Created on Nov 9, 2004
*
* This file is part of susimail project, see http://susi.i2p/
*
* Copyright (C) 2004-2005 <susi23@mail.i2p>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Revision: 1.1 $
*/
package i2p.susi.webmail;
import i2p.susi.util.Config;
import i2p.susi.util.ReadBuffer;
import i2p.susi.webmail.encoding.Encoding;
import i2p.susi.webmail.encoding.EncodingFactory;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
/**
* data structure to hold a single message, mostly used with folder view and sorting
*
* @author susi
*/
public class Mail {
public static final String DATEFORMAT = "date.format";
public static final String unknown = "unknown";
public int id, size;
public String sender, reply, subject, dateString,
formattedSender, formattedSubject, formattedDate,
shortSender, shortSubject, quotedDate, uidl;
public Date date;
public ReadBuffer header, body;
public MailPart part;
Object[] to, cc;
public String error;
public boolean markForDeletion;
public boolean deleted;
public Mail() {
id = 0;
size = 0;
formattedSender = unknown;
formattedSubject = unknown;
formattedDate = unknown;
shortSender = unknown;
shortSubject = unknown;
quotedDate = unknown;
error = "";
}
/**
*
* @param address
* @return
*/
public static boolean validateAddress( String address )
{
if( address == null || address.length() == 0 )
return false;
address = address.trim();
if( address.indexOf( "\n" ) != -1 ||
address.indexOf( "\r" ) != -1 )
return false;
String[] tokens = address.split( "[ \t]+" );
int addresses = 0;
for( int i = 0; i < tokens.length; i++ ) {
if( tokens[i].matches( "^[^@< \t]+@[^> \t]+$" ) ||
tokens[i].matches( "^<[^@< \t]+@[^> \t]+>$" ) )
addresses++;
}
return addresses == 1;
}
/**
* @param address
* @return
*/
public static String getAddress(String address )
{
String[] tokens = address.split( "[ \t]+" );
for( int i = 0; i < tokens.length; i++ ) {
if( tokens[i].matches( "^[^@< \t]+@[^> \t]+$" ) )
return "<" + tokens[i] + ">";
if( tokens[i].matches( "^<[^@< \t]+@[^> \t]+>$" ) )
return tokens[i];
}
return null;
}
public static boolean getRecipientsFromList( ArrayList recipients, String text, boolean ok )
{
if( text != null && text.length() > 0 ) {
String[] ccs = text.split( "," );
for( int i = 0; i < ccs.length; i++ ) {
String recipient = ccs[i].trim();
if( validateAddress( recipient ) ) {
String str = getAddress( recipient );
if( str != null && str.length() > 0 ) {
recipients.add( str );
}
else {
ok = false;
}
}
else {
ok = false;
}
}
}
return ok;
}
public static void appendRecipients( StringBuffer buf, ArrayList recipients, String prefix )
{
for( Iterator it = recipients.iterator(); it.hasNext(); ) {
buf.append( prefix );
prefix ="\t";
buf.append( (String)it.next() );
buf.append( "\r\n" );
}
}
public void parseHeaders()
{
DateFormat dateFormatter = new SimpleDateFormat( Config.getProperty( DATEFORMAT, "mm/dd/yyyy HH:mm:ss" ) );
DateFormat mailDateFormatter = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH );
error = "";
if( header != null ) {
boolean ok = true;
Encoding html = EncodingFactory.getEncoding( "HTML" );
if( html == null ) {
error += "HTML encoder not found.<br>";
ok = false;
}
Encoding hl = EncodingFactory.getEncoding( "HEADERLINE" );
if( hl == null ) {
error += "Header line encoder not found.<br>";
ok = false;
}
if( ok ) {
try {
ReadBuffer decoded = hl.decode( header );
BufferedReader reader = new BufferedReader( new InputStreamReader( new ByteArrayInputStream( decoded.content, decoded.offset, decoded.length ), "ISO-8859-1" ) );
String line;
while( ( line = reader.readLine() ) != null ) {
if( line.length() == 0 )
break;
if( line.startsWith( "From:" ) ) {
sender = line.substring( 5 ).trim();
formattedSender = getAddress( sender );
shortSender = formattedSender.trim();
if( shortSender.length() > 40 ) {
shortSender = shortSender.substring( 0, 37 ).trim() + "...";
}
shortSender = html.encode( shortSender );
}
else if( line.startsWith( "Date:" ) ) {
dateString = line.substring( 5 ).trim();
try {
date = mailDateFormatter.parse( dateString );
formattedDate = dateFormatter.format( date );
quotedDate = html.encode( dateString );
}
catch (ParseException e) {
date = null;
e.printStackTrace();
}
}
else if( line.startsWith( "Subject:" ) ) {
subject = line.substring( 8 ).trim();
formattedSubject = subject;
shortSubject = formattedSubject;
if( formattedSubject.length() > 60 )
shortSubject = formattedSubject.substring( 0, 57 ).trim() + "...";
shortSubject = html.encode( shortSubject );
}
else if( line.toLowerCase().startsWith( "Reply-To:" ) ) {
reply = Mail.getAddress( line.substring( 9 ).trim() );
}
else if( line.startsWith( "To:" ) ) {
ArrayList list = new ArrayList();
Mail.getRecipientsFromList( list, line.substring( 3 ).trim(), true );
to = list.toArray();
}
else if( line.startsWith( "Cc:" ) ) {
ArrayList list = new ArrayList();
Mail.getRecipientsFromList( list, line.substring( 3 ).trim(), true );
cc = list.toArray();
}
}
}
catch( Exception e ) {
error += "Error parsing mail header: " + e.getClass().getName() + "<br>";
}
}
}
}
}
/*
* Created on Nov 9, 2004
*
* This file is part of susimail project, see http://susi.i2p/
*
* Copyright (C) 2004-2005 <susi23@mail.i2p>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Revision: 1.2 $
*/
package i2p.susi.webmail;
import i2p.susi.util.Config;
import i2p.susi.util.ReadBuffer;
import i2p.susi.webmail.encoding.Encoding;
import i2p.susi.webmail.encoding.EncodingFactory;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
/**
* data structure to hold a single message, mostly used with folder view and sorting
*
* @author susi
*/
public class Mail {
public static final String DATEFORMAT = "date.format";
public static final String unknown = "unknown";
public int id, size;
public String sender, reply, subject, dateString,
formattedSender, formattedSubject, formattedDate,
shortSender, shortSubject, quotedDate, uidl;
public Date date;
public ReadBuffer header, body;
public MailPart part;
Object[] to, cc;
public String error;
public boolean markForDeletion;
public boolean deleted;
public Mail() {
id = 0;
size = 0;
formattedSender = unknown;
formattedSubject = unknown;
formattedDate = unknown;
shortSender = unknown;
shortSubject = unknown;
quotedDate = unknown;
error = "";
}
/**
*
* @param address
* @return
*/
public static boolean validateAddress( String address )
{
if( address == null || address.length() == 0 )
return false;
address = address.trim();
if( address.indexOf( "\n" ) != -1 ||
address.indexOf( "\r" ) != -1 )
return false;
String[] tokens = address.split( "[ \t]+" );
int addresses = 0;
for( int i = 0; i < tokens.length; i++ ) {
if( tokens[i].matches( "^[^@< \t]+@[^> \t]+$" ) ||
tokens[i].matches( "^<[^@< \t]+@[^> \t]+>$" ) )
addresses++;
}
return addresses == 1;
}
/**
* @param address
* @return
*/
public static String getAddress(String address )
{
String[] tokens = address.split( "[ \t]+" );
for( int i = 0; i < tokens.length; i++ ) {
if( tokens[i].matches( "^[^@< \t]+@[^> \t]+$" ) )
return "<" + tokens[i] + ">";
if( tokens[i].matches( "^<[^@< \t]+@[^> \t]+>$" ) )
return tokens[i];
}
return null;
}
public static boolean getRecipientsFromList( ArrayList recipients, String text, boolean ok )
{
if( text != null && text.length() > 0 ) {
String[] ccs = text.split( "," );
for( int i = 0; i < ccs.length; i++ ) {
String recipient = ccs[i].trim();
if( validateAddress( recipient ) ) {
String str = getAddress( recipient );
if( str != null && str.length() > 0 ) {
recipients.add( str );
}
else {
ok = false;
}
}
else {
ok = false;
}
}
}
return ok;
}
public static void appendRecipients( StringBuffer buf, ArrayList recipients, String prefix )
{
for( Iterator it = recipients.iterator(); it.hasNext(); ) {
buf.append( prefix );
prefix ="\t";
buf.append( (String)it.next() );
buf.append( "\r\n" );
}
}
public void parseHeaders()
{
DateFormat dateFormatter = new SimpleDateFormat( Config.getProperty( DATEFORMAT, "mm/dd/yyyy HH:mm:ss" ) );
DateFormat mailDateFormatter = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH );
error = "";
if( header != null ) {
boolean ok = true;
Encoding html = EncodingFactory.getEncoding( "HTML" );
if( html == null ) {
error += "HTML encoder not found.<br>";
ok = false;
}
Encoding hl = EncodingFactory.getEncoding( "HEADERLINE" );
if( hl == null ) {
error += "Header line encoder not found.<br>";
ok = false;
}
if( ok ) {
try {
ReadBuffer decoded = hl.decode( header );
BufferedReader reader = new BufferedReader( new InputStreamReader( new ByteArrayInputStream( decoded.content, decoded.offset, decoded.length ), "ISO-8859-1" ) );
String line;
while( ( line = reader.readLine() ) != null ) {
if( line.length() == 0 )
break;
if( line.startsWith( "From:" ) ) {
sender = line.substring( 5 ).trim();
formattedSender = getAddress( sender );
shortSender = formattedSender.trim();
if( shortSender.length() > 40 ) {
shortSender = shortSender.substring( 0, 37 ).trim() + "...";
}
shortSender = html.encode( shortSender );
}
else if( line.startsWith( "Date:" ) ) {
dateString = line.substring( 5 ).trim();
try {
date = mailDateFormatter.parse( dateString );
formattedDate = dateFormatter.format( date );
quotedDate = html.encode( dateString );
}
catch (ParseException e) {
date = null;
e.printStackTrace();
}
}
else if( line.startsWith( "Subject:" ) ) {
subject = line.substring( 8 ).trim();
formattedSubject = subject;
shortSubject = formattedSubject;
if( formattedSubject.length() > 60 )
shortSubject = formattedSubject.substring( 0, 57 ).trim() + "...";
shortSubject = html.encode( shortSubject );
}
else if( line.toLowerCase().startsWith( "Reply-To:" ) ) {
reply = Mail.getAddress( line.substring( 9 ).trim() );
}
else if( line.startsWith( "To:" ) ) {
ArrayList list = new ArrayList();
Mail.getRecipientsFromList( list, line.substring( 3 ).trim(), true );
to = list.toArray();
}
else if( line.startsWith( "Cc:" ) ) {
ArrayList list = new ArrayList();
Mail.getRecipientsFromList( list, line.substring( 3 ).trim(), true );
cc = list.toArray();
}
}
}
catch( Exception e ) {
error += "Error parsing mail header: " + e.getClass().getName() + "<br>";
}
}
}
}
}

View File

@ -1,102 +1,102 @@
/*
* Created on Nov 23, 2004
*
* This file is part of susimail project, see http://susi.i2p/
*
* Copyright (C) 2004-2005 <susi23@mail.i2p>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Revision: 1.1 $
*/
package i2p.susi.webmail;
import java.util.Hashtable;
import i2p.susi.webmail.pop3.POP3MailBox;
/**
* @author user
*/
public class MailCache {
public static final boolean FETCH_HEADER = true;
public static final boolean FETCH_ALL = false;
private POP3MailBox mailbox;
private String error;
private Hashtable mails;
private Object synchronizer;
MailCache( POP3MailBox mailbox ) {
this.mailbox = mailbox;
mails = new Hashtable();
synchronizer = new Object();
}
/**
* Fetch any needed data from pop3 server.
*
* @param id message id to get
* @param headerOnly fetch only header lines?
* @return
*/
public Mail getMail( String uidl, boolean headerOnly ) {
Mail mail = null, newMail = null;
if( mailbox != null ) {
/*
* synchronize update to hashtable
*/
synchronized( synchronizer ) {
mail = (Mail)mails.get( uidl );
if( mail == null ) {
newMail = new Mail();
mails.put( uidl, newMail );
}
}
if( mail == null ) {
mail = newMail;
mail.uidl = uidl;
mail.size = mailbox.getSize( uidl );
}
if( mail.size < 1024 )
headerOnly = false;
boolean parseHeaders = mail.header == null;
if( headerOnly ) {
if( mail.header == null )
mail.header = mailbox.getHeader( uidl );
}
else {
if( mail.body == null ) {
mail.body = mailbox.getBody( uidl );
if( mail.body != null ) {
mail.header = mail.body;
MailPart.parse( mail );
}
}
}
if( parseHeaders && mail.header != null )
mail.parseHeaders();
}
if( mail != null && mail.deleted )
mail = null;
return mail;
}
}
/*
* Created on Nov 23, 2004
*
* This file is part of susimail project, see http://susi.i2p/
*
* Copyright (C) 2004-2005 <susi23@mail.i2p>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Revision: 1.2 $
*/
package i2p.susi.webmail;
import java.util.Hashtable;
import i2p.susi.webmail.pop3.POP3MailBox;
/**
* @author user
*/
public class MailCache {
public static final boolean FETCH_HEADER = true;
public static final boolean FETCH_ALL = false;
private POP3MailBox mailbox;
private String error;
private Hashtable mails;
private Object synchronizer;
MailCache( POP3MailBox mailbox ) {
this.mailbox = mailbox;
mails = new Hashtable();
synchronizer = new Object();
}
/**
* Fetch any needed data from pop3 server.
*
* @param id message id to get
* @param headerOnly fetch only header lines?
* @return
*/
public Mail getMail( String uidl, boolean headerOnly ) {
Mail mail = null, newMail = null;
if( mailbox != null ) {
/*
* synchronize update to hashtable
*/
synchronized( synchronizer ) {
mail = (Mail)mails.get( uidl );
if( mail == null ) {
newMail = new Mail();
mails.put( uidl, newMail );
}
}
if( mail == null ) {
mail = newMail;
mail.uidl = uidl;
mail.size = mailbox.getSize( uidl );
}
if( mail.size < 1024 )
headerOnly = false;
boolean parseHeaders = mail.header == null;
if( headerOnly ) {
if( mail.header == null )
mail.header = mailbox.getHeader( uidl );
}
else {
if( mail.body == null ) {
mail.body = mailbox.getBody( uidl );
if( mail.body != null ) {
mail.header = mail.body;
MailPart.parse( mail );
}
}
}
if( parseHeaders && mail.header != null )
mail.parseHeaders();
}
if( mail != null && mail.deleted )
mail = null;
return mail;
}
}