diff --git a/etc/venice-config.xml b/etc/venice-config.xml index 790fe0a..e531ade 100644 --- a/etc/venice-config.xml +++ b/etc/venice-config.xml @@ -285,6 +285,7 @@ + diff --git a/src/com/silverwrist/venice/core/ConferenceContext.java b/src/com/silverwrist/venice/core/ConferenceContext.java index d38dbb7..e296afd 100644 --- a/src/com/silverwrist/venice/core/ConferenceContext.java +++ b/src/com/silverwrist/venice/core/ConferenceContext.java @@ -171,4 +171,7 @@ public interface ConferenceContext public abstract boolean canSendInvitation(); + public abstract void sendMailToParticipants(boolean posters, int day_limit, String subject, String text) + throws AccessError, DataException; + } // end interface ConferenceContext diff --git a/src/com/silverwrist/venice/core/TopicContext.java b/src/com/silverwrist/venice/core/TopicContext.java index ea61cf4..b094df4 100644 --- a/src/com/silverwrist/venice/core/TopicContext.java +++ b/src/com/silverwrist/venice/core/TopicContext.java @@ -110,5 +110,8 @@ public interface TopicContext public abstract boolean canSendInvitation(); + public abstract void sendMailToParticipants(boolean posters, int day_limit, String subject, String text) + throws AccessError, DataException; + } // end interface TopicContext diff --git a/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java b/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java index 193f7a4..18b2b76 100644 --- a/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java @@ -888,6 +888,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend public TopicContext addTopic(String title, String zp_pseud, String zp_text) throws DataException, AccessError { + if (logger.isDebugEnabled()) + logger.debug("addTopic(\"" + title + "\") entry"); if (!(getConferenceData().canCreateTopic(level))) { // not allowed to create a topic - bail out logger.error("addTopic(): user not permitted to create new topic"); @@ -920,6 +922,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend { // call down to create the new topic! real_title = title_ch.getValue(); new_topic_inf = getConferenceData().createNewTopic(env,real_title,zp_pseud_ch.getValue(),zp_text); + if (logger.isDebugEnabled()) + logger.debug("Created new topic ID #" + new_topic_inf.getTopicID()); } // end try catch (NotYetFinishedException e) @@ -939,6 +943,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend StringBuffer sql = new StringBuffer("INSERT INTO topicsettings (topicid, uid, last_post) VALUES ("); sql.append(new_topic_inf.getTopicID()).append(", ").append(env.getUserID()).append(", '"); sql.append(SQLUtil.encodeDate(new_topic_inf.getCreateDate())).append("');"); + if (logger.isDebugEnabled()) + logger.debug("SQL: " + sql.toString()); stmt.executeUpdate(sql.toString()); // update the conference last-post information @@ -1489,6 +1495,90 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend } // end canSendInvitation + public void sendMailToParticipants(boolean posters, int day_limit, String subject, String text) + throws AccessError, DataException + { + if (logger.isDebugEnabled()) + logger.debug("sendMailToParticipants(" + posters + "," + day_limit + ")"); + if (!(env.testPermission("Conference.EMailParticipants"))) + throw new AccessError("You are not permitted to send E-mail to conference participants."); + + if (day_limit==0) + return; // no-op + java.util.Date stop_point = null; + if (day_limit>0) + { // compute stop point as a number of days back from this instant + Calendar right_now = Calendar.getInstance(); + right_now.add(Calendar.DAY_OF_MONTH,-day_limit); + stop_point = right_now.getTime(); + + } // end if + + Connection conn = null; + ArrayList rc = new ArrayList(); + + try + { // retrieve a connection + conn = env.getConnection(); + Statement stmt = conn.createStatement(); + + // Build the SQL statement. + StringBuffer sql = new StringBuffer("SELECT c.email, "); + if (posters) + sql.append("s.last_post"); + else + sql.append("s.last_read"); + sql.append(" FROM contacts c, users u, confsettings s WHERE c.contactid = u.contactid " + + "AND u.uid = s.uid AND s.confid = ").append(confid).append(" AND u.is_anon = 0 AND "); + if (posters) + sql.append("ISNULL(s.last_post) = 0 ORDER BY s.last_post DESC;"); + else + sql.append("ISNULL(s.last_read) = 0 ORDER BY s.last_read DESC;"); + if (logger.isDebugEnabled()) + logger.debug("SQL: " + sql.toString()); + + // Execute the query and start reading E-mail addresses. + ResultSet rs = stmt.executeQuery(sql.toString()); + while (rs.next()) + { // accumulate E-mail addresses + if (stop_point!=null) + { // see if we can stop the loop yet + java.util.Date x = SQLUtil.getFullDateTime(rs,2); + if (stop_point.compareTo(x)>0) + break; + + } // end if + + rc.add(rs.getString(1)); // save off the E-mail address + + } // end while + + if (logger.isDebugEnabled()) + logger.debug("Selected " + rc.size() + " address(es) for E-mailing"); + + } // end try + catch (SQLException e) + { // this becomes a DataException + logger.error("DB error getting active poster list: " + e.getMessage(),e); + throw new DataException("unable to get active poster listing: " + e.getMessage(),e); + + } // end catch + finally + { // make sure we release the connection before we go + env.releaseConnection(conn); + + } // end finally + + if (rc.size()>0) + { // send the actual E-mail messages in the background + MailerAgent agent = new MailerAgent(env,env.getUser().realUserName(),env.getUser().realEmailAddress(), + rc,subject,text); + agent.start(); + + } // end if + + } // end if + /*-------------------------------------------------------------------------------- * Implementations from interface ConferenceBackend *-------------------------------------------------------------------------------- diff --git a/src/com/silverwrist/venice/core/impl/MailerAgent.java b/src/com/silverwrist/venice/core/impl/MailerAgent.java new file mode 100644 index 0000000..03615be --- /dev/null +++ b/src/com/silverwrist/venice/core/impl/MailerAgent.java @@ -0,0 +1,118 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.core.impl; + +import java.util.*; +import org.apache.log4j.*; +import com.silverwrist.util.StringUtil; +import com.silverwrist.venice.core.internals.*; +import com.silverwrist.venice.except.*; +import com.silverwrist.venice.htmlcheck.*; + +class MailerAgent extends Thread +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Category logger = Category.getInstance(MailerAgent.class); + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private EnvUser env; // the environment + private String from_name; // the "from" name + private String from_addr; // the "from" address + private List recipients; // who gets the message + private String subject; // message subject + private String text; // message text + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + MailerAgent(EnvUser env, String from_name, String from_addr, List recipients, String subject, String text) + { + super(); + setDaemon(false); + + this.env = env; + this.from_name = from_name; + this.from_addr = from_addr; + this.recipients = recipients; + this.subject = subject; + this.text = text; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class Thread + *-------------------------------------------------------------------------------- + */ + + public void run() + { + NDC.push("MailerAgent"); + + try + { // attach the signature to the message + StringBuffer buf = new StringBuffer(text); + buf.append("\n--\n").append(env.getStockMessage("signature")); + + // Create the emailer object and load it up with most of the data. + Emailer em = env.getEngine().createEmailer(); + em.setSubject(subject); + em.setText(buf.toString()); + + // Deliver the mail to each of the target addresses in turn. + Iterator it = recipients.iterator(); + while (it.hasNext()) + { // get ready to deliver the mail... + String addr = (String)(it.next()); + if (logger.isDebugEnabled()) + logger.debug("Delivering to " + addr); + + try + { // set the recipient and send it out + em.setFrom(from_name,from_addr); + em.setTo(addr); + em.send(); + + } // end try + catch (EmailException e) + { // log the error and move on + logger.error("Caught EmailException when trying to send to " + addr,e); + + } // end catch + + } // end while + + } // end try + finally + { // make sure and pop the diagnostic context before we go + NDC.pop(); + + } // end finally + + } // end run + +} // end class MailerAgent diff --git a/src/com/silverwrist/venice/core/impl/PostDeliveryAgent.java b/src/com/silverwrist/venice/core/impl/PostDeliveryAgent.java index be3856a..1f5d7dc 100644 --- a/src/com/silverwrist/venice/core/impl/PostDeliveryAgent.java +++ b/src/com/silverwrist/venice/core/impl/PostDeliveryAgent.java @@ -51,7 +51,7 @@ class PostDeliveryAgent extends Thread PostDeliveryAgent(EnvConference env, String txt, String pseud, String topicname, int topicnum, List addrs) { - super("PostDeliveryAgent"); + super(); setDaemon(false); // Save the calling data. diff --git a/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java b/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java index 0eb4fde..281dbf3 100644 --- a/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/TopicUserContextImpl.java @@ -1310,6 +1310,90 @@ class TopicUserContextImpl implements TopicContext } // end canSendInvitation + public void sendMailToParticipants(boolean posters, int day_limit, String subject, String text) + throws AccessError, DataException + { + if (logger.isDebugEnabled()) + logger.debug("sendMailToParticipants(" + posters + "," + day_limit + ")"); + if (!(env.testPermission("Conference.EMailParticipants"))) + throw new AccessError("You are not permitted to send E-mail to conference participants."); + + if (day_limit==0) + return; // no-op + java.util.Date stop_point = null; + if (day_limit>0) + { // compute stop point as a number of days back from this instant + Calendar right_now = Calendar.getInstance(); + right_now.add(Calendar.DAY_OF_MONTH,-day_limit); + stop_point = right_now.getTime(); + + } // end if + + Connection conn = null; + ArrayList rc = new ArrayList(); + + try + { // retrieve a connection + conn = env.getConnection(); + Statement stmt = conn.createStatement(); + + // Build the SQL statement. + StringBuffer sql = new StringBuffer("SELECT c.email, "); + if (posters) + sql.append("s.last_post"); + else + sql.append("s.last_read"); + sql.append(" FROM contacts c, users u, topicsettings s WHERE c.contactid = u.contactid " + + "AND u.uid = s.uid AND s.topicid = ").append(topicid).append(" AND u.is_anon = 0 AND "); + if (posters) + sql.append("ISNULL(s.last_post) = 0 ORDER BY s.last_post DESC;"); + else + sql.append("ISNULL(s.last_read) = 0 ORDER BY s.last_read DESC;"); + if (logger.isDebugEnabled()) + logger.debug("SQL: " + sql.toString()); + + // Execute the query and start reading E-mail addresses. + ResultSet rs = stmt.executeQuery(sql.toString()); + while (rs.next()) + { // accumulate E-mail addresses + if (stop_point!=null) + { // see if we can stop the loop yet + java.util.Date x = SQLUtil.getFullDateTime(rs,2); + if (stop_point.compareTo(x)>0) + break; + + } // end if + + rc.add(rs.getString(1)); // save off the E-mail address + + } // end while + + if (logger.isDebugEnabled()) + logger.debug("Selected " + rc.size() + " address(es) for E-mailing"); + + } // end try + catch (SQLException e) + { // this becomes a DataException + logger.error("DB error getting active poster list: " + e.getMessage(),e); + throw new DataException("unable to get active poster listing: " + e.getMessage(),e); + + } // end catch + finally + { // make sure we release the connection before we go + env.releaseConnection(conn); + + } // end finally + + if (rc.size()>0) + { // send the actual E-mail messages in the background + MailerAgent agent = new MailerAgent(env,env.getUser().realUserName(),env.getUser().realEmailAddress(), + rc,subject,text); + agent.start(); + + } // end if + + } // end sendMailToParticipants + /*-------------------------------------------------------------------------------- * External operations usable only from within the package *-------------------------------------------------------------------------------- diff --git a/src/com/silverwrist/venice/servlets/ConfOperations.java b/src/com/silverwrist/venice/servlets/ConfOperations.java index 1c56bad..845ac7d 100644 --- a/src/com/silverwrist/venice/servlets/ConfOperations.java +++ b/src/com/silverwrist/venice/servlets/ConfOperations.java @@ -158,6 +158,7 @@ public class ConfOperations extends VeniceServlet * E = Edit Conference Settings (requires conference parameter) * FX = Fixseen (requires conference parameter) * H = Add Conference to Hotlist (requires conference parameter) + * I = Conference E-Mail (requires conference parameter) * M = Manage Conference Membership (requires conference parameter) * Q = Display Conference Manage menu (requires conference parameter) * RP = Report on Posters (requires conference parameter) @@ -589,6 +590,30 @@ public class ConfOperations extends VeniceServlet } // end if ("H" command) + if (cmd.equals("I")) + { // "I" = "Conference E-Mail" (requires conference parameter) + ConferenceContext conf = getConferenceParameter(request,comm,true,on_error); + on_error = "confops?sig=" + comm.getCommunityID() + "&conf=" + conf.getConfID() + "&cmd=Q"; + + try + { // return the conference E-mail view + return new ConferenceEMail(comm,conf); + + } // end try + catch (DataException de) + { // something wrong in the database + return new ErrorBox("Database Error","Database error getting topic list " + de.getMessage(), + on_error); + + } // end catch + catch (AccessError ae) + { // some lack of access is causing problems + return new ErrorBox("Access Error",ae.getMessage(),on_error); + + } // end catch + + } // end if ("I" command) + if (cmd.equals("DEL")) { // "DEL" = "Delete Conference (requires conference parameter) ConferenceContext conf = getConferenceParameter(request,comm,true,on_error); @@ -1040,6 +1065,80 @@ public class ConfOperations extends VeniceServlet } // end if ("M" command) + if (cmd.equals("I")) + { // "I" = "Conference E-Mail" + ConferenceContext conf = getConferenceParameter(request,comm,true,on_error); + on_error = "confops?sig=" + comm.getCommunityID() + "&conf=" + conf.getConfID() + "&cmd=I"; + + if (isImageButtonClicked(request,"cancel")) // "Cancel" button pressed - bail out + throw new RedirectResult("confops?sig=" + comm.getCommunityID() + "&conf=" + conf.getConfID() + + "&cmd=Q"); + + if (isImageButtonClicked(request,"send")) + { // OK, figure out who we want to send E-mail to + try + { // retrieve the topic we want to send to + TopicContext topic = null; + String s = request.getParameter("top"); + if ((s!=null) && !(s.equals("0"))) + topic = conf.getTopic(Short.parseShort(s)); + + // retrieve other parameters + final String ZERO = "0"; + boolean posters = ZERO.equals(request.getParameter("porl")); + final String YES = "Y"; + int ndays = -1; + if (YES.equals(request.getParameter("xday"))) + { // they selected "within the last X days" + try + { // parse the number of days + s = request.getParameter("day"); + if (s!=null) + ndays = Integer.parseInt(s); + else + ndays = 0; + + } // end try + catch (NumberFormatException nfe) + { // always fail safe when doing e-mail parameters! + ndays = 0; + + } // end catch + + } // end if + + if (topic!=null) + topic.sendMailToParticipants(posters,ndays,request.getParameter("subj"), + request.getParameter("pb")); + else + conf.sendMailToParticipants(posters,ndays,request.getParameter("subj"), + request.getParameter("pb")); + + } // end try + catch (AccessError ae) + { // some sort of access error - display an error dialog + return new ErrorBox("Access Error",ae.getMessage(),on_error); + + } // end catch + catch (DataException de) + { // database error creating the conference + return new ErrorBox("Database Error","Database error sending E-mail: " + de.getMessage(), + on_error); + + } // end catch + + // all done - bounce back to the menu + throw new RedirectResult("confops?sig=" + comm.getCommunityID() + "&conf=" + conf.getConfID() + + "&cmd=Q"); + + } // end if ("send" pressed) + + // we don't know what button was pressed + logger.error("no known button click on ConfOperations.doPost, cmd=I"); + return new ErrorBox("Internal Error","Unknown command button pressed",on_error); + + } // end if ("I" command) + // unrecognized command! logger.error("invalid command to ConfOperations.doPost: " + cmd); return new ErrorBox("Internal Error","Invalid command to ConfOperations.doPost",on_error); diff --git a/src/com/silverwrist/venice/servlets/format/ConferenceEMail.java b/src/com/silverwrist/venice/servlets/format/ConferenceEMail.java new file mode 100644 index 0000000..ce7a264 --- /dev/null +++ b/src/com/silverwrist/venice/servlets/format/ConferenceEMail.java @@ -0,0 +1,152 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.servlets.format; + +import java.io.IOException; +import java.io.Writer; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.silverwrist.util.StringUtil; +import com.silverwrist.venice.core.*; +import com.silverwrist.venice.except.*; + +public class ConferenceEMail implements JSPRender +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + // Attribute name for request attribute + protected static final String ATTR_NAME = "com.silverwrist.venice.content.ConferenceEMail"; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private CommunityContext comm; // the community we're in + private ConferenceContext conf; // the conference being listed + private List topics; // list of topics in that conference + private String locator = null; // locator string + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public ConferenceEMail(CommunityContext comm, ConferenceContext conf) throws DataException, AccessError + { + this.comm = comm; + this.conf = conf; + this.topics = conf.getTopicList(ConferenceContext.DISPLAY_ALL,ConferenceContext.SORT_NAME); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * External static functions + *-------------------------------------------------------------------------------- + */ + + public static ConferenceEMail retrieve(ServletRequest request) + { + return (ConferenceEMail)(request.getAttribute(ATTR_NAME)); + + } // end retrieve + + /*-------------------------------------------------------------------------------- + * Implementations from interface VeniceContent + *-------------------------------------------------------------------------------- + */ + + public String getPageTitle(RenderData rdat) + { + return "Conference E-Mail: " + conf.getName(); + + } // end getPageTitle + + public String getPageQID() + { + return null; + + } // end getPageQID + + /*-------------------------------------------------------------------------------- + * Implementations from interface JSPRender + *-------------------------------------------------------------------------------- + */ + + public void store(ServletRequest request) + { + request.setAttribute(ATTR_NAME,this); + + } // end store + + public String getTargetJSPName() + { + return "conf_email.jsp"; + + } // end getTargetJSPName + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + public final int getCommunityID() + { + return comm.getCommunityID(); + + } // end getCommunityID + + public final int getConferenceID() + { + return conf.getConfID(); + + } // end getConferenceID + + public final String getConferenceName() + { + return conf.getName(); + + } // end getConferenceName + + public final String getLocator() + { + if (locator==null) + locator = "sig=" + comm.getCommunityID() + "&conf=" + conf.getConfID(); + return locator; + + } // end getLocator + + public final void writeTopicChoices(Writer out) throws IOException + { + out.write("\n"); + Iterator it = topics.iterator(); + while (it.hasNext()) + { // write out the entire topic list as a drop-down list + TopicContext topic = (TopicContext)(it.next()); + out.write("\n"); + + } // end while + + } // end writeTopicChoices + +} // end class ConferenceEMail diff --git a/web/format/conf_email.jsp b/web/format/conf_email.jsp new file mode 100644 index 0000000..1db20b1 --- /dev/null +++ b/web/format/conf_email.jsp @@ -0,0 +1,73 @@ +<%-- + The contents of this file are subject to the Mozilla Public License Version 1.1 + (the "License"); you may not use this file except in compliance with the License. + You may obtain a copy of the License at . + + Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + WARRANTY OF ANY KIND, either express or implied. See the License for the specific + language governing rights and limitations under the License. + + The Original Code is the Venice Web Communities System. + + The Initial Developer of the Original Code is Eric J. Bowersox , + for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + + Contributor(s): +--%> +<%@ page import = "java.util.*" %> +<%@ page import = "com.silverwrist.util.StringUtil" %> +<%@ page import = "com.silverwrist.venice.core.*" %> +<%@ page import = "com.silverwrist.venice.servlets.Variables" %> +<%@ page import = "com.silverwrist.venice.servlets.format.*" %> +<% + ConferenceEMail data = ConferenceEMail.retrieve(request); + Variables.failIfNull(data); + RenderData rdat = RenderConfig.createRenderData(application,request,response); +%> +<% if (rdat.useHTMLComments()) { %><% } %> +<% rdat.writeContentHeader(out,"Conference E-Mail:",data.getConferenceName()); %> + +
">
+ + + + + + + + + + + + + + + + + + + +
<%= rdat.getStdFontTag(ColorSelectors.CONTENT_FOREGROUND,2) %> + Send E-mail to all  + +  topic:  + +
 <%= rdat.getStdFontTag(ColorSelectors.CONTENT_FOREGROUND,2) %> + + Within the last day(s) +
+ <%= rdat.getStdFontTag(ColorSelectors.CONTENT_FOREGROUND,2) %>Subject: +
+ " NAME="send" + ALT="Send E-Mail" WIDTH=80 HEIGHT=24 BORDER=0>  + " NAME="cancel" + ALT="Cancel" WIDTH=80 HEIGHT=24 BORDER=0> +
+
\ No newline at end of file diff --git a/web/format/invitation.jsp b/web/format/invitation.jsp index c3f4559..ba1adc4 100644 --- a/web/format/invitation.jsp +++ b/web/format/invitation.jsp @@ -55,3 +55,4 @@ + diff --git a/web/format/manage_conf.jsp b/web/format/manage_conf.jsp index a73640b..a88609d 100644 --- a/web/format/manage_conf.jsp +++ b/web/format/manage_conf.jsp @@ -75,6 +75,8 @@ Conference Members

">Conference Activity Reports

+ ">Conference + E-Mail

">Delete Conference