implemented the rest of the functions on the "posts" page; fixed post links
so they work now; added the HTML Reference (originally from CW); added the post output filtering to turn the "pseudo-URIs" in the database into real URIs
							
								
								
									
										13
									
								
								TODO
									
									
									
									
									
								
							
							
						
						@ -25,19 +25,6 @@ Lots!
 | 
			
		||||
  statements in the case of joined queries (no need to SELECT table.column
 | 
			
		||||
  AS name).
 | 
			
		||||
 | 
			
		||||
- Functions still to do on conferencing "posts" page:
 | 
			
		||||
  Hide/Show Topic
 | 
			
		||||
  Next & Keep New (make it actually Keep New)
 | 
			
		||||
  Freeze/Unfreeze Topic
 | 
			
		||||
  Archive/Unarchive Topic
 | 
			
		||||
  Delete Topic
 | 
			
		||||
  Make number of "viewable" posts per page a config option
 | 
			
		||||
  Display the message locator (i.e. <Playground.56.123>) above each message
 | 
			
		||||
  Hide/Show Post
 | 
			
		||||
  Scribble Post
 | 
			
		||||
  Nuke Post
 | 
			
		||||
  Put the HTML Guide in (for all pages w/post boxes)
 | 
			
		||||
 | 
			
		||||
- Slippage during posting is still untested.
 | 
			
		||||
 | 
			
		||||
- Functions still to do on conferencing "topics" page:
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,7 @@ fucking
 | 
			
		||||
hairstyle
 | 
			
		||||
hairstyles
 | 
			
		||||
hasn't
 | 
			
		||||
haven't
 | 
			
		||||
he'd
 | 
			
		||||
html
 | 
			
		||||
i'd
 | 
			
		||||
 | 
			
		||||
@ -43,6 +43,9 @@
 | 
			
		||||
    <!-- Base URL for all images loaded by the server code.  MUST include the trailing slash. -->
 | 
			
		||||
    <image>http://delenn:8080/venice/images/</image>
 | 
			
		||||
 | 
			
		||||
    <!-- Base URL for all static pages linked to by the engine.  MUST include the trailing slash. -->
 | 
			
		||||
    <static>http://delenn:8080/venice/static/</static>
 | 
			
		||||
 | 
			
		||||
    <!-- The fully-qualified URL to the site logo.  The image should be 140x80 pixels. -->
 | 
			
		||||
    <site-logo>http://delenn:8080/venice/images/powered-by-venice.gif</site-logo>
 | 
			
		||||
  </paths>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								etc/web.xml
									
									
									
									
									
								
							
							
						
						@ -11,7 +11,7 @@
 | 
			
		||||
    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 Community System.
 | 
			
		||||
    The Original Code is the Venice Web Communities System.
 | 
			
		||||
 | 
			
		||||
    The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
    for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
@ -21,9 +21,9 @@
 | 
			
		||||
-->
 | 
			
		||||
<web-app>
 | 
			
		||||
 | 
			
		||||
  <display-name>Venice Web Community System</display-name>
 | 
			
		||||
  <display-name>Venice Web Communities System</display-name>
 | 
			
		||||
  <description>
 | 
			
		||||
    The Venice Web conferencing system provides an online conferencing
 | 
			
		||||
    The Venice Web Communities System provides an online conferencing
 | 
			
		||||
    environment, including discussions, online services, and other
 | 
			
		||||
    things.  Written by Eric J. Bowersox (erbo@silcom.com).
 | 
			
		||||
  </description>
 | 
			
		||||
@ -158,6 +158,30 @@
 | 
			
		||||
    <servlet-class>com.silverwrist.venice.servlets.Attachment</servlet-class>
 | 
			
		||||
  </servlet>
 | 
			
		||||
 | 
			
		||||
  <servlet>
 | 
			
		||||
    <servlet-name>topicoperations</servlet-name>
 | 
			
		||||
    <description>
 | 
			
		||||
      General topic operations.
 | 
			
		||||
    </description>
 | 
			
		||||
    <servlet-class>com.silverwrist.venice.servlets.TopicOperations</servlet-class>
 | 
			
		||||
  </servlet>
 | 
			
		||||
 | 
			
		||||
  <servlet>
 | 
			
		||||
    <servlet-name>postoperations</servlet-name>
 | 
			
		||||
    <description>
 | 
			
		||||
      General post operations.
 | 
			
		||||
    </description>
 | 
			
		||||
    <servlet-class>com.silverwrist.venice.servlets.PostOperations</servlet-class>
 | 
			
		||||
  </servlet>
 | 
			
		||||
 | 
			
		||||
  <servlet>
 | 
			
		||||
    <servlet-name>postshortcut</servlet-name>
 | 
			
		||||
    <description>
 | 
			
		||||
      Processes post links and redirects to the appropriate page.
 | 
			
		||||
    </description>
 | 
			
		||||
    <servlet-class>com.silverwrist.venice.servlets.PostShortcut</servlet-class>
 | 
			
		||||
  </servlet>
 | 
			
		||||
 | 
			
		||||
  <!-- the following are test servlets, they should go away -->
 | 
			
		||||
 | 
			
		||||
  <servlet>
 | 
			
		||||
