package zeta.handler.statistic;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import zeta.ZetaServlet;
import zeta.handler.ApproveHandler;
import zeta.handler.approve.ApproveProperties;
import zeta.util.CachedQueries;
import zeta.util.DatabaseUtils;
import zeta.util.QueryWithSum;
import zeta.util.SendMail;
import zeta.util.StreamUtils;
import zeta.util.StringUtils;
import zeta.util.Table;
import zeta.util.ThrowableHandler;
public class TopProducersHandler extends AbstractHandler {
public TopProducersHandler(ZetaServlet servlet) {
super(servlet, 600000, 0, 86400000); }
Table getTopProducersTable() {
return topProducersTable;
}
public String createPage(Connection con) throws SQLException, ServletException {
StringBuffer buffer = new StringBuffer(100*1024);
buffer.append("<tr><td colspan=\"6\">");
buffer.append("<br><center>");
HtmlTableGenerator generator = new HtmlTableGeneratorWithSum(servlet, servlet.getHandlerAddress(TopProducersHandler.class), "user");
Table table = new Table(7);
table.setColumnName(0, "place");
table.setType(0, Types.VARCHAR);
table.setAlignment(0, Table.LEFT);
table.setColumnName(1, "trend");
table.setType(1, Types.VARCHAR);
table.setAlignment(1, Table.CENTER);
table.setColumnName(2, "user");
table.setType(2, Types.VARCHAR);
table.setAlignment(2, Table.LEFT);
table.setColumnName(3, "age (days)");
table.setType(3, Types.INTEGER);
table.setAlignment(3, Table.RIGHT);
table.setColumnName(4, "work units");
table.setType(4, Types.INTEGER);
table.setAlignment(4, Table.RIGHT);
table.setColumnName(5, "computers used");
table.setType(5, Types.INTEGER);
table.setAlignment(5, Table.RIGHT);
table.setColumnName(6, "zeros");
table.setType(6, Types.INTEGER);
table.setAlignment(6, Table.RIGHT);
Statement stmt = null;
try {
stmt = con.createStatement();
long maxDays = CachedQueries.getMaxDays(stmt);
Map names = CachedQueries.getUserNames(con);
Set lowerUserNamesSet = names.keySet();
String[] lowerUserNames = new String[lowerUserNamesSet.size()];
lowerUserNamesSet.toArray(lowerUserNames);
Arrays.sort(lowerUserNames);
synchronized (lowerUserNameListOrderByZerosYesterday) {
if (maxDays != daysOfLowerUserNameListOrderByZerosDayBeforeYesterday+2) {
if (daysOfLowerUserNameListOrderByZerosYesterday+2 == maxDays) {
lowerUserNameListOrderByZerosDayBeforeYesterday = lowerUserNameListOrderByZerosYesterday;
daysOfLowerUserNameListOrderByZerosDayBeforeYesterday = daysOfLowerUserNameListOrderByZerosYesterday;
} else {
lowerUserNameListOrderByZerosDayBeforeYesterday = new ArrayList(lowerUserNamesSet.size());
ResultSet rs = stmt.executeQuery("SELECT LOWER(b.name) AS \"user\","
+ " SUM(CAST(a.range AS DECIMAL(15, 0))) AS \"zeros\""
+ " FROM zeta.computation a, zeta.user b, zeta.result r"
+ " WHERE a.task_id=r.task_id"
+ " AND a.work_unit_id=r.work_unit_id"
+ " AND a.user_id=b.id"
+ " AND a.server_id=b.server_id"
+ " AND DAYS(r.stop)<=" + (maxDays-2)
+ " GROUP BY LOWER(b.name) ORDER BY \"zeros\" DESC");
while (rs.next()) {
String user = rs.getString(1);
int idx = Arrays.binarySearch(lowerUserNames, user);
lowerUserNameListOrderByZerosDayBeforeYesterday.add((idx >= 0 && user.equals(lowerUserNames[idx]))? lowerUserNames[idx] : user);
}
rs.close();
daysOfLowerUserNameListOrderByZerosDayBeforeYesterday = maxDays-2;
}
}
if (maxDays != daysOfLowerUserNameListOrderByZerosYesterday+1) {
lowerUserNameListOrderByZerosYesterday = new ArrayList(lowerUserNamesSet.size());
ResultSet rs = stmt.executeQuery("SELECT LOWER(b.name) AS \"user\","
+ " SUM(CAST(a.range AS DECIMAL(15, 0))) AS \"zeros\""
+ " FROM zeta.computation a, zeta.user b, zeta.result r"
+ " WHERE a.task_id=r.task_id"
+ " AND a.work_unit_id=r.work_unit_id"
+ " AND a.user_id=b.id"
+ " AND a.server_id=b.server_id"
+ " AND DAYS(r.stop)<=" + (maxDays-1)
+ " GROUP BY LOWER(b.name) ORDER BY \"zeros\" DESC");
while (rs.next()) {
String user = rs.getString(1);
int idx = Arrays.binarySearch(lowerUserNames, user);
lowerUserNameListOrderByZerosYesterday.add((idx >= 0 && user.equals(lowerUserNames[idx]))? lowerUserNames[idx] : user);
}
rs.close();
daysOfLowerUserNameListOrderByZerosYesterday = maxDays-1;
}
}
ResultSet rs = stmt.executeQuery("SELECT LOWER(b.name) AS \"user\","
+ " COUNT(*) AS \"work units\","
+ " SUM(CAST(a.range AS DECIMAL(15, 0))) AS \"zeros\""
+ " FROM zeta.computation a, zeta.user b, zeta.result r"
+ " WHERE r.task_id=a.task_id"
+ " AND r.work_unit_id=a.work_unit_id"
+ " AND a.user_id=b.id"
+ " AND a.server_id=b.server_id"
+ " GROUP BY LOWER(b.name) ORDER BY \"zeros\" DESC");
for (int place = 0; rs.next(); ++place) {
table.addRow();
table.setValue(place, 0, Integer.toString(place+1) + '.');
String user = rs.getString(1);
int idx = Arrays.binarySearch(lowerUserNames, user);
if (idx >= 0 && user.equals(lowerUserNames[idx])) {
user = lowerUserNames[idx];
}
idx = 0;
int placeYesterday = lowerUserNameListOrderByZerosYesterday.indexOf(user);
int placeDayBeforeYesterday = lowerUserNameListOrderByZerosDayBeforeYesterday.indexOf(user);
if (placeYesterday < placeDayBeforeYesterday) {
++idx;
} else if (placeYesterday > placeDayBeforeYesterday) {
--idx;
}
if (place < placeYesterday) {
++idx;
} else if (place > placeYesterday) {
--idx;
}
if (idx < 0) {
table.setValue(place, 1, (idx < -1)? "--" : "-");
} else if (idx > 0) {
table.setValue(place, 1, (idx > 1)? "++" : "+");
} else {
table.setValue(place, 1, " ");
}
String s = (String)names.get(user);
table.setValue(place, 2, (s == null)? user : s);
Long userMinStartDays = CachedQueries.getUserMinStartDays(con, user);
if (userMinStartDays == null) {
table.setValue(place, 3, new Long(0));
} else {
table.setValue(place, 3, new Long(Math.max(0, maxDays - userMinStartDays.longValue())));
}
table.setValue(place, 4, new Integer(rs.getInt(2)));
table.setValue(place, 5, new Integer(CachedQueries.getMaxComputersUsed(user)));
table.setValue(place, 6, new Long(rs.getLong(3)));
}
rs.close();
} finally {
DatabaseUtils.close(stmt);
}
QueryWithSum.addSum(table);
CachedQueries.setNumberOfComputers(((Integer)table.getValue(table.getRowCount()-1, 5)).intValue());
buffer.append(generator.generate(table));
topProducersTable = table;
buffer.append("</center></td></tr>");
buffer.append("<tr><td colspan=\"6\">");
buffer.append("<br><center>");
generator = new HtmlTableGenerator(servlet);
buffer.append(generator.generate(CachedQueries.getUserData(con)));
buffer.append("</center></td></tr>");
return buffer.toString();
}
protected String createPage(HttpServletRequest req, Connection con) throws SQLException, ServletException {
String workunit = req.getParameter("workunit");
String user = req.getParameter("user");
if (user == null) {
if (req.getParameter("all") != null) {
InnerPageBuffer innerPageBuffer = null;
try {
if (innerPageBuffer != null) {
innerPageBuffer = getInnerPageBuffer();
ByteArrayOutputStream out = new ByteArrayOutputStream(10*1024);
StreamUtils.writeData(innerPageBuffer.buffer, out, false, true);
return out.toString("ISO-8859-1");
}
} catch (IOException ioe) {
} finally {
if (innerPageBuffer != null) {
innerPageBuffer.close();
}
}
}
StringBuffer buffer = new StringBuffer(1024);
inputUser(null, null, workunit, false, buffer);
return buffer.toString();
}
String key = req.getParameter("key");
String keyLength = req.getParameter("length");
String email = req.getParameter("email");
if (key != null && keyLength != null) {
StringBuffer buffer = new StringBuffer(1024);
requestApprovalToChangeProperties(con, key, keyLength, req, buffer);
return buffer.toString();
}
InnerPageBuffer innerPageBuffer = null;
try {
innerPageBuffer = getInnerPageBuffer();
if (innerPageBuffer == null) {
return "<tr><td colspan=\"8\"><p>This statistic is not available at moment! Please try again later.</td></tr>";
}
final int NUMBER_ABOVE_BELOW_USER = 3;
String beginTable = StreamUtils.between(innerPageBuffer.buffer, "<table", "</tr>", false);
StreamUtils.skip(innerPageBuffer.buffer, "<tr>", false);
String[] userLines = StreamUtils.getLines(innerPageBuffer.buffer, NUMBER_ABOVE_BELOW_USER+1, "</td><td><a href=\"" + servlet.getHandlerAddress(getClass()) + "?user=" + URLEncoder.encode(user, "ISO-8859-1") + "\">" + user + "</a></td><td class=\"r\">", true);
int userId = 0;
if (userLines != null && workunit != null) {
userId = isLoginNeeded(user, email, workunit);
if (userId == 0) {
StringBuffer buffer = new StringBuffer(2048);
if (workunit.length() > 0) {
buffer.append("<tr><td colspan=\"6\"><p><b>Error:</b> Work unit id '");
buffer.append(workunit);
buffer.append("' is invalid.</td></tr>");
}
inputUser(user, email, workunit, false, buffer);
return buffer.toString();
}
}
if (userLines == null) {
StringBuffer buffer = new StringBuffer(1024);
buffer.append("<tr><td colspan=\"6\"><p><b>Error:</b> User '");
buffer.append(user);
buffer.append("' is unknown.</td></tr>");
inputUser(null, null, workunit, false, buffer);
return buffer.toString();
} if (workunit != null) {
StringBuffer buffer = new StringBuffer(4096);
changeProperties(con, userId, workunit, buffer);
return buffer.toString();
} else {
String[] nextUsers = StreamUtils.getLines(innerPageBuffer.buffer, NUMBER_ABOVE_BELOW_USER);
String[] endTable = StreamUtils.getLines(innerPageBuffer.buffer, 2, "</table>", false);
String viewWorkstations = req.getParameter("view");
if (viewWorkstations == null || !viewWorkstations.equals("all")) {
viewWorkstations = "active";
}
boolean viewAllWorkstations = viewWorkstations.equals("all");
StringBuffer buffer = new StringBuffer(70*1024);
String userLine = null;
if (email != null) {
userLine = StreamUtils.between(innerPageBuffer.buffer, "><td>" + user + "</td><td>" + ((email.trim().length() == 0)? " " : email) + "</td><td", "</tr>", true);
if (userLine == null) {
if (email.trim().length() > 0) {
buffer.append("<tr><td colspan=\"6\"><p><b>Error:</b> E-mail '");
buffer.append(email);
buffer.append("' is unknown.</td></tr>");
}
innerPageBuffer.close();
innerPageBuffer = null;
innerPageBuffer = getInnerPageBuffer();
StreamUtils.skip(innerPageBuffer.buffer, "</table>", false);
email = null;
}
}
if (email == null) {
userLine = StreamUtils.between(innerPageBuffer.buffer, "><td>" + user + "</td><td", "</tr>", true);
if (userLine != null) {
int pos = userLine.indexOf('>');
int pos2 = userLine.indexOf("</td>", pos+1);
if (pos >= 0 && pos2 > pos) {
userLine = userLine.substring(pos2+5);
}
}
}
String[] userData = getUserData(userLine);
if (userData != null && (userData[5] == null || userData[5].length() == 0) && (userData[3] == null || userData[3].length() == 0)) {
while (true) {
if (email != null) {
userLine = StreamUtils.between(innerPageBuffer.buffer, "><td>" + user + "</td><td>" + ((email.trim().length() == 0)? " " : email) + "</td><td", "</tr>", true);
} else {
userLine = StreamUtils.between(innerPageBuffer.buffer, "><td>" + user + "</td><td", "</tr>", true);
if (userLine != null) {
int pos = userLine.indexOf('>');
int pos2 = userLine.indexOf("</td>", pos+1);
if (pos >= 0 && pos2 > pos) {
userLine = userLine.substring(pos2+5);
}
}
}
if (userLine == null) {
break;
}
String[] userData2 = getUserData(userLine);
if (userData2 != null && ((userData2[5] != null && userData2[5].length() > 0) || (userData2[3] != null && userData2[3].length() > 0))) {
userData = userData2;
break;
}
}
}
inputUser(user, email, null, viewAllWorkstations, buffer);
buffer.append("<tr><td colspan=\"6\" height=\"30pt\" class=\"second-head-gray\"><center>Top producer '");
buffer.append(user);
buffer.append("'</center></td></tr><tr><td colspan=\"6\">");
if (userData != null) {
Properties properties = new Properties();
if (userData[5] == null) {
userData[5] = "";
}
try {
properties.load(new ByteArrayInputStream(userData[5].getBytes()));
} catch (IOException ioe) {
}
String s = properties.getProperty("homepage", "");
if (s.length() > 0 || properties.getProperty("freetext", "").length() > 0 || properties.getProperty("visibleemail", "").length() > 0) {
buffer.append("<br><center><table cellspacing=\"0\" width=\"90%\" border=\"1\"><colgroup><col width=\"30%\"><col width=\"70%\"></colgroup>");
if (s.length() > 0) {
buffer.append("<tr><td>Homepage </td><td><a href=\"");
buffer.append(s);
buffer.append("\">");
buffer.append(s);
buffer.append("</a></td></tr>");
}
s = properties.getProperty("visibleemail", "");
if (s.length() > 0) {
buffer.append("<tr><td>Contact </td><td><a href=\"mailto:");
buffer.append(s);
buffer.append("\">");
buffer.append(s);
buffer.append("</a></td></tr>");
}
s = properties.getProperty("freetext", "");
if (s.length() > 0) {
buffer.append("<tr bgcolor=\"#eeeeee\"><td colspan=\"2\">");
buffer.append(s);
buffer.append("</td></tr>");
}
buffer.append("</table></center><p>");
} else {
buffer.append("<br>");
}
String teamName = userData[3];
if (teamName != null && teamName.length() > 0) {
buffer.append("<center><table cellspacing=\"0\" width=\"90%\" border=\"1\"><colgroup><col width=\"30%\"><col width=\"70%\"></colgroup>");
buffer.append("<tr><td>Member of team </td><td><a href=\"");
buffer.append(servlet.getHandlerAddress(TeamMembersHandler.class));
buffer.append("?team=");
buffer.append(URLEncoder.encode(teamName, "ISO-8859-1"));
buffer.append("\">");
buffer.append(teamName);
buffer.append("</a></td></tr>");
s = properties.getProperty("teamintroduction", "");
if (s.length() > 0) {
buffer.append("<tr bgcolor=\"#eeeeee\"><td colspan=\"2\">");
buffer.append(s);
buffer.append("</td></tr>");
}
buffer.append("</table></center>");
}
if (email != null) {
buffer.append("<br><center><table cellspacing=\"0\" width=\"90%\" border=\"1\"><colgroup><col width=\"60%\"><col width=\"40%\"></colgroup>");
buffer.append("<tr><td bgcolor=\"#eeeeee\">Number of redistributed work units (not delivered in 7 days) </td><td>");
buffer.append(userData[0]);
try {
if (userData[1].length() > 0 && !userData[1].equals(" ")) {
Long redistributedWorkUnitId = new Long(userData[1]);
if (redistributedWorkUnitId != null && redistributedWorkUnitId.longValue() > 0) {
buffer.append("</td></tr><tr><td bgcolor=\"#eeeeee\">Last redistributed work unit ID </td><td>");
DecimalFormat decFormatter = new DecimalFormat("#,###");
buffer.append(decFormatter.format(redistributedWorkUnitId));
buffer.append("</td></tr>");
try {
DateFormat dateFormatter = new SimpleDateFormat("MM/dd/yyyy", Locale.GERMANY);
String time = dateFormatter.format(Timestamp.valueOf(userData[2]));
buffer.append("<tr><td bgcolor=\"#eeeeee\">Last redistributed work unit at </td><td>");
buffer.append(time);
} catch (IllegalArgumentException iae) {
}
}
}
} catch (NumberFormatException nfe) {
}
buffer.append("</table></center>");
}
}
buffer.append("</td></tr>\n<style type=\"text/css\">\n.c { text-align:center }\n.r { text-align:right }\n</style>\n<tr><td colspan=\"6\" height=\"30pt\" class=\"second-head-gray\">Overall ranking (");
int l = endTable[0].length();
int i = 0;
while (++i < l && !Character.isDigit(endTable[0].charAt(i)));
while (i < l) {
char c = endTable[0].charAt(i);
if (!Character.isDigit(c)) {
break;
}
buffer.append(c);
++i;
}
buffer.append(" users):</td></tr><tr><td colspan=\"6\"><br><center><table");
buffer.append(beginTable);
buffer.append("</tr>\n");
for (i = 0; i+1 < userLines.length && userLines[i+1] != null; ++i) {
buffer.append(userLines[i]);
}
buffer.append("\n<tr bgcolor=\"#ffffe0\">");
buffer.append(userLines[i].substring(userLines[i].indexOf('>')+1));
for (i = 0; i < nextUsers.length && nextUsers[i] != null; ++i) {
buffer.append(nextUsers[i]);
}
final Class[] handlerClass = { TopProducers24HoursHandler.class, TopProducers7DaysHandler.class, CloseZerosHandler.class };
final String[] handlerTitle = { "Last 24 hours", "Last 7 days", "Close zeros" };
final String[] handlerNoWU = { "No work units delivered in the last 24 hours.", "No work units delivered in the last 7 days.", "No delivered work unit contains a close zero." };
final boolean[] handlerCountUser = { true, true, false };
for (int classIdx = 0; classIdx < handlerClass.length; ++classIdx) {
AbstractHandler handler = servlet.getStatisticHandler(handlerClass[classIdx]);
if (handler != null) {
String pageBuffer = handler.getBufferedPage(req);
int tableBegin = pageBuffer.indexOf("<th>user</th>")+13;
int userPlace = StringUtils.indexOfIgnoreCase(pageBuffer, "\">" + user + "</a></td><td", tableBegin);
if (userPlace == -1) {
String search = "\">" + user + ' ';
userPlace = StringUtils.indexOfIgnoreCase(pageBuffer, search, tableBegin);
final int lp = pageBuffer.length();
int idx;
for (idx = userPlace+search.length(); idx < lp && pageBuffer.charAt(idx) == ' '; ++idx);
if (idx == lp || pageBuffer.charAt(idx) != '<') {
userPlace = -1;
}
}
buffer.append("\n</table></center></td></tr>\n<tr><td colspan=\"6\" height=\"30pt\" class=\"second-head-gray\">");
buffer.append(handlerTitle[classIdx]);
int lp = pageBuffer.indexOf("</table>", tableBegin);
if (lp == -1) {
lp = pageBuffer.length();
}
if (handlerCountUser[classIdx]) {
buffer.append(" (");
i = pageBuffer.indexOf("∑");
while (++i < lp && !Character.isDigit(pageBuffer.charAt(i)));
while (i < lp) {
char c = pageBuffer.charAt(i);
if (!Character.isDigit(c)) {
break;
}
buffer.append(c);
++i;
}
buffer.append(" users)");
}
buffer.append(":</td></tr><tr><td colspan=\"6\"><br><center>");
if (userPlace < 0) {
buffer.append("<table><tr><td>");
buffer.append(handlerNoWU[classIdx]);
buffer.append("</td></tr>");
} else {
int statisticBegin = tableBegin;
for (int count = 1; statisticBegin > 0 && (pageBuffer.charAt(statisticBegin) != '\n' || --count >= 0); --statisticBegin);
while (tableBegin < lp && pageBuffer.charAt(tableBegin) != '\n') {
++tableBegin;
}
buffer.append(pageBuffer.substring(statisticBegin+1, tableBegin));
while (userPlace > tableBegin && pageBuffer.charAt(userPlace) != '\n') {
--userPlace;
}
i = userPlace;
for (int count = NUMBER_ABOVE_BELOW_USER; i > tableBegin && (pageBuffer.charAt(i) != '\n' || --count >= 0); --i);
buffer.append(pageBuffer.substring(i, userPlace));
buffer.append("\n<tr bgcolor=\"#ffffe0\">");
while (userPlace < lp && pageBuffer.charAt(userPlace) != '>') {
++userPlace;
}
i = ++userPlace;
for (int count = NUMBER_ABOVE_BELOW_USER; i < lp && (pageBuffer.charAt(i) != '\n' || --count >= 0); ++i);
buffer.append(pageBuffer.substring(userPlace, i));
}
}
}
buffer.append("</table></center></td></tr>");
if (email != null) {
WorkstationsHandler handler = new WorkstationsHandler(servlet); if (handler != null) {
ListGenerator generator = new ListGenerator();
String pageBuffer = handler.getBufferedPage(req);
int tableBegin = 0;
String search = "\n" + handler.encode("user") + user + ',' + email + ',';
for (tableBegin = StringUtils.indexOfIgnoreCase(pageBuffer, search, tableBegin); tableBegin >= 0; tableBegin = StringUtils.indexOfIgnoreCase(pageBuffer, search, tableBegin)) {
int wsEnd = pageBuffer.indexOf('\n', tableBegin+search.length());
if (wsEnd == -1) {
break;
}
String hostname = pageBuffer.substring(tableBegin+search.length(), wsEnd);
final int lp = pageBuffer.length();
tableBegin = wsEnd+1;
int tableEnd = pageBuffer.indexOf("\n" + handler.encode("user"), tableBegin);
String content = (tableEnd == -1)? pageBuffer.substring(tableBegin) : pageBuffer.substring(tableBegin, tableEnd);
if (viewAllWorkstations || handler.isActive(content)) {
buffer.append("\n<tr><td colspan=\"6\" height=\"30pt\" class=\"second-head-gray\">Workstation '");
buffer.append(hostname);
buffer.append("':</td></tr><tr><td colspan=\"6\"><br><center>");
buffer.append(generator.generateHTML(content, handler));
buffer.append("</center>");
}
tableBegin = tableEnd;
}
}
}
return buffer.toString();
}
} catch (IOException ioe) {
throw new ServletException(ioe); } finally {
if (innerPageBuffer != null) {
innerPageBuffer.close();
}
}
}
private static String[] getUserData(String line) {
if (line != null) {
int pos = line.indexOf('>');
int pos2 = line.indexOf("</td>", pos+1);
if (pos >= 0 && pos2 > pos) {
String numberOfRedistributions = line.substring(pos+1, pos2);
pos = line.indexOf('>', line.indexOf("<td", pos2+5)+3);
pos2 = line.indexOf("</td>", pos+1);
if (pos >= 0 && pos2 > pos) {
String lastRedistributedWorkUnit = line.substring(pos+1, pos2);
pos = line.indexOf('>', line.indexOf("<td", pos2+5)+3);
pos2 = line.indexOf("</td>", pos+1);
if (pos >= 0 && pos2 > pos) {
String lastRedistributedTimestamp = line.substring(pos+1, pos2);
pos = line.indexOf('>', line.indexOf("<td", pos2+5)+3);
pos2 = line.indexOf("</td>", pos+1);
if (pos >= 0 && pos2 > pos) {
String teamName = line.substring(pos+1, pos2).trim();
if (teamName.equals(" ")) {
teamName = null;
}
pos = line.indexOf('>', line.indexOf("<td", pos2+5)+3);
pos2 = line.indexOf("</td>", pos+1);
if (pos >= 0 && pos2 > pos) {
String messages = line.substring(pos+1, pos2);
pos = line.indexOf('>', line.indexOf("<td", pos2+5)+3);
pos2 = line.indexOf("</td>", pos+1);
if (pos >= 0 && pos2 > pos) {
String properties = line.substring(pos+1, pos2).trim();
if (properties.equals(" ")) {
properties = null;
}
return new String[] { numberOfRedistributions, lastRedistributedWorkUnit, lastRedistributedTimestamp, teamName, messages, properties };
}
}
}
}
}
}
}
return null;
}
private void inputUser(String user, String email, String workunit, boolean viewAllWorkstations, StringBuffer buffer) {
buffer.append("<tr><td colspan=\"6\"><form action=\"");
buffer.append(servlet.getHandlerAddress(getClass()));
buffer.append("\"><p>Please type your registered user name (exactly as it appears in the list) into the entry field.");
if (workunit == null) {
buffer.append("<br>Your position and three places above and below will be displayed.");
if (email == null) {
buffer.append("<br>To get more information about your computer(s) fill in your email address.");
} else {
buffer.append("<br>You can <a href=\"");
buffer.append(servlet.getHandlerAddress(getClass()));
buffer.append("?user=");
try {
buffer.append(URLEncoder.encode(user, "ISO-8859-1"));
buffer.append("&email=");
buffer.append(URLEncoder.encode(email, "ISO-8859-1"));
} catch (UnsupportedEncodingException uee) {
}
buffer.append("&workunit=");
buffer.append("\">change</a> any properties at the server which are associated with your user id.");
}
} else {
buffer.append("<p>You can change any properties at the server which are associated with your user id.");
}
buffer.append("<p><table><tr><td>User name </td><td><input name=\"user\" type=\"text\" size=\"60\" maxlength=\"100");
if (user != null) {
buffer.append("\" value=\"");
buffer.append(user);
}
buffer.append("\"></td><td> </td></tr><tr><td>E-mail </td><td><input name=\"email\" type=\"text\" size=\"60\" maxlength=\"100");
if (email != null) {
buffer.append("\" value=\"");
buffer.append(email);
}
if (workunit != null) {
buffer.append("\"></td><td> </td></tr><tr><td>Active work unit id </td><td><input name=\"workunit\" type=\"file\" size=\"60\" maxlength=\"100\" value=\"");
buffer.append(workunit);
buffer.append("\"></td><td> </td></tr>\n");
buffer.append("<tr><td colspan=\"3\"><table><tr><td>Notes:</td><td>1. Use either the whole filename like 'zeta_zeros_<id>_<range>.txt' or just the id.</td></tr>\n");
buffer.append("<tr><td></td><td>2. You cannot use a local work unit which is older than 7 days since it maybe redistributed.</td></tr></table></td></tr>\n");
buffer.append("<tr><td><input type=\"submit\" value=\"Login\"></td></tr>\n");
} else {
buffer.append("\"> <td><input type=\"submit\" value=\"View\"></td></tr>");
}
if (workunit == null && email != null && email.length() > 0) {
buffer.append("<tr><td><input type=\"radio\" name=\"view\" value=\"active\"");
if (!viewAllWorkstations) {
buffer.append(" checked");
}
buffer.append("></td><td>View only active workstations</td><td> </td></tr>");
buffer.append("<tr><td><input type=\"radio\" name=\"view\" value=\"all\"");
if (viewAllWorkstations) {
buffer.append(" checked");
}
buffer.append("></td><td>View all workstations</td><td> </td></tr>");
}
buffer.append("</table></form></td></tr>");
}
private int isLoginNeeded(String user, String email, String workunit) {
if (user != null && user.length() > 0 && email != null && email.length() > 0 && workunit != null && workunit.length() > 0) {
int i = 0;
for (int l = workunit.length(); i < l && !Character.isDigit(workunit.charAt(i)); ++i);
int j = i;
for (int l = workunit.length(); j < l && Character.isDigit(workunit.charAt(j)); ++j);
if (j > i) {
workunit = workunit.substring(i, j);
}
Connection con = null;
Statement stmt = null;
try {
con = servlet.getConnection();
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT user_id FROM zeta.computation c WHERE c.work_unit_id=" + workunit + " AND c.server_id=" + servlet.getServerId()
+ " AND c.task_id NOT IN (SELECT task_id FROM zeta.result WHERE work_unit_id=c.work_unit_id)"
+ " AND c.user_id IN (SELECT id FROM zeta.user WHERE server_id=c.server_id AND id=c.user_id AND name='" + user
+ "' AND email='" + email + "') AND user_id>0 ORDER BY user_id");
if (rs.next()) {
int userId = rs.getInt(1);
rs.close();
return userId;
}
rs.close();
} catch (ServletException e) {
ThrowableHandler.handle(e);
} catch (SQLException e) {
ThrowableHandler.handle(e);
} finally {
DatabaseUtils.close(stmt);
DatabaseUtils.close(con);
}
}
return 0;
}
private void changeProperties(Connection con, int userId, String workunit, StringBuffer buffer) throws ServletException {
buffer.append("<tr><td colspan=\"6\">You can change any properties at the server which are associated with your user id.");
Statement stmt = null;
try {
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT name,email,email_valid_YN,team_name,properties FROM zeta.user WHERE server_id=" + servlet.getServerId() + " AND id=" + userId);
if (rs.next()) {
buffer.append("<p><form action=\"");
buffer.append(servlet.getHandlerAddress(getClass()));
buffer.append("\"><table>");
buffer.append("<tr><td>user </td><td>");
String user = rs.getString(1);
buffer.append(user);
buffer.append("</td></tr><tr><td></td><td><input name=\"user\" type=\"text\" size=\"60\" maxlength=\"100\" value=\"");
buffer.append(user);
buffer.append("\"></td><td> </td></tr>");
buffer.append("<tr><td colspan=\"2\" background=\"/zeta/images/back_dots_66f.gif\"><img width=\"2\" src=\"/zeta/images/odot.gif\" height=\"2\" border=\"0\" alt=\"\"/></td></tr>");
buffer.append("<tr><td>e-mail address </td><td>");
String email = rs.getString(2);
buffer.append(email);
buffer.append("</td></tr><tr><td></td><td><input name=\"email\" type=\"text\" size=\"60\" maxlength=\"100\" value=\"");
buffer.append(email);
buffer.append("\"></td><td> </td></tr>");
buffer.append("<tr><td>visible to others </td><td>");
Properties properties = new Properties();
String s = rs.getString(5);
if (s == null) {
s = "";
}
try {
properties.load(new ByteArrayInputStream(s.getBytes()));
} catch (IOException ioe) {
}
s = properties.getProperty("visibleemail", "");
buffer.append(s);
buffer.append("</td></tr><tr><td></td><td><input name=\"visibleemail\" type=\"text\" size=\"60\" maxlength=\"100\" value=\"");
buffer.append(s);
buffer.append("\"></td><td> </td></tr><tr><td colspan=\"2\">note: Everybody could see your detailed statistic about your computer(s) if you make your e-mail address visible.</td></tr>");
buffer.append("<tr><td colspan=\"2\" background=\"/zeta/images/back_dots_66f.gif\"><img width=\"2\" src=\"/zeta/images/odot.gif\" height=\"2\" border=\"0\" alt=\"\"/></td></tr>");
buffer.append("<tr><td>receive announcements </td><td>");
String messages = rs.getString(3);
buffer.append((messages.equals("Y")? "yes" : "no"));
buffer.append("</td></tr>");
buffer.append("<tr><td></td><td><input name=\"messages\" type=\"checkbox\" value=\"Y\"");
if (messages.equals("Y")) {
buffer.append(" checked");
}
buffer.append("></td><td> </td></tr>");
buffer.append("<tr><td colspan=\"2\" background=\"/zeta/images/back_dots_66f.gif\"><img width=\"2\" src=\"/zeta/images/odot.gif\" height=\"2\" border=\"0\" alt=\"\"/></td></tr>");
buffer.append("<tr><td>team </td><td>");
String team = rs.getString(4);
if (team == null) {
team = "";
}
buffer.append(team);
buffer.append("</td></tr>");
buffer.append("<tr><td></td><td><input name=\"team\" type=\"text\" size=\"60\" maxlength=\"100\" value=\"");
buffer.append(team);
buffer.append("\"></td><td> </td></tr><tr><td colspan=\"2\">note: 'Join in team date' will be set to current date if you change your team membership.</td></tr>");
buffer.append("<tr><td colspan=\"2\" background=\"/zeta/images/back_dots_66f.gif\"><img width=\"2\" src=\"/zeta/images/odot.gif\" height=\"2\" border=\"0\" alt=\"\"/></td></tr>");
buffer.append("<tr><td>current<br>team introduction </td><td><textarea cols=\"60\" rows=\"4\" readonly>");
s = properties.getProperty("teamintroduction", "");
buffer.append(s);
buffer.append("</textarea></td></tr>");
buffer.append("<tr><td>new team introduction<br>(max. 255 characters)</td><td><textarea name=\"teamintroduction\" cols=\"60\" rows=\"4\">");
buffer.append(s);
buffer.append("</textarea></td><td> </td></tr>");
buffer.append("<tr><td colspan=\"2\" background=\"/zeta/images/back_dots_66f.gif\"><img width=\"2\" src=\"/zeta/images/odot.gif\" height=\"2\" border=\"0\" alt=\"\"/></td></tr>");
buffer.append("<tr><td>homepage </td><td><a href=\"");
s = properties.getProperty("homepage", "");
buffer.append(s);
buffer.append("\">");
buffer.append(s);
buffer.append("</a></td></tr>");
buffer.append("<tr><td></td><td><input name=\"homepage\" type=\"text\" size=\"60\" maxlength=\"100\" value=\"");
buffer.append(s);
buffer.append("\"></td><td> </td></tr>");
buffer.append("<tr><td colspan=\"2\" background=\"/zeta/images/back_dots_66f.gif\"><img width=\"2\" src=\"/zeta/images/odot.gif\" height=\"2\" border=\"0\" alt=\"\"/></td></tr>");
buffer.append("<tr><td>is team homepage </td><td>");
s = properties.getProperty("teamhomepage", "");
buffer.append((s.equals("true")? "yes" : "no"));
buffer.append("</td></tr>");
buffer.append("<tr><td></td><td><input name=\"teamhomepage\" type=\"checkbox\" value=\"true\"");
if (s.equals("true")) {
buffer.append(" checked");
}
buffer.append("></td><td> </td></tr>");
buffer.append("<tr><td colspan=\"2\" background=\"/zeta/images/back_dots_66f.gif\"><img width=\"2\" src=\"/zeta/images/odot.gif\" height=\"2\" border=\"0\" alt=\"\"/></td></tr>");
buffer.append("<tr><td>current<br>free text </td><td><textarea cols=\"60\" rows=\"4\" readonly>");
s = properties.getProperty("freetext", "");
buffer.append(s);
buffer.append("</textarea></td></tr>");
buffer.append("<tr><td>new free text<br>(max. 255 characters)</td><td><textarea name=\"freetext\" cols=\"60\" rows=\"4\">");
buffer.append(s);
buffer.append("</textarea></td></tr>");
buffer.append("<tr><td colspan=\"2\" background=\"/zeta/images/back_dots_66f.gif\"><img width=\"2\" src=\"/zeta/images/odot.gif\" height=\"2\" border=\"0\" alt=\"\"/></td></tr>");
String sessionKey = ApproveHandler.generateAddressToApprove(servlet, String.valueOf(userId) + ':' + workunit + ':' + email + ':' + user);
int idx = sessionKey.indexOf("?key=");
int idx2 = sessionKey.indexOf("&length=", idx);
buffer.append("<tr><td></td><td><input name=\"key\" type=\"hidden\" value=\"");
buffer.append(sessionKey.substring(idx+5, idx2));
buffer.append("\"></td></tr>");
buffer.append("<tr><td></td><td><input name=\"length\" type=\"hidden\" value=\"");
buffer.append(sessionKey.substring(idx2+8));
buffer.append("\"></td></tr>");
buffer.append("<tr><td colspan=\"2\">A link to approve the changes will be sent to '");
buffer.append(email);
buffer.append("' if you change some properties.</td></tr>");
buffer.append("<tr><td></td><td align=right><input type=\"submit\" value=\"Change\"></td></tr>");
buffer.append("</table></form>");
}
rs.close();
} catch (SQLException e) {
throw new ServletException(e);
} catch (IOException e) {
throw new ServletException(e);
} finally {
DatabaseUtils.close(stmt);
}
buffer.append("</td></tr>");
}
private void requestApprovalToChangeProperties(Connection con, String key, String keyLength, HttpServletRequest req, StringBuffer buffer) throws SQLException, ServletException {
Statement stmt = null;
try {
stmt = con.createStatement();
String sessionKey = ApproveHandler.decrypt(servlet, stmt, key, keyLength);
int idx = sessionKey.indexOf(':');
if (idx == -1) {
buffer.append("<tr><td colspan=\"6\"><p><b>Error:</b> Session key is invalid.</td></tr>");
return;
}
int userId = Integer.parseInt(sessionKey.substring(0, idx));
idx = sessionKey.indexOf(':', idx+1);
if (idx == -1) {
buffer.append("<tr><td colspan=\"6\"><p><b>Error:</b> Session key is invalid.</td></tr>");
return;
}
int idx2 = sessionKey.indexOf(':', idx+1);
if (idx2 == -1) {
buffer.append("<tr><td colspan=\"6\"><p><b>Error:</b> Session key is invalid.</td></tr>");
return;
}
String emailOrig = sessionKey.substring(idx+1, idx2);
String userOrig = sessionKey.substring(idx2+1);
ResultSet rs = stmt.executeQuery("SELECT email_valid_YN,team_name,properties FROM zeta.user WHERE server_id=" + servlet.getServerId() + " AND id=" + userId
+ " AND name='" + userOrig + "' AND email='" + emailOrig + '\'');
if (!rs.next()) {
rs.close();
buffer.append("<tr><td colspan=\"6\"><p><b>Error:</b> Session key is invalid or user '");
buffer.append(userOrig);
buffer.append("' (in combination with the defined e-mail address) is unknown.</td></tr>");
return;
}
String messagesOrig = rs.getString(1);
String teamOrig = rs.getString(2);
Properties properties = new Properties();
String prop = rs.getString(3);
rs.close();
if (prop == null) {
prop = "";
}
properties.load(new ByteArrayInputStream(prop.getBytes()));
String teamintroductionOrig = properties.getProperty("teamintroduction", "");
String homepageOrig = properties.getProperty("homepage", "");
String teamhomepageOrig = properties.getProperty("teamhomepage", "");
String freetextOrig = properties.getProperty("freetext", "");
String visibleemailOrig = properties.getProperty("visibleemail", "");
String user = req.getParameter("user");
String email = req.getParameter("email");
String messages = req.getParameter("messages");
if (messages == null || !messages.equals("Y")) {
messages = "N";
}
String team = req.getParameter("team");
String teamintroduction = req.getParameter("teamintroduction");
if (teamintroduction != null && teamintroduction.length() > 255) {
teamintroduction = teamintroduction.substring(0, 255);
}
String homepage = req.getParameter("homepage");
if (homepage != null && homepage.trim().length() > 0 && homepage.indexOf(':') == -1) {
homepage = "http://" + homepage;
}
String teamhomepage = req.getParameter("teamhomepage");
if (teamhomepage == null || !teamhomepage.equals("true")) {
teamhomepage = "false";
}
String freetext = req.getParameter("freetext");
if (freetext != null && freetext.length() > 255) {
freetext = freetext.substring(0, 255);
}
String visibleemail = req.getParameter("visibleemail");
if (visibleemail != null && visibleemail.length() > 100) {
visibleemail = visibleemail.substring(0, 100);
}
if (!user.equals(userOrig) || !email.equals(emailOrig)) {
rs = stmt.executeQuery("SELECT id FROM zeta.user WHERE server_id=" + servlet.getServerId() + " AND name='" + user + "' AND email='" + email + '\'');
if (rs.next()) {
rs.close();
buffer.append("<tr><td colspan=\"6\"><p><b>Error:</b> User '");
buffer.append(user);
buffer.append("' (in combination with the defined e-mail address) is already defined.</td></tr>");
return;
}
rs.close();
}
StringBuffer message1 = new StringBuffer(4000);
StringBuffer message2 = new StringBuffer(2000);
StringBuffer changeLocalConfig = new StringBuffer(500);
message1.append("If you want to change your current properties\n");
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
ZipOutputStream zip = new ZipOutputStream(out);
zip.setLevel(Deflater.BEST_COMPRESSION);
zip.putNextEntry(new ZipEntry("user_id"));
StreamUtils.writeData(new ByteArrayInputStream(String.valueOf(userId).getBytes()), zip, true, false);
zip.putNextEntry(new ZipEntry("user_orig"));
StreamUtils.writeData(new ByteArrayInputStream(userOrig.getBytes()), zip, true, false);
zip.putNextEntry(new ZipEntry("email_orig"));
StreamUtils.writeData(new ByteArrayInputStream(emailOrig.getBytes()), zip, true, false);
if (!user.equals(userOrig)) {
zip.putNextEntry(new ZipEntry("user"));
StreamUtils.writeData(new ByteArrayInputStream(user.getBytes()), zip, true, false);
message1.append("\nuser: ");
message1.append(userOrig);
message2.append("\nuser: ");
message2.append(user);
changeLocalConfig.append("\nname=");
changeLocalConfig.append(user);
}
if (!email.equals(emailOrig)) {
zip.putNextEntry(new ZipEntry("email"));
StreamUtils.writeData(new ByteArrayInputStream(email.getBytes()), zip, true, false);
message1.append("\nemail: ");
message1.append(emailOrig);
message2.append("\nemail: ");
message2.append(email);
changeLocalConfig.append("\neMail=");
changeLocalConfig.append(email);
}
if (!messages.equals(messagesOrig)) {
zip.putNextEntry(new ZipEntry("messages"));
StreamUtils.writeData(new ByteArrayInputStream(messages.getBytes()), zip, true, false);
message1.append("\nreceive announcements: ");
message1.append((messagesOrig.equals("Y"))? "yes" : "no");
message2.append("\nreceive announcements: ");
message2.append((messages.equals("Y"))? "yes" : "no");
changeLocalConfig.append("\nmessages=");
changeLocalConfig.append((messages.equals("Y"))? "true" : "false");
}
if (!team.equals(teamOrig)) {
zip.putNextEntry(new ZipEntry("team"));
StreamUtils.writeData(new ByteArrayInputStream(team.getBytes()), zip, true, false);
message1.append("\nteam: ");
message1.append(teamOrig);
message2.append("\nteam: ");
message2.append(team);
changeLocalConfig.append("\nteam=");
changeLocalConfig.append(team);
}
if (!teamintroduction.equals(teamintroductionOrig)) {
zip.putNextEntry(new ZipEntry("teamintroduction"));
StreamUtils.writeData(new ByteArrayInputStream(teamintroduction.getBytes()), zip, true, false);
message1.append("\nteamintroduction: ");
message1.append(teamintroductionOrig);
message2.append("\nteamintroduction: ");
message2.append(teamintroduction);
}
if (!homepage.equals(homepageOrig)) {
zip.putNextEntry(new ZipEntry("homepage"));
StreamUtils.writeData(new ByteArrayInputStream(homepage.getBytes()), zip, true, false);
message1.append("\nhomepage: ");
message1.append(homepageOrig);
message2.append("\nhomepage: ");
message2.append(homepage);
}
if (!teamhomepage.equals(teamhomepageOrig)) {
zip.putNextEntry(new ZipEntry("teamhomepage"));
StreamUtils.writeData(new ByteArrayInputStream(teamhomepage.getBytes()), zip, true, false);
message1.append("\nis homepage for the team: ");
message1.append((teamhomepageOrig.equals("true"))? "yes" : "no");
message2.append("\nis homepage for the team: ");
message2.append((teamhomepage.equals("true"))? "yes" : "no");
}
if (!freetext.equals(freetextOrig)) {
zip.putNextEntry(new ZipEntry("freetext"));
StreamUtils.writeData(new ByteArrayInputStream(freetext.getBytes()), zip, true, false);
message1.append("\nfreetext: ");
message1.append(freetextOrig);
message2.append("\nfreetext: ");
message2.append(freetext);
}
if (!visibleemail.equals(visibleemailOrig)) {
zip.putNextEntry(new ZipEntry("visibleemail"));
StreamUtils.writeData(new ByteArrayInputStream(visibleemail.getBytes()), zip, true, false);
message1.append("\ne-mail address is visible to others: ");
message1.append(visibleemailOrig);
message2.append("\ne-mail address is visible to others: ");
message2.append(visibleemail);
}
zip.flush();
zip.close();
message1.append("\n\nto the new properties\n");
rs = stmt.executeQuery("SELECT smtp_hostname,smtp_port,smtp_login_name,smtp_login_password FROM zeta.server WHERE server_id=" + servlet.getServerId());
if (rs.next()) {
String smtpHostname = rs.getString(1);
int smtpPort = rs.getInt(2);
String smtpLoginName = rs.getString(3);
String smtpPassword = rs.getString(4);
rs.close();
String title = "ZetaGrid needs your approval to change your current properties";
message1.append(message2.toString());
message1.append("\n\nthen click the following link to approve this:\n\n");
ApproveProperties approveProperties = new ApproveProperties(servlet, userId, userOrig, emailOrig);
message1.append(approveProperties.generateAddressToApprove(out.toByteArray()));
message1.append("\n\nRemark: The server needs at least 1 hour to update your changes in the statistics after your approval.");
if (changeLocalConfig.length() > 0) {
message1.append("\n\n! Please remeber to change the following line in your local configuration file 'zeta.cfg' before you restart your client (after the approval):\n");
message1.append(changeLocalConfig.toString());
}
message1.append("\n\nThis key is valid for 7 days.");
String messageText = message1.toString();
if (SendMail.isValidEmailAddressSyntax(emailOrig)) {
servlet.log("send email to " + emailOrig + " using " + smtpHostname + ':' + smtpPort + " change properties");
SendMail sendMail = new SendMail(smtpHostname, smtpPort, smtpLoginName, smtpPassword, "<office@zetagrid.net>", emailOrig, title, messageText);
sendMail.setPop3Authentication(110); sendMail.setRealNameFrom("\"ZetaGrid\" <office@zetagrid.net>");
sendMail.setRealNameTo("\"" + userOrig + "\" <" + emailOrig + '>');
sendMail.start();
buffer.append("<tr><td colspan=\"6\"><p>The e-mail is successfully sent to '");
buffer.append(emailOrig);
buffer.append("' with the following content:\n<p> <br>");
messageText = StringUtils.replace(messageText, "\n\n", "<br> <br>");
messageText = StringUtils.replace(messageText, "\n", "<br>");
idx = messageText.indexOf("to approve this:");
if (idx >= 0) {
messageText = messageText.substring(0, idx+16) + " ...";
}
buffer.append(messageText);
buffer.append("</td></tr>");
} else {
buffer.append("<tr><td colspan=\"6\"><p><b>Error:</b> The e-mail address '");
buffer.append(emailOrig);
buffer.append("' is not valid!</td></tr>");
}
buffer.append("<tr><td colspan=\"2\" background=\"/zeta/images/back_dots_66f.gif\"><img width=\"2\" src=\"/zeta/images/odot.gif\" height=\"2\" border=\"0\" alt=\"\"/></td></tr>");
buffer.append("<tr><td colspan=\"6\"><p><a href=\"");
buffer.append(servlet.getHandlerAddress(TopProducersHandler.class));
buffer.append("\">Back to statistic 'top producers'</a></td></tr>");
return;
} else {
rs.close();
}
} catch (IOException ioe) {
} finally {
DatabaseUtils.close(stmt);
}
buffer.append("<tr><td colspan=\"6\"><p>Internal server error!</td></tr>");
}
private Table topProducersTable = null;
private long daysOfLowerUserNameListOrderByZerosYesterday = 0;
private long daysOfLowerUserNameListOrderByZerosDayBeforeYesterday = 0;
private List lowerUserNameListOrderByZerosYesterday = new ArrayList(1);
private List lowerUserNameListOrderByZerosDayBeforeYesterday = null;
}