forked from I2P_Developers/i2p.i2p
merge of '9f159df098940fb0feecf6eae0c990c62736bb9c'
and 'ba82e9e4c57bd8d9f567c9252fe7b5815972e370'
This commit is contained in:
@@ -113,10 +113,10 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
renderForm(buf, ""+cur, ca.clientName,
|
||||
// urlify, enabled
|
||||
false, !ca.disabled,
|
||||
// read only
|
||||
// read only, preventDisable
|
||||
// dangerous, but allow editing the console args too
|
||||
//"webConsole".equals(ca.clientName) || "Web console".equals(ca.clientName),
|
||||
false,
|
||||
false, RouterConsoleRunner.class.getName().equals(ca.className),
|
||||
// description, edit
|
||||
ca.className + ((ca.args != null) ? " " + ca.args : ""), (""+cur).equals(_edit),
|
||||
// show edit button, show update button
|
||||
@@ -129,7 +129,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
}
|
||||
|
||||
if ("new".equals(_edit))
|
||||
renderForm(buf, "" + clients.size(), "", false, false, false, "", true, false, false, false, false, false);
|
||||
renderForm(buf, "" + clients.size(), "", false, false, false, false, "", true, false, false, false, false, false);
|
||||
buf.append("</table>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
@@ -150,7 +150,8 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
String val = props.getProperty(name);
|
||||
boolean isRunning = WebAppStarter.isWebAppRunning(app);
|
||||
renderForm(buf, app, app, !"addressbook".equals(app),
|
||||
"true".equals(val), RouterConsoleRunner.ROUTERCONSOLE.equals(app), app + ".war",
|
||||
"true".equals(val), RouterConsoleRunner.ROUTERCONSOLE.equals(app),
|
||||
RouterConsoleRunner.ROUTERCONSOLE.equals(app), app + ".war",
|
||||
false, false, false, isRunning, false, !isRunning);
|
||||
}
|
||||
}
|
||||
@@ -239,7 +240,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
enableStop &= PluginStarter.isPluginRunning(app, _context);
|
||||
boolean enableStart = !PluginStarter.isPluginRunning(app, _context);
|
||||
renderForm(buf, app, app, false,
|
||||
"true".equals(val), false, desc.toString(), false, false,
|
||||
"true".equals(val), false, false, desc.toString(), false, false,
|
||||
updateURL != null, enableStop, true, enableStart);
|
||||
}
|
||||
}
|
||||
@@ -253,7 +254,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
* ro trumps edit and showEditButton
|
||||
*/
|
||||
private void renderForm(StringBuilder buf, String index, String name, boolean urlify,
|
||||
boolean enabled, boolean ro, String desc, boolean edit,
|
||||
boolean enabled, boolean ro, boolean preventDisable, String desc, boolean edit,
|
||||
boolean showEditButton, boolean showUpdateButton, boolean showStopButton,
|
||||
boolean showDeleteButton, boolean showStartButton) {
|
||||
String escapeddesc = DataHelper.escapeHTML(desc);
|
||||
@@ -275,7 +276,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
buf.append("</td><td align=\"center\" width=\"10%\"><input type=\"checkbox\" class=\"optbox\" name=\"").append(index).append(".enabled\" value=\"true\" ");
|
||||
if (enabled) {
|
||||
buf.append("checked=\"checked\" ");
|
||||
if (ro)
|
||||
if (ro || preventDisable)
|
||||
buf.append("disabled=\"disabled\" ");
|
||||
}
|
||||
buf.append("></td><td align=\"center\" width=\"15%\">");
|
||||
|
@@ -13,8 +13,22 @@
|
||||
<condition property="no.bundle">
|
||||
<isfalse value="${require.gettext}" />
|
||||
</condition>
|
||||
<condition property="depend.available">
|
||||
<typefound name="depend" />
|
||||
</condition>
|
||||
<target name="depend" if="depend.available">
|
||||
<depend
|
||||
cache="../../build"
|
||||
srcdir="./src/src"
|
||||
destdir="./src/WEB-INF/classes" >
|
||||
<!-- Depend on classes instead of jars where available -->
|
||||
<classpath>
|
||||
<pathelement location="../../core/java/build/obj" />
|
||||
</classpath>
|
||||
</depend>
|
||||
</target>
|
||||
|
||||
<target name="compile">
|
||||
<target name="compile" depends="depend" >
|
||||
<mkdir dir="./src/WEB-INF/classes" />
|
||||
<javac
|
||||
srcdir="./src/src"
|
||||
|
@@ -13,7 +13,7 @@
|
||||
<url-pattern>/susimail</url-pattern>
|
||||
</servlet-mapping>
|
||||
<session-config>
|
||||
<session-timeout>15</session-timeout>
|
||||
<session-timeout>1440</session-timeout>
|
||||
</session-config>
|
||||
|
||||
<!--
|
||||
|
@@ -68,6 +68,16 @@ public class Config {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't bother showing a reload config button if this returns false.
|
||||
* @since 0.9.13
|
||||
*/
|
||||
public static boolean hasConfigFile() {
|
||||
File cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), "susimail.config");
|
||||
return cfg.exists();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
|
@@ -37,6 +37,9 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
/**
|
||||
* data structure to hold a single message, mostly used with folder view and sorting
|
||||
@@ -51,8 +54,12 @@ public class Mail {
|
||||
|
||||
public int id, size;
|
||||
public String sender, reply, subject, dateString,
|
||||
formattedSender, formattedSubject, formattedDate,
|
||||
shortSender, shortSubject, quotedDate, uidl;
|
||||
formattedSender, formattedSubject,
|
||||
formattedDate, // US Locale, UTC
|
||||
localFormattedDate, // Current Locale, local time zone
|
||||
shortSender, shortSubject,
|
||||
quotedDate, // Current Locale, local time zone, longer format
|
||||
uidl;
|
||||
public Date date;
|
||||
public ReadBuffer header, body;
|
||||
public MailPart part;
|
||||
@@ -68,6 +75,7 @@ public class Mail {
|
||||
formattedSender = unknown;
|
||||
formattedSubject = unknown;
|
||||
formattedDate = unknown;
|
||||
localFormattedDate = unknown;
|
||||
shortSender = unknown;
|
||||
shortSubject = unknown;
|
||||
quotedDate = unknown;
|
||||
@@ -110,7 +118,7 @@ public class Mail {
|
||||
for( int i = 0; i < tokens.length; i++ ) {
|
||||
if( tokens[i].matches( "^[^@< \t]+@[^> \t]+$" ) )
|
||||
return "<" + tokens[i] + ">";
|
||||
if( tokens[i].matches( "^<[^@< \t]+@[^> \t]+>$" ) )
|
||||
if( tokens[i].matches( "^<[^@< \t]+@[^> \t]+>$" ) )
|
||||
return tokens[i];
|
||||
}
|
||||
|
||||
@@ -149,7 +157,16 @@ public class Mail {
|
||||
}
|
||||
public void parseHeaders()
|
||||
{
|
||||
DateFormat dateFormatter = new SimpleDateFormat( Config.getProperty( DATEFORMAT, "mm/dd/yyyy HH:mm:ss" ) );
|
||||
DateFormat dateFormatter = new SimpleDateFormat("yyyy-mm-dd HH:mm");
|
||||
DateFormat localDateFormatter = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
|
||||
DateFormat longLocalDateFormatter = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM);
|
||||
// the router sets the JVM time zone to UTC but saves the original here so we can get it
|
||||
String systemTimeZone = I2PAppContext.getGlobalContext().getProperty("i2p.systemTimeZone");
|
||||
if (systemTimeZone != null) {
|
||||
TimeZone tz = TimeZone.getTimeZone(systemTimeZone);
|
||||
localDateFormatter.setTimeZone(tz);
|
||||
longLocalDateFormatter.setTimeZone(tz);
|
||||
}
|
||||
DateFormat mailDateFormatter = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH );
|
||||
|
||||
error = "";
|
||||
@@ -195,7 +212,9 @@ public class Mail {
|
||||
try {
|
||||
date = mailDateFormatter.parse( dateString );
|
||||
formattedDate = dateFormatter.format( date );
|
||||
quotedDate = html.encode( dateString );
|
||||
localFormattedDate = localDateFormatter.format( date );
|
||||
//quotedDate = html.encode( dateString );
|
||||
quotedDate = longLocalDateFormatter.format(date);
|
||||
}
|
||||
catch (ParseException e) {
|
||||
date = null;
|
||||
@@ -211,16 +230,16 @@ public class Mail {
|
||||
shortSubject = html.encode( shortSubject );
|
||||
}
|
||||
else if( line.toLowerCase(Locale.US).startsWith( "reply-to:" ) ) {
|
||||
reply = Mail.getAddress( line.substring( 9 ).trim() );
|
||||
reply = getAddress( line.substring( 9 ).trim() );
|
||||
}
|
||||
else if( line.startsWith( "To:" ) ) {
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
Mail.getRecipientsFromList( list, line.substring( 3 ).trim(), true );
|
||||
getRecipientsFromList( list, line.substring( 3 ).trim(), true );
|
||||
to = list.toArray();
|
||||
}
|
||||
else if( line.startsWith( "Cc:" ) ) {
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
Mail.getRecipientsFromList( list, line.substring( 3 ).trim(), true );
|
||||
getRecipientsFromList( list, line.substring( 3 ).trim(), true );
|
||||
cc = list.toArray();
|
||||
}
|
||||
}
|
||||
|
@@ -370,7 +370,9 @@ public class WebMail extends HttpServlet
|
||||
*/
|
||||
private static String sortHeader( String name, String label, String imgPath )
|
||||
{
|
||||
return "" + label + " <a href=\"" + myself + "?" + name + "=up\"><img src=\"" + imgPath + "3up.png\" border=\"0\" alt=\"^\"></a><a href=\"" + myself + "?" + name + "=down\"><img src=\"" + imgPath + "3down.png\" border=\"0\" alt=\"v\"></a>";
|
||||
return label + " <a href=\"" + myself + "?" + name + "=up\"><img src=\"" +
|
||||
imgPath + "3up.png\" border=\"0\" alt=\"^\"></a><a href=\"" + myself +
|
||||
"?" + name + "=down\"><img src=\"" + imgPath + "3down.png\" border=\"0\" alt=\"v\"></a>";
|
||||
}
|
||||
/**
|
||||
* check, if a given button "was pressed" in the received http request
|
||||
@@ -758,7 +760,7 @@ public class WebMail extends HttpServlet
|
||||
sessionObject.subject = "Re: " + mail.formattedSubject;
|
||||
StringWriter text = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter( text );
|
||||
pw.println( _("On {0} {1} wrote:", mail.formattedDate, sessionObject.replyTo) );
|
||||
pw.println( _("On {0} {1} wrote:", mail.formattedDate + " UTC", sessionObject.replyTo) );
|
||||
StringWriter text2 = new StringWriter();
|
||||
PrintWriter pw2 = new PrintWriter( text2 );
|
||||
showPart( pw2, mail.part, 0, TEXT_ONLY );
|
||||
@@ -1273,7 +1275,7 @@ public class WebMail extends HttpServlet
|
||||
if( sessionObject.state == STATE_LIST ) {
|
||||
processFolderButtons( sessionObject, request );
|
||||
for( Iterator<String> it = sessionObject.folder.currentPageIterator(); it != null && it.hasNext(); ) {
|
||||
String uidl = (String)it.next();
|
||||
String uidl = it.next();
|
||||
Mail mail = sessionObject.mailCache.getMail( uidl, MailCache.FETCH_HEADER );
|
||||
if( mail != null && mail.error.length() > 0 ) {
|
||||
sessionObject.error += mail.error;
|
||||
@@ -1579,9 +1581,10 @@ public class WebMail extends HttpServlet
|
||||
{
|
||||
out.println( button( SEND, _("Send") ) +
|
||||
button( CANCEL, _("Cancel") ) + spacer +
|
||||
(sessionObject.attachments != null && (!sessionObject.attachments.isEmpty()) ? button( DELETE_ATTACHMENT, _("Delete Attachment") ) : button2( DELETE_ATTACHMENT, _("Delete Attachment") ) ) + spacer +
|
||||
button( RELOAD, _("Reload Config") ) + spacer +
|
||||
button( LOGOUT, _("Logout") ) );
|
||||
(sessionObject.attachments != null && (!sessionObject.attachments.isEmpty()) ? button( DELETE_ATTACHMENT, _("Delete Attachment") ) : button2( DELETE_ATTACHMENT, _("Delete Attachment") ) ) + spacer);
|
||||
if (Config.hasConfigFile())
|
||||
out.println(button( RELOAD, _("Reload Config") ) + spacer);
|
||||
out.println(button( LOGOUT, _("Logout") ) );
|
||||
|
||||
String from = request.getParameter( NEW_FROM );
|
||||
String fixed = Config.getProperty( CONFIG_SENDER_FIXED, "true" );
|
||||
@@ -1672,18 +1675,21 @@ public class WebMail extends HttpServlet
|
||||
button( REPLYALL, _("Reply All") ) +
|
||||
button( FORWARD, _("Forward") ) + spacer +
|
||||
button( DELETE, _("Delete") ) + spacer +
|
||||
button( REFRESH, _("Check Mail") ) + spacer +
|
||||
button( RELOAD, _("Reload Config") ) + spacer +
|
||||
button( LOGOUT, _("Logout") ) + "<table id=\"mailbox\" cellspacing=\"0\" cellpadding=\"5\">\n" +
|
||||
button( REFRESH, _("Check Mail") ) + spacer);
|
||||
if (Config.hasConfigFile())
|
||||
out.println(button( RELOAD, _("Reload Config") ) + spacer);
|
||||
out.println(button( LOGOUT, _("Logout") ) + "<table id=\"mailbox\" cellspacing=\"0\" cellpadding=\"5\">\n" +
|
||||
"<tr><td colspan=\"8\"><hr></td></tr>\n<tr>" +
|
||||
thSpacer + "<th>" + sortHeader( SORT_SENDER, _("Sender"), sessionObject.imgPath ) + "</th>" +
|
||||
thSpacer + "<th>" + sortHeader( SORT_SUBJECT, _("Subject"), sessionObject.imgPath ) + "</th>" +
|
||||
thSpacer + "<th>" + sortHeader( SORT_DATE, _("Date"), sessionObject.imgPath ) + sortHeader( SORT_ID, "", sessionObject.imgPath ) + "</th>" +
|
||||
thSpacer + "<th>" + sortHeader( SORT_DATE, _("Date"), sessionObject.imgPath ) +
|
||||
//sortHeader( SORT_ID, "", sessionObject.imgPath ) +
|
||||
"</th>" +
|
||||
thSpacer + "<th>" + sortHeader( SORT_SIZE, _("Size"), sessionObject.imgPath ) + "</th></tr>" );
|
||||
int bg = 0;
|
||||
int i = 0;
|
||||
for( Iterator<String> it = sessionObject.folder.currentPageIterator(); it != null && it.hasNext(); ) {
|
||||
String uidl = (String)it.next();
|
||||
String uidl = it.next();
|
||||
Mail mail = sessionObject.mailCache.getMail( uidl, MailCache.FETCH_HEADER );
|
||||
String link = "<a href=\"" + myself + "?" + SHOW + "=" + i + "\">";
|
||||
|
||||
@@ -1705,7 +1711,9 @@ public class WebMail extends HttpServlet
|
||||
", invert=" + sessionObject.invert +
|
||||
", clear=" + sessionObject.clear );
|
||||
out.println( "<tr class=\"list" + bg + "\"><td><input type=\"checkbox\" class=\"optbox\" name=\"check" + i + "\" value=\"1\"" +
|
||||
( idChecked ? "checked" : "" ) + ">" + ( RELEASE ? "" : "" + i ) + "</td><td>" + link + mail.shortSender + "</a></td><td> </td><td>" + link + mail.shortSubject + "</a></td><td> </td><td>" + mail.formattedDate + "</td><td> </td><td>" + ngettext("1 Byte", "{0} Bytes", mail.size) + "</td></tr>" );
|
||||
( idChecked ? "checked" : "" ) + ">" + ( RELEASE ? "" : "" + i ) + "</td><td>" +
|
||||
link + mail.shortSender + "</a></td><td> </td><td>" + link + mail.shortSubject + "</a></td><td> </td><td>" +
|
||||
mail.localFormattedDate + "</td><td> </td><td>" + ngettext("1 Byte", "{0} Bytes", mail.size) + "</td></tr>" );
|
||||
bg = 1 - bg;
|
||||
i++;
|
||||
}
|
||||
@@ -1754,15 +1762,19 @@ public class WebMail extends HttpServlet
|
||||
button( DELETE, _("Delete") ) + spacer +
|
||||
( sessionObject.folder.isFirstElement( sessionObject.showUIDL ) ? button2( PREV, _("Previous") ) : button( PREV, _("Previous") ) ) +
|
||||
( sessionObject.folder.isLastElement( sessionObject.showUIDL ) ? button2( NEXT, _("Next") ) : button( NEXT, _("Next") ) ) + spacer +
|
||||
button( LIST, _("Back to Folder") ) + spacer +
|
||||
button( RELOAD, _("Reload Config") ) + spacer +
|
||||
button( LOGOUT, _("Logout") ) );
|
||||
button( LIST, _("Back to Folder") ) + spacer);
|
||||
if (Config.hasConfigFile())
|
||||
out.println(button( RELOAD, _("Reload Config") ) + spacer);
|
||||
out.println(button( LOGOUT, _("Logout") ) );
|
||||
if( mail != null ) {
|
||||
out.println( "<table cellspacing=\"0\" cellpadding=\"5\">\n" +
|
||||
"<tr><td colspan=\"2\" align=\"center\"><hr></td></tr>\n" +
|
||||
"<tr class=\"mailhead\"><td align=\"right\">" + _("From:") + "</td><td align=\"left\">" + quoteHTML( mail.formattedSender ) + "</td></tr>\n" +
|
||||
"<tr class=\"mailhead\"><td align=\"right\">" + _("Date:") + "</td><td align=\"left\">" + mail.quotedDate + "</td></tr>\n" +
|
||||
"<tr class=\"mailhead\"><td align=\"right\">" + _("Subject:") + "</td><td align=\"left\">" + quoteHTML( mail.formattedSubject ) + "</td></tr>\n" +
|
||||
"<tr class=\"mailhead\"><td align=\"right\" valign=\"top\">" + _("From:") +
|
||||
"</td><td align=\"left\">" + quoteHTML( mail.sender ) + "</td></tr>\n" +
|
||||
"<tr class=\"mailhead\"><td align=\"right\" valign=\"top\">" + _("Date:") +
|
||||
"</td><td align=\"left\">" + mail.quotedDate + "</td></tr>\n" +
|
||||
"<tr class=\"mailhead\"><td align=\"right\" valign=\"top\">" + _("Subject:") +
|
||||
"</td><td align=\"left\">" + quoteHTML( mail.formattedSubject ) + "</td></tr>\n" +
|
||||
"<tr><td colspan=\"2\" align=\"center\"><hr></td></tr>" );
|
||||
if( mail.body != null ) {
|
||||
showPart( out, mail.part, 0, SHOW_HTML );
|
||||
|
@@ -23,12 +23,14 @@
|
||||
*/
|
||||
package i2p.susi.webmail.encoding;
|
||||
|
||||
import i2p.susi.debug.Debug;
|
||||
import i2p.susi.util.HexTable;
|
||||
import i2p.susi.util.ReadBuffer;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Ref:
|
||||
@@ -170,7 +172,8 @@ public class HeaderLine implements Encoding {
|
||||
if( length > 0 ) {
|
||||
if( in[offset] == '?' ) {
|
||||
// System.err.println( "=? found at " + ( offset -1 ) );
|
||||
int f2 = offset + 1;
|
||||
int f1 = offset;
|
||||
int f2 = f1 + 1;
|
||||
// FIXME save charset here ticket #508
|
||||
for( ; f2 < end && in[f2] != '?'; f2++ );
|
||||
if( f2 < end ) {
|
||||
@@ -201,18 +204,31 @@ public class HeaderLine implements Encoding {
|
||||
try {
|
||||
// System.err.println( "decode(" + (f3 + 1) + "," + ( f4 - f3 - 1 ) + ")" );
|
||||
tmp = e.decode( in, f3 + 1, f4 - f3 - 1 );
|
||||
// FIXME use saved charset here ticket #508
|
||||
for( int j = 0; j < tmp.length; j++ ) {
|
||||
byte d = tmp.content[ tmp.offset + j ];
|
||||
out[written++] = ( d == '_' ? 32 : d );
|
||||
// get charset
|
||||
String charset = new String(in, f1 + 1, f2 - f1 - 1, "ISO-8859-1");
|
||||
String clc = charset.toLowerCase(Locale.US);
|
||||
if (clc.equals("utf-8") || clc.equals("utf8")) {
|
||||
for( int j = 0; j < tmp.length; j++ ) {
|
||||
byte d = tmp.content[ tmp.offset + j ];
|
||||
out[written++] = ( d == '_' ? 32 : d );
|
||||
}
|
||||
} else {
|
||||
// decode string
|
||||
String decoded = new String(tmp.content, tmp.offset, tmp.length, charset);
|
||||
// encode string
|
||||
byte[] utf8 = decoded.getBytes("UTF-8");
|
||||
for( int j = 0; j < utf8.length; j++ ) {
|
||||
byte d = utf8[j];
|
||||
out[written++] = ( d == '_' ? 32 : d );
|
||||
}
|
||||
}
|
||||
int distance = f4 + 2 - offset;
|
||||
offset += distance;
|
||||
length -= distance;
|
||||
lastCharWasQuoted = true;
|
||||
continue;
|
||||
}
|
||||
catch (Exception e1) {
|
||||
} catch (Exception e1) {
|
||||
Debug.debug(Debug.ERROR, e1.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -38,19 +38,19 @@ import java.net.Socket;
|
||||
*/
|
||||
public class SMTPClient {
|
||||
|
||||
Socket socket;
|
||||
byte buffer[];
|
||||
private Socket socket;
|
||||
private final byte buffer[];
|
||||
public String error;
|
||||
String lastResponse;
|
||||
private String lastResponse;
|
||||
|
||||
private static Encoding base64 = null;
|
||||
private static final Encoding base64;
|
||||
|
||||
static {
|
||||
base64 = EncodingFactory.getEncoding( "base64" );
|
||||
}
|
||||
|
||||
public SMTPClient()
|
||||
{
|
||||
socket = null;
|
||||
buffer = new byte[10240];
|
||||
error = "";
|
||||
lastResponse = "";
|
||||
|
@@ -11,10 +11,10 @@ susimail.fast.start=true
|
||||
susimail.sender.fixed=true
|
||||
susimail.sender.domain=mail.i2p
|
||||
|
||||
susimail.pager.pagesize=10
|
||||
susimail.pager.pagesize=40
|
||||
|
||||
susimail.composer.cols=80
|
||||
susimail.composer.rows=15
|
||||
susimail.composer.bcc.to.self=true
|
||||
|
||||
susimail.date.format=MM/dd/yyyy HH:mm:ss
|
||||
susimail.date.format=MM/dd/yyyy HH:mm:ss
|
||||
|
12
history.txt
12
history.txt
@@ -1,3 +1,15 @@
|
||||
2014-04-18 zzz
|
||||
* configclients: Don't allow console disable
|
||||
* SusiMail:
|
||||
- Extend session expiration (ticket #1253)
|
||||
- Handle non-UTF8 encoding on header lines (ticket #508)
|
||||
- Display dates in current locale and time zone
|
||||
- Display sender name on message view
|
||||
- Remove sort-by-ID buttons
|
||||
- Hide "reload config" button unless config file is present
|
||||
- Increase default page size
|
||||
- Add dependency tracking to build
|
||||
|
||||
2014-04-17 zzz
|
||||
* i2psnark: Randomize announce list order and limit size
|
||||
* SSU: SessionRequest replay prevention (ticket #1212)
|
||||
|
Reference in New Issue
Block a user