@ -226,6 +250,21 @@
 | 
			
		||||
    <url-pattern>/attachment</url-pattern>
 | 
			
		||||
  </servlet-mapping>
 | 
			
		||||
 | 
			
		||||
  <servlet-mapping>
 | 
			
		||||
    <servlet-name>topicoperations</servlet-name>
 | 
			
		||||
    <url-pattern>/topicops</url-pattern>
 | 
			
		||||
  </servlet-mapping>
 | 
			
		||||
 | 
			
		||||
  <servlet-mapping>
 | 
			
		||||
    <servlet-name>postoperations</servlet-name>
 | 
			
		||||
    <url-pattern>/postops</url-pattern>
 | 
			
		||||
  </servlet-mapping>
 | 
			
		||||
 | 
			
		||||
  <servlet-mapping>
 | 
			
		||||
    <servlet-name>postshortcut</servlet-name>
 | 
			
		||||
    <url-pattern>/go/*</url-pattern>
 | 
			
		||||
  </servlet-mapping>
 | 
			
		||||
 | 
			
		||||
  <!-- the following are test servlets, they should go away -->
 | 
			
		||||
  <servlet-mapping>
 | 
			
		||||
    <servlet-name>testformdata</servlet-name>
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,14 @@ USE venice;
 | 
			
		||||
# Table Creation
 | 
			
		||||
##############################################################################
 | 
			
		||||
 | 
			
		||||
# The global parameters table.  This is used for stuff that a Venice admin would be
 | 
			
		||||
# likely to edit "on the fly."  Stuff that can only be updated with a shutdown should go
 | 
			
		||||
# in the XML config file.  This table has ONLY ONE ROW!
 | 
			
		||||
CREATE TABLE globals (
 | 
			
		||||
    posts_per_page INT NOT NULL,
 | 
			
		||||
    old_posts_at_top INT NOT NULL
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
# The audit records table.  Most "major" events add a record to this table.
 | 
			
		||||
CREATE TABLE audit (
 | 
			
		||||
    record BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
 | 
			
		||||
@ -1282,6 +1290,10 @@ INSERT INTO refsigftr (ftr_code, is_default, is_locked, is_hidden, require_read,
 | 
			
		||||
# Database Initialization
 | 
			
		||||
##############################################################################
 | 
			
		||||
 | 
			
		||||
# Initialize the system globals table.
 | 
			
		||||
INSERT INTO globals (posts_per_page, old_posts_at_top)
 | 
			
		||||
    VALUES (20, 2);
 | 
			
		||||
 | 
			
		||||
# Add the 'Anonymous Honyak' user to the users table.
 | 
			
		||||
# (Do 'SELECT * FROM users WHERE is_anon = 1' to retrieve the AC user details.)
 | 
			
		||||
# (UID = 1, CONTACTID = 1)
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ package com.silverwrist.venice.core;
 | 
			
		||||
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import com.silverwrist.venice.htmlcheck.HTMLChecker;
 | 
			
		||||
 | 
			
		||||
public interface ConferenceContext
 | 
			
		||||
{
 | 
			
		||||
@ -114,4 +115,6 @@ public interface ConferenceContext
 | 
			
		||||
 | 
			
		||||
  public abstract TopicMessageContext getMessageByPostID(long postid) throws DataException, AccessError;
 | 
			
		||||
 | 
			
		||||
  public abstract HTMLChecker getNewTopicPreviewChecker();
 | 
			
		||||
 | 
			
		||||
} // end interface ConferenceContext
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@
 | 
			
		||||
 * 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 Community System.
 | 
			
		||||
 * The Original Code is the Venice Web Communities System.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
@ -72,4 +72,30 @@ public class IDUtils
 | 
			
		||||
 | 
			
		||||
  } // end isValidConfirmationNumber
 | 
			
		||||
 | 
			
		||||
  public static boolean isValidVeniceIDChar(char c)
 | 
			
		||||
  {
 | 
			
		||||
    if ((c>='A') && (c<='Z'))
 | 
			
		||||
      return true;  // upper-case letters are OK
 | 
			
		||||
    if ((c>='a') && (c<='z'))
 | 
			
		||||
      return true;  // lower-case letters are OK
 | 
			
		||||
    if ((c>='0') && (c<='9'))
 | 
			
		||||
      return true;  // digits are OK
 | 
			
		||||
    return (EXTRA_VALID.indexOf(c)>=0);
 | 
			
		||||
 | 
			
		||||
  } // end isValidVeniceIDChar
 | 
			
		||||
 | 
			
		||||
  public static boolean isValidPostLinkChar(char c)
 | 
			
		||||
  {
 | 
			
		||||
    if ((c>='A') && (c<='Z'))
 | 
			
		||||
      return true;  // upper-case letters are OK
 | 
			
		||||
    if ((c>='a') && (c<='z'))
 | 
			
		||||
      return true;  // lower-case letters are OK
 | 
			
		||||
    if ((c>='0') && (c<='9'))
 | 
			
		||||
      return true;  // digits are OK
 | 
			
		||||
    if (EXTRA_VALID.indexOf(c)>=0)
 | 
			
		||||
      return true;  // other characters from Venice IDs are OK
 | 
			
		||||
    return ((c=='.') || (c=='!'));  // also dots and bangs
 | 
			
		||||
 | 
			
		||||
  } // end isValidPostLinkChar
 | 
			
		||||
 | 
			
		||||
} // end class IDUtils
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ package com.silverwrist.venice.core;
 | 
			
		||||
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import com.silverwrist.venice.htmlcheck.HTMLChecker;
 | 
			
		||||
 | 
			
		||||
public interface TopicContext
 | 
			
		||||
{
 | 
			
		||||
@ -71,4 +72,11 @@ public interface TopicContext
 | 
			
		||||
  public abstract TopicMessageContext postNewMessage(long parent, String pseud, String text)
 | 
			
		||||
      throws DataException, AccessError;
 | 
			
		||||
 | 
			
		||||
  public abstract HTMLChecker getPreviewChecker();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean canDelete();
 | 
			
		||||
 | 
			
		||||
  public abstract void delete() throws DataException, AccessError;
 | 
			
		||||
 | 
			
		||||
} // end interface TopicContext
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -61,8 +61,10 @@ public interface VeniceEngine extends SearchMode
 | 
			
		||||
 | 
			
		||||
  public abstract boolean confAliasExists(String alias);
 | 
			
		||||
 | 
			
		||||
  public abstract HTMLChecker getPreviewChecker();
 | 
			
		||||
 | 
			
		||||
  public abstract HTMLChecker getEscapingChecker();
 | 
			
		||||
 | 
			
		||||
  public abstract int getNumPostsPerPage();
 | 
			
		||||
 | 
			
		||||
  public abstract int getNumOldPostsBeforeNew();
 | 
			
		||||
 | 
			
		||||
} // end interface VeniceEngine
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										112
									
								
								src/com/silverwrist/venice/core/impl/BackgroundTopicPurge.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,112 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 * 
 | 
			
		||||
 * 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 <erbo@silcom.com>,
 | 
			
		||||
 * 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.sql.*;
 | 
			
		||||
import org.apache.log4j.*;
 | 
			
		||||
import com.silverwrist.venice.db.*;
 | 
			
		||||
 | 
			
		||||
class BackgroundTopicPurge implements Runnable
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static data members
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private static Category logger = Category.getInstance(BackgroundTopicPurge.class.getName());
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Attributes
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private DataPool datapool;
 | 
			
		||||
  private int topicid;
 | 
			
		||||
  private int num_posts;
 | 
			
		||||
  private long max_postid;
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Constructor
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  BackgroundTopicPurge(DataPool datapool, int topicid, int num_posts, long max_postid)
 | 
			
		||||
  {
 | 
			
		||||
    this.datapool = datapool;
 | 
			
		||||
    this.topicid = topicid;
 | 
			
		||||
    this.num_posts = num_posts;
 | 
			
		||||
    this.max_postid = max_postid;
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface Runnable
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public void run()
 | 
			
		||||
  {
 | 
			
		||||
    if (logger.isDebugEnabled())
 | 
			
		||||
      logger.debug("BackgroundTopicPurge running on topic #" + String.valueOf(topicid));
 | 
			
		||||
 | 
			
		||||
    long[] postids = new long[num_posts];  // stores the post IDs
 | 
			
		||||
    Connection conn = null;  // pooled database connection
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // get a database connection from the pool
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
 | 
			
		||||
      // look up all the post IDs that are present for this topic
 | 
			
		||||
      StringBuffer sql = new StringBuffer("SELECT postid FROM posts WHERE topicid = ");
 | 
			
		||||
      sql.append(topicid).append(" AND postid <= ").append(max_postid).append(" ORDER BY postid;");
 | 
			
		||||
      ResultSet rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
      int posts = 0;
 | 
			
		||||
      while (rs.next())
 | 
			
		||||
	postids[posts++] = rs.getLong(1);
 | 
			
		||||
 | 
			
		||||
      for (int i=0; i<posts; i++)
 | 
			
		||||
      { // remove all references to the posts in question
 | 
			
		||||
	stmt.executeUpdate("DELETE FROM posts WHERE postid = " + String.valueOf(postids[i]) + ";");
 | 
			
		||||
	stmt.executeUpdate("DELETE FROM postdata WHERE postid = " + String.valueOf(postids[i]) + ";");
 | 
			
		||||
	stmt.executeUpdate("DELETE FROM postattach WHERE postid = " + String.valueOf(postids[i]) + ";");
 | 
			
		||||
	stmt.executeUpdate("DELETE FROM postdogear WHERE postid = " + String.valueOf(postids[i]) + ";");
 | 
			
		||||
 | 
			
		||||
      } // end for
 | 
			
		||||
 | 
			
		||||
      // all done, Bunky!
 | 
			
		||||
      if (logger.isDebugEnabled())
 | 
			
		||||
	logger.debug("BackgroundTopicPurge complete for topic #" + String.valueOf(topicid));
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // on an error, just die
 | 
			
		||||
      logger.error("BackgroundTopicPurge FATAL EXCEPTION purging #" + String.valueOf(topicid) + ": "
 | 
			
		||||
		   + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    finally
 | 
			
		||||
    { // make sure we release the connection before we go
 | 
			
		||||
      if (conn!=null)
 | 
			
		||||
	datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
  } // end run
 | 
			
		||||
 | 
			
		||||
} // end class BackgroundTopicPurge
 | 
			
		||||
@ -20,6 +20,7 @@ package com.silverwrist.venice.core.impl;
 | 
			
		||||
import java.sql.Connection;
 | 
			
		||||
import java.sql.SQLException;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import com.silverwrist.venice.db.PostLinkDecoderContext;
 | 
			
		||||
import com.silverwrist.venice.core.DataException;
 | 
			
		||||
 | 
			
		||||
public interface ConferenceBackend extends SIGBackend
 | 
			
		||||
@ -44,4 +45,6 @@ public interface ConferenceBackend extends SIGBackend
 | 
			
		||||
 | 
			
		||||
  public abstract void touchUpdate(Connection conn, java.util.Date date) throws DataException;
 | 
			
		||||
 | 
			
		||||
  public abstract PostLinkDecoderContext createDecoderContext(short topicid);
 | 
			
		||||
 | 
			
		||||
} // end interface ConferenceBackend
 | 
			
		||||
 | 
			
		||||
@ -39,23 +39,24 @@ class ConferenceCoreData implements ConferenceData
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private int refcount = 1;             // object reference count
 | 
			
		||||
  private EngineBackend engine;         // pointer to engine back end
 | 
			
		||||
  private DataPool datapool;            // pointer to data pool
 | 
			
		||||
  private int confid;                   // ID of this conference
 | 
			
		||||
  private java.util.Date create_date;   // creation date of this conference
 | 
			
		||||
  private java.util.Date last_update;   // last update date of conference
 | 
			
		||||
  private int read_level;               // access level required to read conference contents
 | 
			
		||||
  private int post_level;               // access level required to post messages
 | 
			
		||||
  private int create_level;             // access level required to create new topics
 | 
			
		||||
  private int hide_level;               // access level required to hide posts/archive topics
 | 
			
		||||
  private int nuke_level;               // access level required to delete topics/scribble/nuke posts
 | 
			
		||||
  private int change_level;             // access level required to modify conference profile
 | 
			
		||||
  private int delete_level;             // access level required to delete conference
 | 
			
		||||
  private short top_topic;              // the highest topic number in the conference
 | 
			
		||||
  private String name;                  // the name of the conference
 | 
			
		||||
  private String description;           // the conference's description
 | 
			
		||||
  private String cached_alias = null;   // the cached alias (for getAnAlias)
 | 
			
		||||
  private int refcount = 1;                // object reference count
 | 
			
		||||
  private EngineBackend engine;            // pointer to engine back end
 | 
			
		||||
  private DataPool datapool;               // pointer to data pool
 | 
			
		||||
  private int confid;                      // ID of this conference
 | 
			
		||||
  private java.util.Date create_date;      // creation date of this conference
 | 
			
		||||
  private java.util.Date last_update;      // last update date of conference
 | 
			
		||||
  private int read_level;                  // access level required to read conference contents
 | 
			
		||||
  private int post_level;                  // access level required to post messages
 | 
			
		||||
  private int create_level;                // access level required to create new topics
 | 
			
		||||
  private int hide_level;                  // access level required to hide posts/archive topics
 | 
			
		||||
  private int nuke_level;                  // access level required to delete topics/scribble/nuke posts
 | 
			
		||||
  private int change_level;                // access level required to modify conference profile
 | 
			
		||||
  private int delete_level;                // access level required to delete conference
 | 
			
		||||
  private short top_topic;                 // the highest topic number in the conference
 | 
			
		||||
  private String name;                     // the name of the conference
 | 
			
		||||
  private String description;              // the conference's description
 | 
			
		||||
  private String cached_alias = null;      // the cached alias (for getAnAlias)
 | 
			
		||||
  private boolean creating_topic = false;  // is somebody creating a topic?
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Constructors
 | 
			
		||||
@ -817,8 +818,8 @@ class ConferenceCoreData implements ConferenceData
 | 
			
		||||
 | 
			
		||||
  } // end getAnAlias
 | 
			
		||||
 | 
			
		||||
  public ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud, String body,
 | 
			
		||||
					int body_lines) throws DataException
 | 
			
		||||
  public synchronized ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud,
 | 
			
		||||
						     String body, int body_lines) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    Connection conn = null;    // database connection
 | 
			
		||||
    AuditRecord ar = null;     // audit record
 | 
			
		||||
@ -963,6 +964,40 @@ class ConferenceCoreData implements ConferenceData
 | 
			
		||||
 | 
			
		||||
  } // end touchUpdate
 | 
			
		||||
 | 
			
		||||
  public synchronized short enterCreateTopic()
 | 
			
		||||
  {
 | 
			
		||||
    while (creating_topic)
 | 
			
		||||
    { // we're ready to create a topic
 | 
			
		||||
      try
 | 
			
		||||
      { // wait for another thread to relinquish the topic create mechanism
 | 
			
		||||
	wait();
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (InterruptedException e)
 | 
			
		||||
      { // do nothing
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
    } // end while
 | 
			
		||||
 | 
			
		||||
    creating_topic = true;
 | 
			
		||||
    // new topic number, needed to properly parse post links in new topic's zero post
 | 
			
		||||
    return (short)(top_topic + 1);
 | 
			
		||||
 | 
			
		||||
  } // end enterCreateTopic
 | 
			
		||||
 | 
			
		||||
  public synchronized void exitCreateTopic()
 | 
			
		||||
  {
 | 
			
		||||
    creating_topic = false;
 | 
			
		||||
    notify();  // wake somebody up if they were going to create a topic
 | 
			
		||||
 | 
			
		||||
  } // end exitCreateTopic
 | 
			
		||||
 | 
			
		||||
  public short getTopTopic()
 | 
			
		||||
  {
 | 
			
		||||
    return top_topic;
 | 
			
		||||
 | 
			
		||||
  } // end getTopTopic
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * External static operations (usable only from within package)
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@ -86,4 +86,10 @@ public interface ConferenceData extends ReferencedData
 | 
			
		||||
 | 
			
		||||
  public abstract void touchUpdate(Connection conn, Date date) throws DataException;
 | 
			
		||||
 | 
			
		||||
  public abstract short enterCreateTopic();
 | 
			
		||||
 | 
			
		||||
  public abstract void exitCreateTopic();
 | 
			
		||||
 | 
			
		||||
  public abstract short getTopTopic();
 | 
			
		||||
 | 
			
		||||
} // end interface ConferenceData
 | 
			
		||||
 | 
			
		||||
@ -89,8 +89,8 @@ public interface ConferenceSIGContext extends ReferencedData
 | 
			
		||||
 | 
			
		||||
  public abstract String getAnAlias() throws DataException;
 | 
			
		||||
 | 
			
		||||
  public abstract ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud, String body,
 | 
			
		||||
						 int body_lines) throws DataException;
 | 
			
		||||
  public abstract ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud, String body)
 | 
			
		||||
      throws DataException;
 | 
			
		||||
 | 
			
		||||
  public abstract boolean canScribblePosts(int level);
 | 
			
		||||
 | 
			
		||||
@ -98,4 +98,6 @@ public interface ConferenceSIGContext extends ReferencedData
 | 
			
		||||
 | 
			
		||||
  public abstract void touchUpdate(Connection conn, Date date) throws DataException;
 | 
			
		||||
 | 
			
		||||
  public abstract short getTopTopic();
 | 
			
		||||
 | 
			
		||||
} // end interface ConferenceSIGContext
 | 
			
		||||
 | 
			
		||||
@ -21,6 +21,7 @@ import java.sql.*;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import org.apache.log4j.*;
 | 
			
		||||
import com.silverwrist.venice.db.*;
 | 
			
		||||
import com.silverwrist.venice.htmlcheck.*;
 | 
			
		||||
import com.silverwrist.venice.security.AuditRecord;
 | 
			
		||||
import com.silverwrist.venice.core.*;
 | 
			
		||||
 | 
			
		||||
@ -611,10 +612,48 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
 | 
			
		||||
 | 
			
		||||
  } // end getAnAlias
 | 
			
		||||
 | 
			
		||||
  public ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud, String body,
 | 
			
		||||
					int body_lines) throws DataException
 | 
			
		||||
  public ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud, String body)
 | 
			
		||||
      throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    return getConferenceData().createNewTopic(sig,title,pseud,body,body_lines);
 | 
			
		||||
    ConferenceData d = getConferenceData();
 | 
			
		||||
    String conf_alias = d.getAnAlias();
 | 
			
		||||
    short new_topic = d.enterCreateTopic();
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // preprocess the body argument through the HTML checker
 | 
			
		||||
      HTMLChecker text_ch = engine.createCheckerObject(engine.HTMLC_POST_BODY);
 | 
			
		||||
      text_ch.setContextValue("PostLinkDecoderContext",
 | 
			
		||||
			      new PostLinkDecoderContext(sig.realSIGAlias(),conf_alias,new_topic));
 | 
			
		||||
 | 
			
		||||
      try
 | 
			
		||||
      { // run through the HTML checker
 | 
			
		||||
	text_ch.append(body);
 | 
			
		||||
	text_ch.finish();
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (AlreadyFinishedException e)
 | 
			
		||||
      { // this isn't right...
 | 
			
		||||
	throw new InternalStateError("HTMLChecker erroneously throwing AlreadyFinishedException",e);
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
      try
 | 
			
		||||
      { // call down to create the new topic!
 | 
			
		||||
	return d.createNewTopic(sig,title,pseud,text_ch.getValue(),text_ch.getLines());
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (NotYetFinishedException e)
 | 
			
		||||
      { // this isn't right either!
 | 
			
		||||
	throw new InternalStateError("HTMLChecker erroneously throwing NotYetFinishedException",e);
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    finally
 | 
			
		||||
    { // make sure we relinquish the topic creation no matter what happens
 | 
			
		||||
      d.exitCreateTopic();
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
  } // end createNewTopic
 | 
			
		||||
 | 
			
		||||
@ -648,4 +687,14 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
 | 
			
		||||
 | 
			
		||||
  } // end touchUpdate
 | 
			
		||||
 | 
			
		||||
  public short getTopTopic()
 | 
			
		||||
  {
 | 
			
		||||
    ConferenceData c = getConferenceDataNE();
 | 
			
		||||
    if (c==null)
 | 
			
		||||
      return -1;
 | 
			
		||||
    else
 | 
			
		||||
      return c.getTopTopic();
 | 
			
		||||
 | 
			
		||||
  } // end getTopTopic
 | 
			
		||||
 | 
			
		||||
} // end class ConferenceSIGContextImpl
 | 
			
		||||
 | 
			
		||||
@ -821,19 +821,16 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    // preprocess the three arguments through HTML checkers
 | 
			
		||||
    // preprocess the pseud and title arguments through HTML checkers
 | 
			
		||||
    HTMLChecker title_ch = engine.createCheckerObject(engine.HTMLC_POST_PSEUD);
 | 
			
		||||
    HTMLChecker zp_pseud_ch = engine.createCheckerObject(engine.HTMLC_POST_PSEUD);
 | 
			
		||||
    HTMLChecker zp_text_ch = engine.createCheckerObject(engine.HTMLC_POST_BODY);
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // run all three arguments through the HTML checker
 | 
			
		||||
    { // run arguments through the HTML checker
 | 
			
		||||
      title_ch.append(title);
 | 
			
		||||
      title_ch.finish();
 | 
			
		||||
      zp_pseud_ch.append(zp_pseud);
 | 
			
		||||
      zp_pseud_ch.finish();
 | 
			
		||||
      zp_text_ch.append(zp_text);
 | 
			
		||||
      zp_text_ch.finish();
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (AlreadyFinishedException e)
 | 
			
		||||
@ -848,8 +845,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
    try
 | 
			
		||||
    { // call down to create the new topic!
 | 
			
		||||
      real_title = title_ch.getValue();
 | 
			
		||||
      new_topic_inf = getConferenceData().createNewTopic(sig,real_title,zp_pseud_ch.getValue(),
 | 
			
		||||
							 zp_text_ch.getValue(),zp_text_ch.getLines());
 | 
			
		||||
      new_topic_inf = getConferenceData().createNewTopic(sig,real_title,zp_pseud_ch.getValue(),zp_text);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NotYetFinishedException e)
 | 
			
		||||
@ -898,6 +894,20 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
 | 
			
		||||
  } // end getMessageByPostID
 | 
			
		||||
 | 
			
		||||
  public HTMLChecker getNewTopicPreviewChecker()
 | 
			
		||||
  {
 | 
			
		||||
    ConferenceSIGContext c = getConferenceDataNE();
 | 
			
		||||
    short new_topic;
 | 
			
		||||
    if (c==null)
 | 
			
		||||
      new_topic = 0;
 | 
			
		||||
    else
 | 
			
		||||
      new_topic = (short)(c.getTopTopic() + 1);
 | 
			
		||||
    HTMLChecker rc = engine.createCheckerObject(engine.HTMLC_PREVIEW_BODY);
 | 
			
		||||
    rc.setContextValue("PostLinkDecoderContext",createDecoderContext(new_topic));
 | 
			
		||||
    return rc;
 | 
			
		||||
    
 | 
			
		||||
  } // end getNewTopicPreviewChecker
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface UserBackend
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -1097,6 +1107,12 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
 | 
			
		||||
  } // end getConferenceData
 | 
			
		||||
 | 
			
		||||
  public PostLinkDecoderContext createDecoderContext(short topicid)
 | 
			
		||||
  {
 | 
			
		||||
    return new PostLinkDecoderContext(sig.realSIGAlias(),realConfAlias(),topicid);
 | 
			
		||||
 | 
			
		||||
  } // end createDecoderContext
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static functions usable only from within the package
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,9 @@ public interface EngineBackend
 | 
			
		||||
  public static final int HTMLC_PREVIEW_BODY = 2;
 | 
			
		||||
  public static final int HTMLC_ESCAPE_BODY_PSEUD = 3;
 | 
			
		||||
 | 
			
		||||
  public static final int IP_POSTSPERPAGE = 0;
 | 
			
		||||
  public static final int IP_POSTSATTOP = 1;
 | 
			
		||||
 | 
			
		||||
  public abstract SimpleEmailer createEmailer();
 | 
			
		||||
 | 
			
		||||
  public abstract String getStockMessage(String key);
 | 
			
		||||
@ -66,4 +69,8 @@ public interface EngineBackend
 | 
			
		||||
 | 
			
		||||
  public abstract HTMLChecker createCheckerObject(int type);
 | 
			
		||||
 | 
			
		||||
  public abstract int getParamInt(int selector);
 | 
			
		||||
 | 
			
		||||
  public abstract void forceParamReload() throws DataException;
 | 
			
		||||
 | 
			
		||||
} // end interface EngineBackend
 | 
			
		||||
 | 
			
		||||
@ -134,9 +134,10 @@ class TopicMessageUserContextImpl implements TopicMessageContext
 | 
			
		||||
  private void refresh(Connection conn) throws SQLException
 | 
			
		||||
  {
 | 
			
		||||
    Statement stmt = conn.createStatement();
 | 
			
		||||
    StringBuffer sql = new StringBuffer("SELECT p.hidden, p.scribble_uid, p.scribble_date, p.pseud, "
 | 
			
		||||
					+ "a.datalen, a.filename, a.mimetype FROM posts p LEFT JOIN "
 | 
			
		||||
					+ "postattach a ON p.postid = a.postid WHERE p.postid = ");
 | 
			
		||||
    StringBuffer sql = new StringBuffer("SELECT posts.hidden, posts.scribble_uid, posts.scribble_date, "
 | 
			
		||||
					+ "posts.pseud, postattach.datalen, postattach.filename, "
 | 
			
		||||
					+ "postattach.mimetype FROM posts LEFT JOIN postattach ON "
 | 
			
		||||
					+ "posts.postid = postattach.postid WHERE posts.postid = ");
 | 
			
		||||
    sql.append(postid).append(';');
 | 
			
		||||
    ResultSet rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
    if (rs.next())
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@
 | 
			
		||||
 * 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 Community System.
 | 
			
		||||
 * The Original Code is the Venice Web Communities System.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
@ -617,6 +617,7 @@ class TopicUserContextImpl implements TopicContext
 | 
			
		||||
    // preprocess the two arguments through HTML checkers
 | 
			
		||||
    HTMLChecker pseud_ch = engine.createCheckerObject(engine.HTMLC_POST_PSEUD);
 | 
			
		||||
    HTMLChecker text_ch = engine.createCheckerObject(engine.HTMLC_POST_BODY);
 | 
			
		||||
    text_ch.setContextValue("PostLinkDecoderContext",conf.createDecoderContext(topicnum));
 | 
			
		||||
    try
 | 
			
		||||
    { // run both arguments through the HTML checker
 | 
			
		||||
      pseud_ch.append(pseud);
 | 
			
		||||
@ -773,6 +774,117 @@ class TopicUserContextImpl implements TopicContext
 | 
			
		||||
 | 
			
		||||
  } // end postMessage
 | 
			
		||||
 | 
			
		||||
  public HTMLChecker getPreviewChecker()
 | 
			
		||||
  {
 | 
			
		||||
    HTMLChecker rc = engine.createCheckerObject(engine.HTMLC_PREVIEW_BODY);
 | 
			
		||||
    rc.setContextValue("PostLinkDecoderContext",conf.createDecoderContext(topicnum));
 | 
			
		||||
    return rc;
 | 
			
		||||
    
 | 
			
		||||
  } // end getPreviewChecker
 | 
			
		||||
 | 
			
		||||
  public boolean canDelete()
 | 
			
		||||
  {
 | 
			
		||||
    return conf.userCanNuke();
 | 
			
		||||
 | 
			
		||||
  } // end canDelete
 | 
			
		||||
 | 
			
		||||
  public void delete() throws DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    if (!(conf.userCanNuke()))
 | 
			
		||||
    { // we can't delete the topic!
 | 
			
		||||
      logger.error("trying to delete w/o permission!");
 | 
			
		||||
      throw new AccessError("You do not have permission to delete this topic.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    if (deleted)
 | 
			
		||||
      return;  // an exercise in futility...
 | 
			
		||||
 | 
			
		||||
    Connection conn = null;
 | 
			
		||||
    AuditRecord ar = null;
 | 
			
		||||
    int post_count;
 | 
			
		||||
    long post_max;
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // get a database connection
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
 | 
			
		||||
      // lock some tables while we do the critical parts of the delete
 | 
			
		||||
      stmt.executeUpdate("LOCK TABLES confs WRITE, topics WRITE, topicsettings WRITE, posts READ;");
 | 
			
		||||
      try
 | 
			
		||||
      { // first delete the topic record itself
 | 
			
		||||
	StringBuffer sql = new StringBuffer("DELETE FROM topics WHERE topicid = ");
 | 
			
		||||
	sql.append(topicid).append(';');
 | 
			
		||||
	stmt.executeUpdate(sql.toString());
 | 
			
		||||
 | 
			
		||||
	// now delete all topicsettings records
 | 
			
		||||
	sql.setLength(0);
 | 
			
		||||
	sql.append("DELETE FROM topicsettings WHERE topicid = ").append(topicid).append(';');
 | 
			
		||||
	stmt.executeUpdate(sql.toString());
 | 
			
		||||
 | 
			
		||||
	// and indicate that we updated the conference
 | 
			
		||||
	conf.touchUpdate(conn,new java.util.Date());
 | 
			
		||||
 | 
			
		||||
	// determine the number of posts in this topic, and the maximum post ID
 | 
			
		||||
	sql.setLength(0);
 | 
			
		||||
	sql.append("SELECT COUNT(*), MAX(postid) FROM posts WHERE topicid = ").append(topicid).append(';');
 | 
			
		||||
	ResultSet rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
	if (!(rs.next()))
 | 
			
		||||
	  throw new InternalStateError("TopicContext.delete screwup on post SELECT");
 | 
			
		||||
	post_count = rs.getInt(1);
 | 
			
		||||
	post_max = rs.getLong(2);
 | 
			
		||||
	
 | 
			
		||||
	// and record that we're now deleted
 | 
			
		||||
	makeDeleted();
 | 
			
		||||
    
 | 
			
		||||
      } // end try
 | 
			
		||||
      finally
 | 
			
		||||
      { // make sure and unlock before we're done
 | 
			
		||||
	Statement ulk_stmt = conn.createStatement();
 | 
			
		||||
	ulk_stmt.executeUpdate("UNLOCK TABLES;");
 | 
			
		||||
 | 
			
		||||
      } // end finally
 | 
			
		||||
 | 
			
		||||
      // record what we did in an audit record
 | 
			
		||||
      ar = new AuditRecord(AuditRecord.DELETE_TOPIC,conf.realUID(),conf.userRemoteAddress(),
 | 
			
		||||
			   conf.realSIGID(),"conf=" + String.valueOf(conf.realConfID()) + ",topic="
 | 
			
		||||
			   + String.valueOf(topicid));
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // turn SQLException into data exception
 | 
			
		||||
      logger.error("DB error deleting topic: " + e.getMessage(),e);
 | 
			
		||||
      throw new DataException("unable to delete topic: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    finally
 | 
			
		||||
    { // make sure we release the connection before we go
 | 
			
		||||
      try
 | 
			
		||||
      { // save off the audit record before we go, though
 | 
			
		||||
	if ((ar!=null) && (conn!=null))
 | 
			
		||||
	  ar.store(conn);
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (SQLException e)
 | 
			
		||||
      { // we couldn't store the audit record!
 | 
			
		||||
	logger.error("DB error saving audit record: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
      if (conn!=null)
 | 
			
		||||
	datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
    // Delete the rest of the gunk in the background; spin off another thread to handle it.
 | 
			
		||||
    BackgroundTopicPurge purger = new BackgroundTopicPurge(datapool,topicid,post_count,post_max);
 | 
			
		||||
    Thread thrd = new Thread(purger);
 | 
			
		||||
    thrd.setPriority(Thread.NORM_PRIORITY-1);
 | 
			
		||||
    thrd.start();
 | 
			
		||||
 | 
			
		||||
  } // end delete
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * External operations usable only from within the package
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@ -213,6 +213,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
 | 
			
		||||
  private Hashtable feature_syms = new Hashtable();   // hashtable mapping symbols to features
 | 
			
		||||
  private Hashtable conf_objects = new Hashtable();   // holder for ConferenceCoreData objects
 | 
			
		||||
  private HTMLCheckerConfig[] html_configs;           // holder for HTML checker configurations
 | 
			
		||||
  private int[] gp_ints;                              // global integer parameters
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Constructor
 | 
			
		||||
@ -239,6 +240,19 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
 | 
			
		||||
 | 
			
		||||
  } // end checkInitialized
 | 
			
		||||
 | 
			
		||||
  private void loadDefaults(Statement stmt) throws SQLException, DataException
 | 
			
		||||
  {
 | 
			
		||||
    final String query = "SELECT posts_per_page, old_posts_at_top FROM globals;";
 | 
			
		||||
    ResultSet rs = stmt.executeQuery(query);
 | 
			
		||||
    if (!(rs.next()))
 | 
			
		||||
      throw new DataException("Globals table does not appear to be loaded!");
 | 
			
		||||
 | 
			
		||||
    // stash the globals from the database
 | 
			
		||||
    gp_ints[IP_POSTSPERPAGE] = rs.getInt(1);
 | 
			
		||||
    gp_ints[IP_POSTSATTOP] = rs.getInt(2);
 | 
			
		||||
    
 | 
			
		||||
  } // end loadDefaults
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface VeniceEngine
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -378,6 +392,9 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
    // Allocate the global parameter arrays.
 | 
			
		||||
    gp_ints = new int[2];
 | 
			
		||||
 | 
			
		||||
    // initialize anything that requires us to pull from the database
 | 
			
		||||
    Connection conn = null;
 | 
			
		||||
    try
 | 
			
		||||
@ -404,6 +421,9 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
 | 
			
		||||
      if (logger.isDebugEnabled())
 | 
			
		||||
	logger.debug(String.valueOf(max_value) + " features loaded from database");
 | 
			
		||||
 | 
			
		||||
      // load the global defaults
 | 
			
		||||
      loadDefaults(stmt);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // convert exceptions to DataException
 | 
			
		||||
@ -1207,18 +1227,24 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
 | 
			
		||||
 | 
			
		||||
  } // end confAliasExists
 | 
			
		||||
 | 
			
		||||
  public HTMLChecker getPreviewChecker()
 | 
			
		||||
  {
 | 
			
		||||
    return html_configs[HTMLC_PREVIEW_BODY].createHTMLChecker();
 | 
			
		||||
 | 
			
		||||
  } // end getPreviewChecker
 | 
			
		||||
 | 
			
		||||
  public HTMLChecker getEscapingChecker()
 | 
			
		||||
  {
 | 
			
		||||
    return html_configs[HTMLC_ESCAPE_BODY_PSEUD].createHTMLChecker();
 | 
			
		||||
 | 
			
		||||
  } // end getEscapingChecker
 | 
			
		||||
 | 
			
		||||
  public int getNumPostsPerPage()
 | 
			
		||||
  {
 | 
			
		||||
    return gp_ints[IP_POSTSPERPAGE];
 | 
			
		||||
 | 
			
		||||
  } // end getNumPostsPerPage
 | 
			
		||||
 | 
			
		||||
  public int getNumOldPostsBeforeNew()
 | 
			
		||||
  {
 | 
			
		||||
    return gp_ints[IP_POSTSATTOP];
 | 
			
		||||
 | 
			
		||||
  } // end getNumOldPostsBeforeNew
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface EngineBackend
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -1557,4 +1583,36 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
 | 
			
		||||
 | 
			
		||||
  } // end createCheckerObject
 | 
			
		||||
 | 
			
		||||
  public int getParamInt(int selector)
 | 
			
		||||
  {
 | 
			
		||||
    return gp_ints[selector];
 | 
			
		||||
 | 
			
		||||
  } // end getParamInt
 | 
			
		||||
 | 
			
		||||
  public void forceParamReload() throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    Connection conn = null;  // data pooled connection
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // get a connection and use it to reload
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
      loadDefaults(stmt);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // just log an error if we screwed up
 | 
			
		||||
      logger.error("DB error loading parameters: " + e.getMessage(),e);
 | 
			
		||||
      throw new DataException("Database error reloading parameters: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    finally
 | 
			
		||||
    { // make sure the connection is released before we go
 | 
			
		||||
      if (conn!=null)
 | 
			
		||||
	datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
  } // end forceParamReload
 | 
			
		||||
 | 
			
		||||
} // end class VeniceEngineImpl
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@
 | 
			
		||||
 * 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 Community System.
 | 
			
		||||
 * The Original Code is the Venice Web Communities System.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
@ -27,6 +27,13 @@ import com.silverwrist.venice.core.IDUtils;
 | 
			
		||||
 | 
			
		||||
public class PostLinkRewriter implements Rewriter
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static data members
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public static final String URI_PREFIX = "x-postlink:";
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Attributes
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -52,7 +59,7 @@ public class PostLinkRewriter implements Rewriter
 | 
			
		||||
 | 
			
		||||
  private static String buildPostLink(PostLinkDecoder pl, PostLinkDecoderContext ctxt)
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer b = new StringBuffer("x-postlink:");
 | 
			
		||||
    StringBuffer b = new StringBuffer(URI_PREFIX);
 | 
			
		||||
    boolean started = false;
 | 
			
		||||
    if (pl.getSIG()==null)
 | 
			
		||||
      b.append(ctxt.getSIGName());
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@
 | 
			
		||||
 * 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 Community System.
 | 
			
		||||
 * The Original Code is the Venice Web Communities System.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
@ -26,6 +26,13 @@ import com.silverwrist.venice.core.IDUtils;
 | 
			
		||||
 | 
			
		||||
public class UserNameRewriter implements Rewriter
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static data members
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public static final String URI_PREFIX = "x-userlink:";
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Attributes
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -85,8 +92,9 @@ public class UserNameRewriter implements Rewriter
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
    StringBuffer open_a = new StringBuffer("<A HREF=\"x-userlink:");
 | 
			
		||||
    open_a.append(data).append("\"");
 | 
			
		||||
    // build the markup data and return it
 | 
			
		||||
    StringBuffer open_a = new StringBuffer("<A HREF=\"");
 | 
			
		||||
    open_a.append(URI_PREFIX).append(data).append("\"");
 | 
			
		||||
    String catenate = svc.getRewriterAttrValue("ANCHORTAIL");
 | 
			
		||||
    if (!(StringUtil.isStringEmpty(catenate)))
 | 
			
		||||
      open_a.append(' ').append(catenate);
 | 
			
		||||
 | 
			
		||||
@ -224,7 +224,7 @@ public class ConfDisplay extends VeniceServlet
 | 
			
		||||
 | 
			
		||||
  } // end getViewSortDefaults
 | 
			
		||||
 | 
			
		||||
  private static PostInterval getInterval(ServletRequest request, TopicContext topic)
 | 
			
		||||
  private static PostInterval getInterval(VeniceEngine engine, ServletRequest request, TopicContext topic)
 | 
			
		||||
     throws ValidationException
 | 
			
		||||
  {
 | 
			
		||||
    int first, last;
 | 
			
		||||
@ -274,10 +274,10 @@ public class ConfDisplay extends VeniceServlet
 | 
			
		||||
    { // no range specified - cook up a default one
 | 
			
		||||
      last = topic.getTotalMessages();
 | 
			
		||||
      int ur = topic.getUnreadMessages();
 | 
			
		||||
      if ((ur==0) || (ur>=20))  // TODO: configurable
 | 
			
		||||
	first = last - 20;
 | 
			
		||||
      if ((ur==0) || (ur>=engine.getNumPostsPerPage()))
 | 
			
		||||
	first = last - engine.getNumPostsPerPage();
 | 
			
		||||
      else
 | 
			
		||||
	first = last - (ur+2);
 | 
			
		||||
	first = last - (ur + engine.getNumOldPostsBeforeNew());
 | 
			
		||||
      last--;
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
@ -324,6 +324,72 @@ public class ConfDisplay extends VeniceServlet
 | 
			
		||||
 | 
			
		||||
  } // end getInterval
 | 
			
		||||
 | 
			
		||||
  private static void restorePosts(ServletRequest request, ConferenceContext conf)
 | 
			
		||||
  {
 | 
			
		||||
    String xtopic = request.getParameter("rtop");
 | 
			
		||||
    if (StringUtil.isStringEmpty(xtopic))
 | 
			
		||||
      return;
 | 
			
		||||
    String xcount = request.getParameter("rct");
 | 
			
		||||
    if (StringUtil.isStringEmpty(xcount))
 | 
			
		||||
      return;
 | 
			
		||||
    
 | 
			
		||||
    TopicContext topic;
 | 
			
		||||
    try
 | 
			
		||||
    { // get the topic corresponding to the first parameter
 | 
			
		||||
      topic = conf.getTopic(Short.parseShort(xtopic));
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // the topic number was invalid - forget it
 | 
			
		||||
      logger.warn("restorePosts: error translating topic number");
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    catch (DataException de)
 | 
			
		||||
    { // could not get the topic...
 | 
			
		||||
      logger.warn("restorePosts: DataException getting topic - " + de.getMessage(),de);
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    catch (AccessError ae)
 | 
			
		||||
    { // no access to the topic
 | 
			
		||||
      logger.warn("restorePosts: AccessError getting topic - " + ae.getMessage(),ae);
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
    int nunread;
 | 
			
		||||
    try
 | 
			
		||||
    { // translate the number of unread posts to set
 | 
			
		||||
      nunread = Integer.parseInt(xcount);
 | 
			
		||||
      if ((nunread<=0) || (nunread>topic.getTotalMessages()))
 | 
			
		||||
      { // must be in the range [1, #messages]...
 | 
			
		||||
	logger.warn("restorePosts: unread post count out of range");
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // the number of unread posts was invalid - forget it
 | 
			
		||||
      logger.warn("restorePosts: error translating unread post count");
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // now try to set the unread messages
 | 
			
		||||
      topic.setUnreadMessages(nunread);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (DataException de)
 | 
			
		||||
    { // could not get the topic...
 | 
			
		||||
      logger.warn("restorePosts: DataException setting unread messages - " + de.getMessage(),de);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end restorePosts
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Overrides from class HttpServlet
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -428,14 +494,18 @@ public class ConfDisplay extends VeniceServlet
 | 
			
		||||
	if (logger.isDebugEnabled())
 | 
			
		||||
	  logger.debug("MODE: display messages in topic");
 | 
			
		||||
 | 
			
		||||
	// if this request is restoring the number of unread posts in another topic, try to do so
 | 
			
		||||
	restorePosts(request,conf);
 | 
			
		||||
 | 
			
		||||
	try
 | 
			
		||||
	{ // determine what the post interval is we want to display
 | 
			
		||||
	  PostInterval piv = getInterval(request,topic);
 | 
			
		||||
	  VeniceEngine engine = getVeniceEngine();
 | 
			
		||||
	  PostInterval piv = getInterval(engine,request,topic);
 | 
			
		||||
	  boolean read_new = !(StringUtil.isStringEmpty(request.getParameter("rnm")));
 | 
			
		||||
	  boolean show_adv = !(StringUtil.isStringEmpty(request.getParameter("shac")));
 | 
			
		||||
 | 
			
		||||
	  // create the post display
 | 
			
		||||
	  TopicPosts tpos = new TopicPosts(request,sig,conf,topic,piv.getFirst(),piv.getLast(),
 | 
			
		||||
	  TopicPosts tpos = new TopicPosts(request,engine,sig,conf,topic,piv.getFirst(),piv.getLast(),
 | 
			
		||||
                                           read_new,show_adv);
 | 
			
		||||
	  content = tpos;
 | 
			
		||||
	  page_title = topic.getName() + ": " + String.valueOf(topic.getTotalMessages()) + " Total; "
 | 
			
		||||
 | 
			
		||||
@ -414,7 +414,7 @@ public class ConfOperations extends VeniceServlet
 | 
			
		||||
 | 
			
		||||
	    try
 | 
			
		||||
	    { // do a preview generation
 | 
			
		||||
	      ntf.generatePreview(getVeniceEngine(),request);
 | 
			
		||||
	      ntf.generatePreview(getVeniceEngine(),conf,request);
 | 
			
		||||
 | 
			
		||||
	      if (ntf.isNullRequest())
 | 
			
		||||
	      { // no title or text specified - this is a "204 No Content" return
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										393
									
								
								src/com/silverwrist/venice/servlets/PostOperations.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,393 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 * 
 | 
			
		||||
 * 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 <erbo@silcom.com>,
 | 
			
		||||
 * 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;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import javax.servlet.*;
 | 
			
		||||
import javax.servlet.http.*;
 | 
			
		||||
import org.apache.log4j.*;
 | 
			
		||||
import com.silverwrist.util.StringUtil;
 | 
			
		||||
import com.silverwrist.venice.ValidationException;
 | 
			
		||||
import com.silverwrist.venice.core.*;
 | 
			
		||||
import com.silverwrist.venice.servlets.format.*;
 | 
			
		||||
 | 
			
		||||
public class PostOperations extends VeniceServlet
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static data members
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private static final String NUKE_CONFIRM_ATTR = "servlets.PostOperations.nuke.confirm";
 | 
			
		||||
  private static final String NUKE_CONFIRM_PARAM = "confirm";
 | 
			
		||||
 | 
			
		||||
  private static Category logger = Category.getInstance(TopicOperations.class.getName());
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Internal functions
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private static SIGContext getSIGParameter(ServletRequest request, UserContext user)
 | 
			
		||||
      throws ValidationException, DataException
 | 
			
		||||
  {
 | 
			
		||||
    String str = request.getParameter("sig");
 | 
			
		||||
    if (str==null)
 | 
			
		||||
    { // no SIG parameter - bail out now!
 | 
			
		||||
      logger.error("SIG parameter not specified!");
 | 
			
		||||
      throw new ValidationException("No SIG specified.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // turn the string into a SIGID, and thence to a SIGContext
 | 
			
		||||
      int sigid = Integer.parseInt(str);
 | 
			
		||||
      return user.getSIGContext(sigid);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // error in Integer.parseInt
 | 
			
		||||
      logger.error("Cannot convert SIG parameter '" + str + "'!");
 | 
			
		||||
      throw new ValidationException("Invalid SIG parameter.");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getSIGParameter
 | 
			
		||||
 | 
			
		||||
  private static ConferenceContext getConferenceParameter(ServletRequest request, SIGContext sig)
 | 
			
		||||
    throws ValidationException, DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    String str = request.getParameter("conf");
 | 
			
		||||
    if (str==null)
 | 
			
		||||
    { // no conference parameter - bail out now!
 | 
			
		||||
      logger.error("Conference parameter not specified!");
 | 
			
		||||
      throw new ValidationException("No conference specified.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // turn the string into a ConfID, and thence to a ConferenceContext
 | 
			
		||||
      int confid = Integer.parseInt(str);
 | 
			
		||||
      return sig.getConferenceContext(confid);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // error in Integer.parseInt
 | 
			
		||||
      logger.error("Cannot convert conference parameter '" + str + "'!");
 | 
			
		||||
      throw new ValidationException("Invalid conference parameter.");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getConferenceParameter
 | 
			
		||||
 | 
			
		||||
  private static TopicContext getTopicParameter(ServletRequest request, ConferenceContext conf)
 | 
			
		||||
    throws ValidationException, DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    String str = request.getParameter("top");
 | 
			
		||||
    if (StringUtil.isStringEmpty(str))
 | 
			
		||||
    { // no topic parameter - bail out now!
 | 
			
		||||
      logger.error("Topic parameter not specified!");
 | 
			
		||||
      throw new ValidationException("No topic specified.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // turn the string into a TopicID, and thence to a TopicContext
 | 
			
		||||
      short topicid = Short.parseShort(str);
 | 
			
		||||
      return conf.getTopic(topicid);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // error in Integer.parseInt
 | 
			
		||||
      logger.error("Cannot convert topic parameter '" + str + "'!");
 | 
			
		||||
      throw new ValidationException("Invalid topic parameter.");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getTopicParameter
 | 
			
		||||
 | 
			
		||||
  private static TopicMessageContext getMessageParameter(ServletRequest request, TopicContext topic)
 | 
			
		||||
    throws ValidationException, DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    String str = request.getParameter("msg");
 | 
			
		||||
    if (StringUtil.isStringEmpty(str))
 | 
			
		||||
    { // no topic parameter - bail out now!
 | 
			
		||||
      logger.error("Message parameter not specified!");
 | 
			
		||||
      throw new ValidationException("No message specified.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // turn the string into a TopicID, and thence to a TopicContext
 | 
			
		||||
      int message_num = Integer.parseInt(str);
 | 
			
		||||
      return topic.getMessage(message_num);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // error in Integer.parseInt
 | 
			
		||||
      logger.error("Cannot convert message parameter '" + str + "'!");
 | 
			
		||||
      throw new ValidationException("Invalid message parameter.");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getMessageParameter
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Overrides from class HttpServlet
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public String getServletInfo()
 | 
			
		||||
  {
 | 
			
		||||
    String rc = "PostOperations servlet - General post operations (hide, scribble, etc.)\n"
 | 
			
		||||
              + "Part of the Venice Web Communities System\n";
 | 
			
		||||
    return rc;
 | 
			
		||||
 | 
			
		||||
  } // end getServletInfo
 | 
			
		||||
 | 
			
		||||
  public void doGet(HttpServletRequest request, HttpServletResponse response)
 | 
			
		||||
    throws ServletException, IOException
 | 
			
		||||
  {
 | 
			
		||||
    UserContext user = getUserContext(request);
 | 
			
		||||
    RenderData rdat = createRenderData(request,response);
 | 
			
		||||
    String location = "top";
 | 
			
		||||
    String locator = null;
 | 
			
		||||
    String page_title = null;
 | 
			
		||||
    Object content = null;
 | 
			
		||||
    SIGContext sig = null;            // SIG context
 | 
			
		||||
    ConferenceContext conf = null;    // conference context
 | 
			
		||||
    TopicContext topic = null;        // topic context
 | 
			
		||||
    TopicMessageContext msg = null;   // message context
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // this outer try is to catch ValidationException
 | 
			
		||||
      try
 | 
			
		||||
      { // all commands require a SIG parameter
 | 
			
		||||
	sig = getSIGParameter(request,user);
 | 
			
		||||
	changeMenuSIG(request,sig);
 | 
			
		||||
	if (logger.isDebugEnabled())
 | 
			
		||||
	  logger.debug("found SIG #" + String.valueOf(sig.getSIGID()));
 | 
			
		||||
	locator = "sig=" + String.valueOf(sig.getSIGID());
 | 
			
		||||
	location = "sigprofile?" + locator;
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (DataException de)
 | 
			
		||||
      { // error looking up the SIG
 | 
			
		||||
	page_title = "Database Error";
 | 
			
		||||
	content = new ErrorBox(page_title,"Database error finding SIG: " + de.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
      if (content==null)
 | 
			
		||||
      { // we got the SIG parameter OK
 | 
			
		||||
	try
 | 
			
		||||
	{ // all commands require a conference parameter
 | 
			
		||||
	  conf = getConferenceParameter(request,sig);
 | 
			
		||||
	  if (logger.isDebugEnabled())
 | 
			
		||||
	    logger.debug("found conf #" + String.valueOf(conf.getConfID()));
 | 
			
		||||
	  locator += "&conf=" + String.valueOf(conf.getConfID());
 | 
			
		||||
	  location = "confdisp?" + locator;
 | 
			
		||||
	  
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // error looking up the conference
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error finding conference: " + de.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
 | 
			
		||||
      if (content==null)
 | 
			
		||||
      { // we got the conference parameter OK
 | 
			
		||||
	try
 | 
			
		||||
	{ // now we need a topic parameter
 | 
			
		||||
	  topic = getTopicParameter(request,conf);
 | 
			
		||||
	  if (logger.isDebugEnabled())
 | 
			
		||||
	    logger.debug("found topic #" + String.valueOf(topic.getTopicID()));
 | 
			
		||||
	  locator += "&top=" + String.valueOf(topic.getTopicID());
 | 
			
		||||
	  location = "confdisp?" + locator;
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // error looking up the conference
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error finding topic: " + de.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
 | 
			
		||||
      if (content==null)
 | 
			
		||||
      { // we got the topic parameter OK
 | 
			
		||||
	try
 | 
			
		||||
	{ // now we need a message parameter
 | 
			
		||||
	  msg = getMessageParameter(request,topic);
 | 
			
		||||
	  if (logger.isDebugEnabled())
 | 
			
		||||
	    logger.debug("found message #" + String.valueOf(msg.getPostID()));
 | 
			
		||||
	  location = "confdisp?" + locator + "&p1=" + msg.getPostNumber() + "&shac=1";
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // error looking up the conference
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error finding message: " + de.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (ValidationException ve)
 | 
			
		||||
    { // these all get handled in pretty much the same way
 | 
			
		||||
      page_title = "Error";
 | 
			
		||||
      content = new ErrorBox(null,ve.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    catch (AccessError ae)
 | 
			
		||||
    { // these all get handled in pretty much the same way
 | 
			
		||||
      page_title = "Access Error";
 | 
			
		||||
      content = new ErrorBox(page_title,ae.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
    if (content==null)
 | 
			
		||||
    { // figure out what command we want to perform
 | 
			
		||||
      String cmd = request.getParameter("cmd");
 | 
			
		||||
      if (cmd==null)
 | 
			
		||||
	cmd = "???";
 | 
			
		||||
 | 
			
		||||
      if (cmd.equals("HY") || cmd.equals("HN"))
 | 
			
		||||
      { // we want to hide or show the message
 | 
			
		||||
	try
 | 
			
		||||
	{ // attempt to hide or show the message
 | 
			
		||||
	  msg.setHidden(cmd.equals("HY"));
 | 
			
		||||
 | 
			
		||||
	  // go back and display stuff
 | 
			
		||||
	  rdat.redirectTo(location);
 | 
			
		||||
	  return;
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // there was a database error
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error setting hidden status: " + de.getMessage(),
 | 
			
		||||
				 location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	catch (AccessError ae)
 | 
			
		||||
	{ // naughty naughty = you can't do this!
 | 
			
		||||
	  page_title = "Access Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,ae.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end if ("hide" or "show")
 | 
			
		||||
      else if (cmd.equals("SCR"))
 | 
			
		||||
      { // we want to scribble the message
 | 
			
		||||
	try
 | 
			
		||||
	{ // attempt to scribble the message
 | 
			
		||||
	  msg.scribble();
 | 
			
		||||
 | 
			
		||||
	  // go back and display stuff
 | 
			
		||||
	  rdat.redirectTo(location);
 | 
			
		||||
	  return;
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // there was a database error
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error scribbling message: " + de.getMessage(),
 | 
			
		||||
				 location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	catch (AccessError ae)
 | 
			
		||||
	{ // naughty naughty = you can't do this!
 | 
			
		||||
	  page_title = "Access Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,ae.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end else if ("scribble")
 | 
			
		||||
      else if (cmd.equals("NUKE"))
 | 
			
		||||
      { // nuking requires confirmation
 | 
			
		||||
	try
 | 
			
		||||
	{ // we need confirmation on this operation!
 | 
			
		||||
	  if (ConfirmBox.isConfirmed(request,NUKE_CONFIRM_ATTR,NUKE_CONFIRM_PARAM))
 | 
			
		||||
	  { // OK, go ahead, nuke the message!
 | 
			
		||||
	    msg.nuke();
 | 
			
		||||
 | 
			
		||||
	    // after which, redirect to topic view
 | 
			
		||||
	    rdat.redirectTo("confdisp?" + locator);
 | 
			
		||||
	    return;
 | 
			
		||||
 | 
			
		||||
	  } // end if
 | 
			
		||||
	  else
 | 
			
		||||
	  { // not a proper confirmation - better display one
 | 
			
		||||
	    List aliases = conf.getAliases();
 | 
			
		||||
	    String message = "You are about to nuke message <" + (String)(aliases.get(0)) + "."
 | 
			
		||||
	                   + String.valueOf(topic.getTopicNumber()) + "." + String.valueOf(msg.getPostNumber())
 | 
			
		||||
                           + ">, originally composed by <" + msg.getCreatorName()
 | 
			
		||||
	                   + ">!  Are you sure you want to do this?";
 | 
			
		||||
	    String confirm_url = "postops?" + locator + "&msg=" + msg.getPostNumber() + "&cmd=NUKE";
 | 
			
		||||
 | 
			
		||||
	    page_title = "Nuke Message";
 | 
			
		||||
	    content = new ConfirmBox(request,NUKE_CONFIRM_ATTR,NUKE_CONFIRM_PARAM,page_title,
 | 
			
		||||
				     message,confirm_url,location);
 | 
			
		||||
 | 
			
		||||
	  } // end else
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // there was a database error
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error nuking message: " + de.getMessage(),
 | 
			
		||||
				 location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	catch (AccessError ae)
 | 
			
		||||
	{ // naughty naughty = you can't do this!
 | 
			
		||||
	  page_title = "Access Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,ae.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end else if ("nuke")
 | 
			
		||||
      else
 | 
			
		||||
      { // unrecognized command!
 | 
			
		||||
	page_title = "Internal Error";
 | 
			
		||||
	logger.error("invalid command to PostOperations.doGet: " + cmd);
 | 
			
		||||
	content = new ErrorBox(page_title,"Invalid command to PostOperations.doGet",location);
 | 
			
		||||
 | 
			
		||||
      } // end else
 | 
			
		||||
 | 
			
		||||
    } // end if (got parameters OK)
 | 
			
		||||
 | 
			
		||||
    BaseJSPData basedat = new BaseJSPData(page_title,location,content);
 | 
			
		||||
    basedat.transfer(getServletContext(),rdat);
 | 
			
		||||
 | 
			
		||||
  } // end doGet
 | 
			
		||||
 | 
			
		||||
} // end class PostOperations
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										161
									
								
								src/com/silverwrist/venice/servlets/PostShortcut.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,161 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 * 
 | 
			
		||||
 * 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 <erbo@silcom.com>,
 | 
			
		||||
 * 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;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import javax.servlet.*;
 | 
			
		||||
import javax.servlet.http.*;
 | 
			
		||||
import com.silverwrist.venice.ValidationException;
 | 
			
		||||
import com.silverwrist.venice.core.*;
 | 
			
		||||
import com.silverwrist.venice.db.PostLinkDecoder;
 | 
			
		||||
import com.silverwrist.venice.servlets.format.*;
 | 
			
		||||
 | 
			
		||||
public class PostShortcut extends VeniceServlet
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Overrides from class HttpServlet
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public String getServletInfo()
 | 
			
		||||
  {
 | 
			
		||||
    String rc = "PostShortcut servlet - Decodes a post link and redirects to it\n"
 | 
			
		||||
              + "Part of the Venice Web Communities System\n";
 | 
			
		||||
    return rc;
 | 
			
		||||
 | 
			
		||||
  } // end getServletInfo
 | 
			
		||||
 | 
			
		||||
  public void doGet(HttpServletRequest request, HttpServletResponse response)
 | 
			
		||||
    throws ServletException, IOException
 | 
			
		||||
  {
 | 
			
		||||
    UserContext user = getUserContext(request);
 | 
			
		||||
    RenderData rdat = createRenderData(request,response);
 | 
			
		||||
    String raw_link = request.getPathInfo().substring(1);
 | 
			
		||||
    PostLinkDecoder decoder;
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // attempt to decode the path link information
 | 
			
		||||
      decoder = new PostLinkDecoder(raw_link);
 | 
			
		||||
      if (decoder.getSIG()==null)  // it must include the SIG
 | 
			
		||||
	throw new ValidationException("ambiguous post link (no SIG)");
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (ValidationException e)
 | 
			
		||||
    { // display an error message for validation
 | 
			
		||||
      String page_title = "Invalid Post Link";
 | 
			
		||||
      ContentRender content = new ErrorBox(page_title,"Invalid post link \"" + raw_link + "\": "
 | 
			
		||||
					   + e.getMessage(),null);
 | 
			
		||||
      new BaseJSPData(page_title,"top",content).transfer(getServletContext(),rdat);
 | 
			
		||||
      return;
 | 
			
		||||
      
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
    SIGContext sig;
 | 
			
		||||
    try
 | 
			
		||||
    { // get the SIG represented by that alias
 | 
			
		||||
      sig = user.getSIGContext(decoder.getSIG());
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (DataException e)
 | 
			
		||||
    { // can't find the SIG - we're screwed
 | 
			
		||||
      String page_title = "Invalid Post Link";
 | 
			
		||||
      ContentRender content = new ErrorBox(page_title,"Invalid post link \"" + raw_link
 | 
			
		||||
					   + "\": cannot find SIG: " + e.getMessage(),null);
 | 
			
		||||
      new BaseJSPData(page_title,"top",content).transfer(getServletContext(),rdat);
 | 
			
		||||
      return;
 | 
			
		||||
      
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
    if (decoder.getConference()==null)
 | 
			
		||||
    { // it's a SIG link only - redirect to the SIG's default page
 | 
			
		||||
      rdat.redirectTo("sig/" + decoder.getSIG());
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    ConferenceContext conf;
 | 
			
		||||
    try
 | 
			
		||||
    { // get the conference represented by that alias
 | 
			
		||||
      conf = sig.getConferenceContext(decoder.getConference());
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (DataException e)
 | 
			
		||||
    { // can't find the conference - we're screwed
 | 
			
		||||
      String page_title = "Invalid Post Link";
 | 
			
		||||
      ContentRender content = new ErrorBox(page_title,"Invalid post link \"" + raw_link
 | 
			
		||||
					   + "\": cannot find conference: " + e.getMessage(),null);
 | 
			
		||||
      new BaseJSPData(page_title,"top",content).transfer(getServletContext(),rdat);
 | 
			
		||||
      return;
 | 
			
		||||
      
 | 
			
		||||
    } // end catch
 | 
			
		||||
    catch (AccessError ae)
 | 
			
		||||
    { // we can't get to the conference...
 | 
			
		||||
      String page_title = "Access Error";
 | 
			
		||||
      ContentRender content = new ErrorBox(page_title,ae.getMessage(),null);
 | 
			
		||||
      new BaseJSPData(page_title,"top",content).transfer(getServletContext(),rdat);
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
    // compute an elementary "locator"
 | 
			
		||||
    String locator = "sig=" + String.valueOf(sig.getSIGID()) + "&conf=" + String.valueOf(conf.getConfID());
 | 
			
		||||
 | 
			
		||||
    if (decoder.getTopic()==-1)
 | 
			
		||||
    { // just a conference link - go to the top-level display
 | 
			
		||||
      rdat.redirectTo("confdisp?" + locator);
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    TopicContext topic;
 | 
			
		||||
    try
 | 
			
		||||
    { // get the topic number specified within that topic
 | 
			
		||||
      topic = conf.getTopic(decoder.getTopic());
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (DataException e)
 | 
			
		||||
    { // we can't find the topic - we're screwed
 | 
			
		||||
      String page_title = "Invalid Post Link";
 | 
			
		||||
      ContentRender content = new ErrorBox(page_title,"Invalid post link \"" + raw_link
 | 
			
		||||
					   + "\": cannot find topic: " + e.getMessage(),null);
 | 
			
		||||
      new BaseJSPData(page_title,"top",content).transfer(getServletContext(),rdat);
 | 
			
		||||
      return;
 | 
			
		||||
      
 | 
			
		||||
    } // end catch
 | 
			
		||||
    catch (AccessError ae)
 | 
			
		||||
    { // we can't get to the topic...
 | 
			
		||||
      String page_title = "Access Error";
 | 
			
		||||
      ContentRender content = new ErrorBox(page_title,ae.getMessage(),null);
 | 
			
		||||
      new BaseJSPData(page_title,"top",content).transfer(getServletContext(),rdat);
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
    // add the topic to our locator
 | 
			
		||||
    locator += "&top=" + String.valueOf(decoder.getTopic());
 | 
			
		||||
 | 
			
		||||
    if (decoder.getFirstPost()==-1) // we're just referencing the topic
 | 
			
		||||
      rdat.redirectTo("confdisp?" + locator + "&rnm=1");
 | 
			
		||||
    else  // we're referencing a post range within the topic
 | 
			
		||||
      rdat.redirectTo("confdisp?" + locator + "&p1=" + String.valueOf(decoder.getFirstPost()) + "&p2="
 | 
			
		||||
		      + String.valueOf(decoder.getLastPost()));
 | 
			
		||||
 | 
			
		||||
  } // end doGet
 | 
			
		||||
 | 
			
		||||
} // end class PostShortcut
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@
 | 
			
		||||
 * 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 Community System.
 | 
			
		||||
 * The Original Code is the Venice Web Communities System.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
@ -25,10 +25,15 @@ import com.silverwrist.venice.servlets.format.*;
 | 
			
		||||
 | 
			
		||||
public class SIGFrontEnd extends VeniceServlet
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Overrides from class HttpServlet
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public String getServletInfo()
 | 
			
		||||
  {
 | 
			
		||||
    String rc = "SIGFrontEnd servlet - Redirects to the \"default feature\" of a SIG\n"
 | 
			
		||||
              + "Part of the Venice Web conferencing system\n";
 | 
			
		||||
              + "Part of the Venice Web Communities System\n";
 | 
			
		||||
    return rc;
 | 
			
		||||
 | 
			
		||||
  } // end getServletInfo
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										357
									
								
								src/com/silverwrist/venice/servlets/TopicOperations.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,357 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 * 
 | 
			
		||||
 * 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 <erbo@silcom.com>,
 | 
			
		||||
 * 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;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import javax.servlet.*;
 | 
			
		||||
import javax.servlet.http.*;
 | 
			
		||||
import org.apache.log4j.*;
 | 
			
		||||
import com.silverwrist.util.StringUtil;
 | 
			
		||||
import com.silverwrist.venice.ValidationException;
 | 
			
		||||
import com.silverwrist.venice.core.*;
 | 
			
		||||
import com.silverwrist.venice.servlets.format.*;
 | 
			
		||||
 | 
			
		||||
public class TopicOperations extends VeniceServlet
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static data members
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 
 | 
			
		||||
  private static final String DELETE_CONFIRM_ATTR = "servlets.TopicOperations.delete.confirm";
 | 
			
		||||
  private static final String DELETE_CONFIRM_PARAM = "confirm";
 | 
			
		||||
 | 
			
		||||
  private static Category logger = Category.getInstance(TopicOperations.class.getName());
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Internal functions
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private static SIGContext getSIGParameter(ServletRequest request, UserContext user)
 | 
			
		||||
      throws ValidationException, DataException
 | 
			
		||||
  {
 | 
			
		||||
    String str = request.getParameter("sig");
 | 
			
		||||
    if (str==null)
 | 
			
		||||
    { // no SIG parameter - bail out now!
 | 
			
		||||
      logger.error("SIG parameter not specified!");
 | 
			
		||||
      throw new ValidationException("No SIG specified.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // turn the string into a SIGID, and thence to a SIGContext
 | 
			
		||||
      int sigid = Integer.parseInt(str);
 | 
			
		||||
      return user.getSIGContext(sigid);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // error in Integer.parseInt
 | 
			
		||||
      logger.error("Cannot convert SIG parameter '" + str + "'!");
 | 
			
		||||
      throw new ValidationException("Invalid SIG parameter.");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getSIGParameter
 | 
			
		||||
 | 
			
		||||
  private static ConferenceContext getConferenceParameter(ServletRequest request, SIGContext sig)
 | 
			
		||||
    throws ValidationException, DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    String str = request.getParameter("conf");
 | 
			
		||||
    if (str==null)
 | 
			
		||||
    { // no conference parameter - bail out now!
 | 
			
		||||
      logger.error("Conference parameter not specified!");
 | 
			
		||||
      throw new ValidationException("No conference specified.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // turn the string into a ConfID, and thence to a ConferenceContext
 | 
			
		||||
      int confid = Integer.parseInt(str);
 | 
			
		||||
      return sig.getConferenceContext(confid);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // error in Integer.parseInt
 | 
			
		||||
      logger.error("Cannot convert conference parameter '" + str + "'!");
 | 
			
		||||
      throw new ValidationException("Invalid conference parameter.");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getConferenceParameter
 | 
			
		||||
 | 
			
		||||
  private static TopicContext getTopicParameter(ServletRequest request, ConferenceContext conf)
 | 
			
		||||
    throws ValidationException, DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    String str = request.getParameter("top");
 | 
			
		||||
    if (StringUtil.isStringEmpty(str))
 | 
			
		||||
    { // no topic parameter - bail out now!
 | 
			
		||||
      logger.error("Topic parameter not specified!");
 | 
			
		||||
      throw new ValidationException("No topic specified.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // turn the string into a TopicID, and thence to a TopicContext
 | 
			
		||||
      short topicid = Short.parseShort(str);
 | 
			
		||||
      return conf.getTopic(topicid);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // error in Integer.parseInt
 | 
			
		||||
      logger.error("Cannot convert topic parameter '" + str + "'!");
 | 
			
		||||
      throw new ValidationException("Invalid topic parameter.");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getTopicParameter
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Overrides from class HttpServlet
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public String getServletInfo()
 | 
			
		||||
  {
 | 
			
		||||
    String rc = "TopicOperations servlet - General topic operations (freeze, archive, etc.)\n"
 | 
			
		||||
              + "Part of the Venice Web Communities System\n";
 | 
			
		||||
    return rc;
 | 
			
		||||
 | 
			
		||||
  } // end getServletInfo
 | 
			
		||||
 | 
			
		||||
  public void doGet(HttpServletRequest request, HttpServletResponse response)
 | 
			
		||||
    throws ServletException, IOException
 | 
			
		||||
  {
 | 
			
		||||
    UserContext user = getUserContext(request);
 | 
			
		||||
    RenderData rdat = createRenderData(request,response);
 | 
			
		||||
    String location = "top";
 | 
			
		||||
    String locator = null;
 | 
			
		||||
    String page_title = null;
 | 
			
		||||
    Object content = null;
 | 
			
		||||
    SIGContext sig = null;            // SIG context
 | 
			
		||||
    ConferenceContext conf = null;    // conference context
 | 
			
		||||
    TopicContext topic = null;        // topic context
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // this outer try is to catch ValidationException
 | 
			
		||||
      try
 | 
			
		||||
      { // all commands require a SIG parameter
 | 
			
		||||
	sig = getSIGParameter(request,user);
 | 
			
		||||
	changeMenuSIG(request,sig);
 | 
			
		||||
	if (logger.isDebugEnabled())
 | 
			
		||||
	  logger.debug("found SIG #" + String.valueOf(sig.getSIGID()));
 | 
			
		||||
	locator = "sig=" + String.valueOf(sig.getSIGID());
 | 
			
		||||
	location = "sigprofile?" + locator;
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (DataException de)
 | 
			
		||||
      { // error looking up the SIG
 | 
			
		||||
	page_title = "Database Error";
 | 
			
		||||
	content = new ErrorBox(page_title,"Database error finding SIG: " + de.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
      if (content==null)
 | 
			
		||||
      { // we got the SIG parameter OK
 | 
			
		||||
	try
 | 
			
		||||
	{ // all commands require a conference parameter
 | 
			
		||||
	  conf = getConferenceParameter(request,sig);
 | 
			
		||||
	  if (logger.isDebugEnabled())
 | 
			
		||||
	    logger.debug("found conf #" + String.valueOf(conf.getConfID()));
 | 
			
		||||
	  locator += "&conf=" + String.valueOf(conf.getConfID());
 | 
			
		||||
	  location = "confdisp?" + locator;
 | 
			
		||||
	  
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // error looking up the conference
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error finding conference: " + de.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
 | 
			
		||||
      if (content==null)
 | 
			
		||||
      { // we got the conference parameter OK
 | 
			
		||||
	try
 | 
			
		||||
	{ // now we need a topic parameter
 | 
			
		||||
	  topic = getTopicParameter(request,conf);
 | 
			
		||||
	  if (logger.isDebugEnabled())
 | 
			
		||||
	    logger.debug("found topic #" + String.valueOf(topic.getTopicID()));
 | 
			
		||||
	  locator += "&top=" + String.valueOf(topic.getTopicNumber());
 | 
			
		||||
	  location = "confdisp?" + locator;
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // error looking up the conference
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error finding topic: " + de.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (ValidationException ve)
 | 
			
		||||
    { // these all get handled in pretty much the same way
 | 
			
		||||
      page_title = "Error";
 | 
			
		||||
      content = new ErrorBox(null,ve.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    catch (AccessError ae)
 | 
			
		||||
    { // these all get handled in pretty much the same way
 | 
			
		||||
      page_title = "Access Error";
 | 
			
		||||
      content = new ErrorBox(page_title,ae.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
    if (content==null)
 | 
			
		||||
    { // figure out what command we want to perform...
 | 
			
		||||
      String cmd = request.getParameter("cmd");
 | 
			
		||||
      if (cmd==null)
 | 
			
		||||
	cmd = "???";
 | 
			
		||||
 | 
			
		||||
      if (cmd.equals("HY") || cmd.equals("HN"))
 | 
			
		||||
      { // we want to set the hide status of the topic
 | 
			
		||||
	try
 | 
			
		||||
	{ // call down to set the topic!
 | 
			
		||||
	  topic.setHidden(cmd.equals("HY"));
 | 
			
		||||
 | 
			
		||||
	  // go back to the topic view
 | 
			
		||||
	  rdat.redirectTo(location);
 | 
			
		||||
	  return;
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // there was a database error
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error setting hide status: " + de.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	
 | 
			
		||||
      } // end if ("hide" or "show")
 | 
			
		||||
      else if (cmd.equals("FY") || cmd.equals("FN"))
 | 
			
		||||
      { // we want to set the frozen status of the topic
 | 
			
		||||
	try
 | 
			
		||||
	{ // call down to set the topic!
 | 
			
		||||
	  topic.setFrozen(cmd.equals("FY"));
 | 
			
		||||
 | 
			
		||||
	  // go back to the topic view
 | 
			
		||||
	  rdat.redirectTo(location);
 | 
			
		||||
	  return;
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // there was a database error
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error setting freeze status: " + de.getMessage(),
 | 
			
		||||
				 location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	catch (AccessError ae)
 | 
			
		||||
	{ // naughty naughty = you can't do this!
 | 
			
		||||
	  page_title = "Access Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,ae.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	
 | 
			
		||||
      } // end else if ("freeze" or "unfreeze")
 | 
			
		||||
      else if (cmd.equals("AY") || cmd.equals("AN"))
 | 
			
		||||
      { // we want to change the archived status of the topic
 | 
			
		||||
	try
 | 
			
		||||
	{ // call down to set the topic!
 | 
			
		||||
	  topic.setArchived(cmd.equals("AY"));
 | 
			
		||||
 | 
			
		||||
	  // go back to the topic view
 | 
			
		||||
	  rdat.redirectTo(location);
 | 
			
		||||
	  return;
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // there was a database error
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error setting archive status: " + de.getMessage(),
 | 
			
		||||
				 location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	catch (AccessError ae)
 | 
			
		||||
	{ // naughty naughty = you can't do this!
 | 
			
		||||
	  page_title = "Access Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,ae.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	
 | 
			
		||||
      } // end else if ("archive" or "unarchive")
 | 
			
		||||
      else if (cmd.equals("DEL"))
 | 
			
		||||
      { // we need confirmation on this operation!
 | 
			
		||||
	if (ConfirmBox.isConfirmed(request,DELETE_CONFIRM_ATTR,DELETE_CONFIRM_PARAM))
 | 
			
		||||
	{ // OK, go ahead, delete the topic!
 | 
			
		||||
	  location = "confdisp?sig=" + String.valueOf(sig.getSIGID()) + "&conf="
 | 
			
		||||
                   + String.valueOf(conf.getConfID());
 | 
			
		||||
 | 
			
		||||
	  try
 | 
			
		||||
	  { // delete the bloody topic!
 | 
			
		||||
	    topic.delete();
 | 
			
		||||
 | 
			
		||||
	    // after which, redirect to conference view
 | 
			
		||||
	    rdat.redirectTo(location);
 | 
			
		||||
	    return;
 | 
			
		||||
 | 
			
		||||
	  } // end try
 | 
			
		||||
	  catch (DataException de)
 | 
			
		||||
	  { // there was a database error
 | 
			
		||||
	    page_title = "Database Error";
 | 
			
		||||
	    content = new ErrorBox(page_title,"Database error deleting topic: " + de.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	  } // end catch
 | 
			
		||||
	  catch (AccessError ae)
 | 
			
		||||
	  { // naughty naughty = you can't do this!
 | 
			
		||||
	    page_title = "Access Error";
 | 
			
		||||
	    content = new ErrorBox(page_title,ae.getMessage(),location);
 | 
			
		||||
 | 
			
		||||
	  } // end catch
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
	else
 | 
			
		||||
	{ // not a proper confirmation - better display one
 | 
			
		||||
	  String message = "You are about to delete topic " + String.valueOf(topic.getTopicNumber())
 | 
			
		||||
                 + " from the \"" + conf.getName() + "\" conference!  Are you sure you want to do this?";
 | 
			
		||||
	  String confirm_url = "topicops?" + locator + "&cmd=DEL";
 | 
			
		||||
	  page_title = "Delete Topic";
 | 
			
		||||
	  content = new ConfirmBox(request,DELETE_CONFIRM_ATTR,DELETE_CONFIRM_PARAM,page_title,
 | 
			
		||||
				   message,confirm_url,location);
 | 
			
		||||
 | 
			
		||||
	} // end else
 | 
			
		||||
 | 
			
		||||
      } // end else if ("delete")
 | 
			
		||||
      else
 | 
			
		||||
      { // unrecognized command
 | 
			
		||||
	page_title = "Internal Error";
 | 
			
		||||
	logger.error("invalid command to TopicOperations.doGet: " + cmd);
 | 
			
		||||
	content = new ErrorBox(page_title,"Invalid command to TopicOperations.doGet",location);
 | 
			
		||||
 | 
			
		||||
      } // end else
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    BaseJSPData basedat = new BaseJSPData(page_title,location,content);
 | 
			
		||||
    basedat.transfer(getServletContext(),rdat);
 | 
			
		||||
 | 
			
		||||
  } // end doGet
 | 
			
		||||
 | 
			
		||||
} // end class TopicOperations
 | 
			
		||||
@ -101,7 +101,8 @@ public class NewTopicForm implements JSPRender
 | 
			
		||||
 | 
			
		||||
  } // end setupNewRequest
 | 
			
		||||
 | 
			
		||||
  public void generatePreview(VeniceEngine engine, ServletRequest request) throws ValidationException
 | 
			
		||||
  public void generatePreview(VeniceEngine engine, ConferenceContext conf, ServletRequest request)
 | 
			
		||||
      throws ValidationException
 | 
			
		||||
  {
 | 
			
		||||
    HTMLChecker check;
 | 
			
		||||
 | 
			
		||||
@ -136,7 +137,7 @@ public class NewTopicForm implements JSPRender
 | 
			
		||||
      post_box = check.getValue();
 | 
			
		||||
 | 
			
		||||
      // generate the body text preview
 | 
			
		||||
      check = engine.getPreviewChecker();
 | 
			
		||||
      check = conf.getNewTopicPreviewChecker();
 | 
			
		||||
      check.append(foo);
 | 
			
		||||
      check.finish();
 | 
			
		||||
      preview = check.getValue();
 | 
			
		||||
 | 
			
		||||
@ -79,7 +79,7 @@ public class PostPreview implements JSPRender
 | 
			
		||||
      this.data = check.getValue();
 | 
			
		||||
 | 
			
		||||
      // now generate the preview
 | 
			
		||||
      check = engine.getPreviewChecker();
 | 
			
		||||
      check = topic.getPreviewChecker();
 | 
			
		||||
      check.append(data);
 | 
			
		||||
      check.finish();
 | 
			
		||||
      this.preview = check.getValue();
 | 
			
		||||
 | 
			
		||||
@ -47,6 +47,7 @@ public class PostSlippage implements JSPRender
 | 
			
		||||
  private String pseud;
 | 
			
		||||
  private String text;
 | 
			
		||||
  private boolean attach;
 | 
			
		||||
  private String topic_stem;
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Constructor
 | 
			
		||||
@ -63,6 +64,8 @@ public class PostSlippage implements JSPRender
 | 
			
		||||
    this.messages = topic.getMessages(lastval,topic.getTotalMessages()-1);
 | 
			
		||||
    this.next = next;
 | 
			
		||||
    this.attach = attach;
 | 
			
		||||
    List aliases = conf.getAliases();
 | 
			
		||||
    topic_stem = (String)(aliases.get(0)) + "." + String.valueOf(topic.getTopicNumber()) + ".";
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // run the text and pseud through an HTML checker to escape them
 | 
			
		||||
@ -213,4 +216,10 @@ public class PostSlippage implements JSPRender
 | 
			
		||||
 | 
			
		||||
  } // end getBodyText
 | 
			
		||||
 | 
			
		||||
  public String getMessageReference(TopicMessageContext msg)
 | 
			
		||||
  {
 | 
			
		||||
    return topic_stem + String.valueOf(msg.getPostNumber());
 | 
			
		||||
 | 
			
		||||
  } // end getMessageReference
 | 
			
		||||
 | 
			
		||||
} // end class PostSlippage
 | 
			
		||||
 | 
			
		||||
@ -54,6 +54,7 @@ public class RenderConfig
 | 
			
		||||
  private String font_face;
 | 
			
		||||
  private String base_url;
 | 
			
		||||
  private String image_url;
 | 
			
		||||
  private String static_url;
 | 
			
		||||
  private String site_logo;
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
@ -148,6 +149,17 @@ public class RenderConfig
 | 
			
		||||
    if (logger.isDebugEnabled())
 | 
			
		||||
      logger.debug("Image path: " + image_url);
 | 
			
		||||
 | 
			
		||||
    static_url = paths_sect_h.getSubElementText("static");
 | 
			
		||||
    if (static_url==null)
 | 
			
		||||
    { // no <static/> tag - bail out now!
 | 
			
		||||
      logger.fatal("<paths/> section has no <static/> element");
 | 
			
		||||
      throw new ConfigException("no <static/> found in <paths/> section",paths_sect);
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    if (logger.isDebugEnabled())
 | 
			
		||||
      logger.debug("Static files path: " + static_url);
 | 
			
		||||
 | 
			
		||||
    site_logo = paths_sect_h.getSubElementText("site-logo");
 | 
			
		||||
    if (site_logo==null)
 | 
			
		||||
    { // no <image/> tag - bail out now!
 | 
			
		||||
@ -256,6 +268,14 @@ public class RenderConfig
 | 
			
		||||
 | 
			
		||||
  } // end getFullImagePath
 | 
			
		||||
 | 
			
		||||
  String getStaticFilePath(String name)
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer buf = new StringBuffer();
 | 
			
		||||
    buf.append(static_url).append(name);
 | 
			
		||||
    return buf.toString();
 | 
			
		||||
 | 
			
		||||
  } // end getStaticFilePath
 | 
			
		||||
 | 
			
		||||
  String getTitleTag(String specific)
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer buf = new StringBuffer();
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@
 | 
			
		||||
 * 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 Community System.
 | 
			
		||||
 * The Original Code is the Venice Web Communities System.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
@ -24,6 +24,9 @@ import javax.servlet.*;
 | 
			
		||||
import javax.servlet.http.*;
 | 
			
		||||
import org.apache.log4j.*;
 | 
			
		||||
import com.silverwrist.util.StringUtil;
 | 
			
		||||
import com.silverwrist.venice.core.IDUtils;
 | 
			
		||||
import com.silverwrist.venice.db.PostLinkRewriter;
 | 
			
		||||
import com.silverwrist.venice.db.UserNameRewriter;
 | 
			
		||||
 | 
			
		||||
public class RenderData
 | 
			
		||||
{
 | 
			
		||||
@ -128,6 +131,12 @@ public class RenderData
 | 
			
		||||
 | 
			
		||||
  } // end getFullImagePath
 | 
			
		||||
 | 
			
		||||
  public String getStaticFilePath(String name)
 | 
			
		||||
  {
 | 
			
		||||
    return rconf.getStaticFilePath(name);
 | 
			
		||||
 | 
			
		||||
  } // end getStaticFilePath
 | 
			
		||||
 | 
			
		||||
  public String getFormatJSPPath(String name)
 | 
			
		||||
  {
 | 
			
		||||
    return "/format/" + name;
 | 
			
		||||
@ -320,4 +329,87 @@ public class RenderData
 | 
			
		||||
 | 
			
		||||
  } // end sendBinaryData
 | 
			
		||||
 | 
			
		||||
  public String rewritePostData(String data)
 | 
			
		||||
  {
 | 
			
		||||
    if ((data.indexOf(PostLinkRewriter.URI_PREFIX)<0) && (data.indexOf(UserNameRewriter.URI_PREFIX)<0))
 | 
			
		||||
      return data;
 | 
			
		||||
 | 
			
		||||
    StringBuffer buf = new StringBuffer();
 | 
			
		||||
    String interm;
 | 
			
		||||
 | 
			
		||||
    if (data.indexOf(PostLinkRewriter.URI_PREFIX)>=0)
 | 
			
		||||
    { // begin replacing everything with post links
 | 
			
		||||
      String t = data;
 | 
			
		||||
      int p = t.indexOf(PostLinkRewriter.URI_PREFIX);
 | 
			
		||||
      while (p>=0)
 | 
			
		||||
      { // break off the start of the string
 | 
			
		||||
	if (p>0)
 | 
			
		||||
	  buf.append(t.substring(0,p));
 | 
			
		||||
	t = t.substring(p + PostLinkRewriter.URI_PREFIX.length());
 | 
			
		||||
 | 
			
		||||
	// find the end of the post link...
 | 
			
		||||
	p = 0;
 | 
			
		||||
	while (IDUtils.isValidPostLinkChar(t.charAt(p)))
 | 
			
		||||
	  p++;
 | 
			
		||||
 | 
			
		||||
	if (p>0)
 | 
			
		||||
	{ // append the post link to the "go" servlet path, and encode the lot
 | 
			
		||||
	  buf.append(getEncodedServletPath("go/" + t.substring(0,p)));
 | 
			
		||||
	  t = t.substring(p);
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
	else  // false alarm
 | 
			
		||||
	  buf.append(PostLinkRewriter.URI_PREFIX);
 | 
			
		||||
 | 
			
		||||
	// and now look again...
 | 
			
		||||
	p = t.indexOf(PostLinkRewriter.URI_PREFIX);
 | 
			
		||||
 | 
			
		||||
      } // end while
 | 
			
		||||
 | 
			
		||||
      buf.append(t);
 | 
			
		||||
      interm = buf.toString();
 | 
			
		||||
      buf.setLength(0);
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
    else  // no post link strings, this is the intermediate form
 | 
			
		||||
      interm = data;
 | 
			
		||||
 | 
			
		||||
    if (interm.indexOf(UserNameRewriter.URI_PREFIX)>=0)
 | 
			
		||||
    { // begin replacing everything with user links
 | 
			
		||||
      String t = interm;
 | 
			
		||||
      int p = t.indexOf(UserNameRewriter.URI_PREFIX);
 | 
			
		||||
      while (p>=0)
 | 
			
		||||
      { // break off the start of the string
 | 
			
		||||
	if (p>0)
 | 
			
		||||
	  buf.append(t.substring(0,p));
 | 
			
		||||
	t = t.substring(p + UserNameRewriter.URI_PREFIX.length());
 | 
			
		||||
 | 
			
		||||
	// find the end of the user link...
 | 
			
		||||
	p = 0;
 | 
			
		||||
	while (IDUtils.isValidVeniceIDChar(t.charAt(p)))
 | 
			
		||||
	  p++;
 | 
			
		||||
 | 
			
		||||
	if (p>0)
 | 
			
		||||
	{ // append the post link to the "user" servlet path, and encode the lot
 | 
			
		||||
	  buf.append(getEncodedServletPath("user/" + t.substring(0,p)));
 | 
			
		||||
	  t = t.substring(p);
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
	else  // false alarm
 | 
			
		||||
	  buf.append(UserNameRewriter.URI_PREFIX);
 | 
			
		||||
 | 
			
		||||
	// and now look again...
 | 
			
		||||
	p = t.indexOf(UserNameRewriter.URI_PREFIX);
 | 
			
		||||
 | 
			
		||||
      } // end while
 | 
			
		||||
 | 
			
		||||
      buf.append(t);
 | 
			
		||||
      return buf.toString();
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
    else  // no more to find - just return this
 | 
			
		||||
      return interm;
 | 
			
		||||
 | 
			
		||||
  } // end rewritePostData
 | 
			
		||||
 | 
			
		||||
} // end class RenderData
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,7 @@ public class TopicPosts implements JSPRender
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private VeniceEngine engine;
 | 
			
		||||
  private SIGContext sig;
 | 
			
		||||
  private ConferenceContext conf;
 | 
			
		||||
  private TopicContext topic;
 | 
			
		||||
@ -47,6 +48,7 @@ public class TopicPosts implements JSPRender
 | 
			
		||||
  private int unread;
 | 
			
		||||
  private List messages;
 | 
			
		||||
  private TopicVisitOrder visit_order;
 | 
			
		||||
  private String topic_stem;
 | 
			
		||||
  private String cache_locator = null;
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
@ -54,10 +56,11 @@ public class TopicPosts implements JSPRender
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public TopicPosts(HttpServletRequest request, SIGContext sig, ConferenceContext conf, TopicContext topic,
 | 
			
		||||
		    int first, int last, boolean read_new, boolean show_advanced)
 | 
			
		||||
  public TopicPosts(HttpServletRequest request, VeniceEngine engine, SIGContext sig, ConferenceContext conf,
 | 
			
		||||
		    TopicContext topic, int first, int last, boolean read_new, boolean show_advanced)
 | 
			
		||||
      throws DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    this.engine = engine;
 | 
			
		||||
    this.sig = sig;
 | 
			
		||||
    this.conf = conf;
 | 
			
		||||
    this.topic = topic;
 | 
			
		||||
@ -70,6 +73,8 @@ public class TopicPosts implements JSPRender
 | 
			
		||||
    this.messages = topic.getMessages(first,last);
 | 
			
		||||
    this.visit_order = TopicVisitOrder.retrieve(request.getSession(true),conf.getConfID());
 | 
			
		||||
    visit_order.visit(topic.getTopicNumber());
 | 
			
		||||
    List aliases = conf.getAliases();
 | 
			
		||||
    topic_stem = (String)(aliases.get(0)) + "." + String.valueOf(topic.getTopicNumber()) + ".";
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
 | 
			
		||||
@ -192,6 +197,14 @@ public class TopicPosts implements JSPRender
 | 
			
		||||
 | 
			
		||||
  } // end getNextLocator
 | 
			
		||||
 | 
			
		||||
  public String getRestoreLocator()
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer buf = new StringBuffer("rtop=");
 | 
			
		||||
    buf.append(topic.getTopicNumber()).append("&rct=").append(unread);
 | 
			
		||||
    return buf.toString();
 | 
			
		||||
 | 
			
		||||
  } // end getRestoreLocator
 | 
			
		||||
 | 
			
		||||
  public String getIdentifyingData()
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer buf = new StringBuffer("Posts ");
 | 
			
		||||
@ -262,7 +275,7 @@ public class TopicPosts implements JSPRender
 | 
			
		||||
 | 
			
		||||
  public boolean canDeleteTopic()
 | 
			
		||||
  {
 | 
			
		||||
    return false;  // TODO: fix me
 | 
			
		||||
    return topic.canDelete();
 | 
			
		||||
 | 
			
		||||
  } // end canDeleteTopic
 | 
			
		||||
 | 
			
		||||
@ -274,7 +287,7 @@ public class TopicPosts implements JSPRender
 | 
			
		||||
 | 
			
		||||
  public String getScrollUpLocator()
 | 
			
		||||
  {
 | 
			
		||||
    int new_first = first - 20;  // TODO: configurable
 | 
			
		||||
    int new_first = first - engine.getNumPostsPerPage();
 | 
			
		||||
    int new_last = last - 1;
 | 
			
		||||
    if (new_first<0)
 | 
			
		||||
    { // normalize so we start at 0
 | 
			
		||||
@ -291,14 +304,14 @@ public class TopicPosts implements JSPRender
 | 
			
		||||
 | 
			
		||||
  public boolean canScrollDown()
 | 
			
		||||
  {
 | 
			
		||||
    return ((topic.getTotalMessages() - (1 + last))>=20); // TODO: configurable
 | 
			
		||||
    return ((topic.getTotalMessages() - (1 + last))>=engine.getNumPostsPerPage());
 | 
			
		||||
 | 
			
		||||
  } // end canScrollDown
 | 
			
		||||
 | 
			
		||||
  public String getScrollDownLocator()
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer buf = new StringBuffer("p1=");
 | 
			
		||||
    buf.append(last+1).append("&p2=").append(last+20);  // TODO: configurable
 | 
			
		||||
    buf.append(last+1).append("&p2=").append(last+engine.getNumPostsPerPage());
 | 
			
		||||
    return buf.toString();
 | 
			
		||||
 | 
			
		||||
  } // end getScrollDownLocator
 | 
			
		||||
@ -313,7 +326,7 @@ public class TopicPosts implements JSPRender
 | 
			
		||||
  {
 | 
			
		||||
    int my_last = topic.getTotalMessages();
 | 
			
		||||
    StringBuffer buf = new StringBuffer("p1=");
 | 
			
		||||
    buf.append(my_last-20).append("&p2=").append(my_last-1);  // TODO: configurable
 | 
			
		||||
    buf.append(my_last-engine.getNumPostsPerPage()).append("&p2=").append(my_last-1);
 | 
			
		||||
    return buf.toString();
 | 
			
		||||
 | 
			
		||||
  } // end getScrollToEndLocator
 | 
			
		||||
@ -351,4 +364,16 @@ public class TopicPosts implements JSPRender
 | 
			
		||||
 | 
			
		||||
  } // end getDefaultPseud
 | 
			
		||||
 | 
			
		||||
  public String getMessageReference(TopicMessageContext msg)
 | 
			
		||||
  {
 | 
			
		||||
    return topic_stem + String.valueOf(msg.getPostNumber());
 | 
			
		||||
 | 
			
		||||
  } // end getMessageReference
 | 
			
		||||
 | 
			
		||||
  public int getNumPostsPerPage()
 | 
			
		||||
  {
 | 
			
		||||
    return engine.getNumPostsPerPage();
 | 
			
		||||
 | 
			
		||||
  } // end getNumPostsPerPage
 | 
			
		||||
 | 
			
		||||
} // end class TopicPosts
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,7 @@
 | 
			
		||||
      There were <%= data.getNumSpellingErrors() %> spelling errors in your post.
 | 
			
		||||
    <% } // end if %>
 | 
			
		||||
  </B></FONT>
 | 
			
		||||
  <P><PRE><%= data.getPreviewData() %></PRE><HR>
 | 
			
		||||
  <P><PRE><%= rdat.rewritePostData(data.getPreviewData()) %></PRE><HR>
 | 
			
		||||
<% } // end if %>
 | 
			
		||||
 | 
			
		||||
<FORM METHOD="POST" ACTION="<%= rdat.getEncodedServletPath("confops") %>">
 | 
			
		||||
@ -59,7 +59,7 @@
 | 
			
		||||
    <TR>
 | 
			
		||||
      <TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>Message:</FONT></TD>
 | 
			
		||||
      <TD ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
        <A HREF="TODO" TARGET="_blank">HTML Guide</A>
 | 
			
		||||
        <A HREF="<%= rdat.getStaticFilePath("html-reference.html") %>" TARGET="_blank">HTML Guide</A>
 | 
			
		||||
      </FONT></TD>
 | 
			
		||||
    </TR>
 | 
			
		||||
    <TR><TD ALIGN=LEFT COLSPAN=2>
 | 
			
		||||
 | 
			
		||||
@ -47,11 +47,11 @@
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
        
 | 
			
		||||
      <% if (data.isTopicHidden()) { %>
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("topicops?" + data.getLocator() + "&cmd=HN") %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_show_topic.gif") %>" ALT="Show Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
      <% } else { %>
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("topicops?" + data.getLocator() + "&cmd=HY") %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_hide_topic.gif") %>" ALT="Hide Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
@ -62,8 +62,8 @@
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
          
 | 
			
		||||
        <% if (data.getNewMessages()>0) { %>
 | 
			
		||||
          <%-- TODO: this doesn't do Keep New yet --%>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getNextLocator() + "&rnm=1") %>"><IMG
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getNextLocator() + "&"
 | 
			
		||||
                                                  + data.getRestoreLocator() + "&rnm=1") %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_next_keep_new.gif") %>" ALT="Next & Keep New" WIDTH=80 HEIGHT=24
 | 
			
		||||
           BORDER=0></A>
 | 
			
		||||
            
 | 
			
		||||
@ -75,11 +75,11 @@
 | 
			
		||||
      <% if (data.canFreezeTopic()) { %>
 | 
			
		||||
          
 | 
			
		||||
        <% if (data.isTopicFrozen()) { %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("topicops?" + data.getLocator() + "&cmd=FN") %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_unfreeze_topic.gif") %>" ALT="Unfreeze Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
           BORDER=0></A>
 | 
			
		||||
        <% } else { %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("topicops?" + data.getLocator() + "&cmd=FY") %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_freeze_topic.gif") %>" ALT="Freeze Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
           BORDER=0></A>
 | 
			
		||||
        <% } // end if %>
 | 
			
		||||
@ -87,18 +87,18 @@
 | 
			
		||||
      <% if (data.canArchiveTopic()) { %>
 | 
			
		||||
          
 | 
			
		||||
        <% if (data.isTopicArchived()) { %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("topicops?" + data.getLocator() + "&cmd=AN") %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_unarchive_topic.gif") %>" ALT="Unarchive Topic" WIDTH=80
 | 
			
		||||
           HEIGHT=24 BORDER=0></A>
 | 
			
		||||
        <% } else { %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("topicops?" + data.getLocator() + "&cmd=AY") %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_archive_topic.gif") %>" ALT="Archive Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
           BORDER=0></A>
 | 
			
		||||
        <% } // end if %>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
      <% if (data.canDeleteTopic()) { %>
 | 
			
		||||
          
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("topicops?" + data.getLocator() + "&cmd=DEL") %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_delete_topic.gif") %>" ALT="Delete Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
@ -119,18 +119,17 @@
 | 
			
		||||
    </TD>
 | 
			
		||||
    <TD NOWRAP ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
      <% if (rdat.useHTMLComments()) { %><!-- Upper navigation linkset --><% } %>
 | 
			
		||||
      <%-- TODO: the number "20" should be configurable --%>
 | 
			
		||||
      <A NAME="top">[</A> 
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&p1=0&p2=-1") %>">View All</A>
 | 
			
		||||
      <% if (data.canScrollUp()) { %>
 | 
			
		||||
         | 
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&"
 | 
			
		||||
                                                + data.getScrollUpLocator()) %>">Scroll Up 20</A>
 | 
			
		||||
                    + data.getScrollUpLocator()) %>">Scroll Up <%= data.getNumPostsPerPage() %></A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
      <% if (data.canScrollDown()) { %>
 | 
			
		||||
         | 
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&"
 | 
			
		||||
                                                + data.getScrollDownLocator()) %>">Scroll Down 20</A>
 | 
			
		||||
                 + data.getScrollDownLocator()) %>">Scroll Down <%= data.getNumPostsPerPage() %></A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
      <% if (data.canScrollDown()) { %>
 | 
			
		||||
         | 
 | 
			
		||||
@ -165,7 +164,11 @@
 | 
			
		||||
    <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&shac=1&p1="
 | 
			
		||||
                               + String.valueOf(msg.getPostNumber())) %>"><%= msg.getPostNumber() %></A> of
 | 
			
		||||
    <A HREF="<%= last_post %>"><%= data.getTotalMessages() - 1 %></A>
 | 
			
		||||
    <%= rdat.getStdFontTag(null,1) %><<%= "TODO" %>></FONT><BR>
 | 
			
		||||
    <%= rdat.getStdFontTag(null,1) %><<%= data.getMessageReference(msg) %>></FONT>
 | 
			
		||||
    <% if (data.showAdvanced() && msg.isHidden()) { %>
 | 
			
		||||
      <B><EM>(Hidden)</EM></B>
 | 
			
		||||
    <% } // end if %>
 | 
			
		||||
    <BR>
 | 
			
		||||
    <B><%= msg.getPseud() %></B>
 | 
			
		||||
    (<EM>
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("user/" + poster) %>" TARGET="_blank"><%= poster %></A>,
 | 
			
		||||
@ -183,36 +186,37 @@
 | 
			
		||||
    <TT><EM><B>
 | 
			
		||||
      (Scribbled by <%= data.getMessageBodyText(msg) %> on
 | 
			
		||||
      <%= rdat.formatDateForDisplay(msg.getScribbleDate()) %>)
 | 
			
		||||
    </B></EM></TT>
 | 
			
		||||
    </B></EM></TT><P>
 | 
			
		||||
  <% } else if (msg.isHidden() && !(data.showAdvanced())) { %>
 | 
			
		||||
    <TT><EM><B>
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&shac=1&p1="
 | 
			
		||||
                                              + String.valueOf(msg.getPostNumber())) %>">(Hidden
 | 
			
		||||
      Message: <%= msg.getNumLines() %> <% if (msg.getNumLines()==1) { %>Line<% } else { %>Lines<% } %></A>
 | 
			
		||||
    </B></EM></TT>
 | 
			
		||||
      Message: <%= msg.getNumLines() %> <% if (msg.getNumLines()==1) { %>Line<% } else { %>Lines<% } %>)</A>
 | 
			
		||||
    </B></EM></TT><P>
 | 
			
		||||
  <% } else { %>
 | 
			
		||||
    <PRE><%= data.getMessageBodyText(msg) %></PRE>
 | 
			
		||||
    <PRE><%= rdat.rewritePostData(data.getMessageBodyText(msg)) %></PRE>
 | 
			
		||||
  <% } // end if %>
 | 
			
		||||
  <% if (data.showAdvanced()) { %>
 | 
			
		||||
    <% String po_loc = data.getLocator() + "&msg=" + String.valueOf(msg.getPostNumber()); %>
 | 
			
		||||
    </TD><TD NOWRAP ALIGN=RIGHT>
 | 
			
		||||
      <% if (!(msg.isScribbled())) { %>
 | 
			
		||||
        <% if (msg.canHide()) { %>
 | 
			
		||||
          <% if (msg.isHidden()) { %>
 | 
			
		||||
            <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
            <A HREF="<%= rdat.getEncodedServletPath("postops?" + po_loc + "&cmd=HN") %>"><IMG
 | 
			
		||||
             SRC="<%= rdat.getFullImagePath("bn_show.gif") %>" ALT="Show" WIDTH=80 HEIGHT=24 BORDER=0></A><P>
 | 
			
		||||
          <% } else { %>
 | 
			
		||||
            <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
            <A HREF="<%= rdat.getEncodedServletPath("postops?" + po_loc + "&cmd=HY") %>"><IMG
 | 
			
		||||
             SRC="<%= rdat.getFullImagePath("bn_hide.gif") %>" ALT="Hide" WIDTH=80 HEIGHT=24 BORDER=0></A><P>
 | 
			
		||||
          <% } // end if %>
 | 
			
		||||
        <% } // end if (can hide) %> 
 | 
			
		||||
        <% if (msg.canScribble()) { %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("postops?" + po_loc + "&cmd=SCR") %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_scribble.gif") %>" ALT="Scribble" WIDTH=80 HEIGHT=24
 | 
			
		||||
           BORDER=0></A><P>
 | 
			
		||||
        <% } // end if (can scribble) %> 
 | 
			
		||||
      <% } // end if (not already scribbled) %> 
 | 
			
		||||
      <% if (msg.canNuke()) { %>
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("postops?" + po_loc + "&cmd=NUKE") %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_nuke.gif") %>" ALT="Nuke" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A><P>
 | 
			
		||||
      <% } // end if (can nuke) %> 
 | 
			
		||||
@ -227,18 +231,17 @@
 | 
			
		||||
    <TD NOWRAP ALIGN=LEFT> </TD>
 | 
			
		||||
    <TD NOWRAP ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
      <% if (rdat.useHTMLComments()) { %><!-- Upper navigation linkset --><% } %>
 | 
			
		||||
      <%-- TODO: the number "20" should be configurable --%>
 | 
			
		||||
      <A NAME="bottom">[</A> 
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&p1=0&p2=-1") %>">View All</A>
 | 
			
		||||
      <% if (data.canScrollUp()) { %>
 | 
			
		||||
         | 
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&"
 | 
			
		||||
                                                + data.getScrollUpLocator()) %>">Scroll Up 20</A>
 | 
			
		||||
                   + data.getScrollUpLocator()) %>">Scroll Up <%= data.getNumPostsPerPage() %></A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
      <% if (data.canScrollDown()) { %>
 | 
			
		||||
         | 
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&"
 | 
			
		||||
                                                + data.getScrollDownLocator()) %>">Scroll Down 20</A>
 | 
			
		||||
               + data.getScrollDownLocator()) %>">Scroll Down <%= data.getNumPostsPerPage() %></A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
      <% if (data.canScrollDown()) { %>
 | 
			
		||||
         | 
 | 
			
		||||
@ -258,11 +261,11 @@
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
        
 | 
			
		||||
      <% if (data.isTopicHidden()) { %>
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("topicops?" + data.getLocator() + "&cmd=HN") %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_show_topic.gif") %>" ALT="Show Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
      <% } else { %>
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("topicops?" + data.getLocator() + "&cmd=HY") %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_hide_topic.gif") %>" ALT="Hide Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
@ -273,8 +276,8 @@
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
          
 | 
			
		||||
        <% if (data.getNewMessages()>0) { %>
 | 
			
		||||
          <%-- TODO: this doesn't do Keep New yet --%>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getNextLocator() + "&rnm=1") %>"><IMG
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getNextLocator() + "&"
 | 
			
		||||
                                                  + data.getRestoreLocator() + "&rnm=1") %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_next_keep_new.gif") %>" ALT="Next & Keep New" WIDTH=80 HEIGHT=24
 | 
			
		||||
           BORDER=0></A>
 | 
			
		||||
            
 | 
			
		||||
@ -305,7 +308,7 @@
 | 
			
		||||
      <TR>
 | 
			
		||||
        <TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>Message:</FONT></TD>
 | 
			
		||||
        <TD ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
          <A HREF="TODO" TARGET="_blank">HTML Guide</A>
 | 
			
		||||
          <A HREF="<%= rdat.getStaticFilePath("html-reference.html") %>" TARGET="_blank">HTML Guide</A>
 | 
			
		||||
        </FONT></TD>
 | 
			
		||||
      </TR>
 | 
			
		||||
      <TR><TD ALIGN=LEFT COLSPAN=2>
 | 
			
		||||
 | 
			
		||||
@ -35,7 +35,7 @@
 | 
			
		||||
    There were <%= data.getNumSpellingErrors() %> spelling errors in your post.
 | 
			
		||||
  <% } // end if %>
 | 
			
		||||
</B></FONT>
 | 
			
		||||
<P><PRE><%= data.getPreviewData() %></PRE><HR>
 | 
			
		||||
<P><PRE><%= rdat.rewritePostData(data.getPreviewData()) %></PRE><HR>
 | 
			
		||||
 | 
			
		||||
<FORM METHOD="POST" ACTION="<%= rdat.getEncodedServletPath("post") %>">
 | 
			
		||||
  <INPUT TYPE="HIDDEN" NAME="sig" VALUE="<%= data.getSIGID() %>">
 | 
			
		||||
@ -55,7 +55,7 @@
 | 
			
		||||
    <TR>
 | 
			
		||||
      <TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>Message:</FONT></TD>
 | 
			
		||||
      <TD ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
        <A HREF="TODO" TARGET="_blank">HTML Guide</A>
 | 
			
		||||
        <A HREF="<%= rdat.getStaticFilePath("html-reference.html") %>" TARGET="_blank">HTML Guide</A>
 | 
			
		||||
      </FONT></TD>
 | 
			
		||||
    </TR>
 | 
			
		||||
    <TR><TD ALIGN=LEFT COLSPAN=2>
 | 
			
		||||
 | 
			
		||||
@ -41,7 +41,7 @@
 | 
			
		||||
  %>
 | 
			
		||||
  <%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
    <B><%= msg.getPostNumber() %></B> of <B><%= data.getTotalMessages() - 1 %></B>
 | 
			
		||||
    <%= rdat.getStdFontTag(null,1) %><<%= "TODO" %>></FONT><BR>
 | 
			
		||||
    <%= rdat.getStdFontTag(null,1) %><<%= data.getMessageReference(msg) %>></FONT><BR>
 | 
			
		||||
    <B><%= msg.getPseud() %></B>
 | 
			
		||||
    (<EM>
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("user/" + poster) %>" TARGET="_blank"><%= poster %></A>,
 | 
			
		||||
@ -54,7 +54,7 @@
 | 
			
		||||
      <%= rdat.formatDateForDisplay(msg.getScribbleDate()) %>)
 | 
			
		||||
    </B></EM></TT>
 | 
			
		||||
  <% } else { %>
 | 
			
		||||
    <PRE><%= data.getMessageBodyText(msg) %></PRE>
 | 
			
		||||
    <PRE><%= rdat.rewritePostData(data.getMessageBodyText(msg)) %></PRE>
 | 
			
		||||
  <% } // end if %>
 | 
			
		||||
<% } // end while %>
 | 
			
		||||
<% if (rdat.useHTMLComments()) { %><!-- End Slipped Messages --><% } %>
 | 
			
		||||
@ -79,7 +79,7 @@
 | 
			
		||||
    <TR>
 | 
			
		||||
      <TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>Message:</FONT></TD>
 | 
			
		||||
      <TD ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
        <A HREF="TODO" TARGET="_blank">HTML Guide</A>
 | 
			
		||||
        <A HREF="<%= rdat.getStaticFilePath("html-reference.html") %>" TARGET="_blank">HTML Guide</A>
 | 
			
		||||
      </FONT></TD>
 | 
			
		||||
    </TR>
 | 
			
		||||
    <TR><TD ALIGN=LEFT COLSPAN=2>
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,7 @@
 | 
			
		||||
  String tmp;
 | 
			
		||||
%>
 | 
			
		||||
<% if (rdat.useHTMLComments()) { %><!-- Topic list for conf #<%= data.getConfID() %> --><% } %>
 | 
			
		||||
<% rdat.writeContentHeader(out,data.getConfName() + " Topics",null); %>
 | 
			
		||||
<% rdat.writeContentHeader(out,"Topics in " + data.getConfName(),null); %>
 | 
			
		||||
<%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
  <DIV ALIGN="LEFT">
 | 
			
		||||
    <A HREF="<%= rdat.getEncodedServletPath("confops?sig=" + String.valueOf(data.getSIGID())) %>"><IMG
 | 
			
		||||
@ -40,7 +40,7 @@
 | 
			
		||||
                            WIDTH=80 HEIGHT=24 BORDER=0></A>  
 | 
			
		||||
    <% } // end if %>
 | 
			
		||||
    <% if (data.canDoReadNew()) { %>
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getNextLocator()) %>"><IMG
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getNextLocator() + "&rnm=1") %>"><IMG
 | 
			
		||||
       SRC="<%= rdat.getFullImagePath("bn_read_new.gif") %>" ALT="Read New" WIDTH=80 HEIGHT=24
 | 
			
		||||
       BORDER=0></A>  
 | 
			
		||||
    <% } // end if %>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1570
									
								
								web/static/html-reference.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-c0.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 109 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-c1.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-c2.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-c3.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-c4.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-c5.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-c6.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-c7.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-c8.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-c9.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-ca.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-cb.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-cc.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-cd.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-ce.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref-cf.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 151 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref32smi.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 943 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/images/ref64yr.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.0 KiB  |