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
This commit is contained in:
Eric J. Bowersox
2001-02-09 09:10:46 +00:00
parent 70774ead7d
commit a51fa644b7
58 changed files with 3326 additions and 123 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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)
*--------------------------------------------------------------------------------

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
*--------------------------------------------------------------------------------

View File

@@ -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

View File

@@ -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())

View File

@@ -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
*--------------------------------------------------------------------------------

View File

@@ -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

View File

@@ -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());

View File

@@ -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);

View File

@@ -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; "

View File

@@ -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

View 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

View 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

View File

@@ -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

View 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

View File

@@ -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();

View File

@@ -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();

View File

@@ -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

View File

@@ -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();

View File

@@ -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

View File

@@ -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