implemented front page content management, finally wired up the user locale

and timezone default mechanism, and did some other bugfixing and stuff
This commit is contained in:
Eric J. Bowersox 2001-02-28 07:55:00 +00:00
parent 129b69973b
commit 2e455b4bdd
37 changed files with 1555 additions and 109 deletions

5
TODO
View File

@ -17,11 +17,6 @@ Lots!
- Unimplemented functions on the Top page:
Customize Sideboxes
- The plan for the "main" part of the Top page is to let a sysadmin put
notices there by "publishing" selected conference messages to the front page.
We may include a welcome message up top to be displayed if the user's not
logged in.
- Slippage during posting is still untested.
- Not everybody likes purple. Provide a way to change the default colors.

View File

@ -1,5 +1,6 @@
advogato
ain't
anime
anla'shok
bajor
bios

View File

@ -50,4 +50,20 @@
<site-logo>http://delenn:8080/venice/images/powered-by-venice.gif</site-logo>
</paths>
<!-- Contains standard messages displayed by front end -->
<messages>
<!-- The message displayed at the top of "top" when you're not logged in -->
<welcome>
Welcome to the Venice Web Communities System. To get the most out of this site, you should log in or create
an account, using one of the links above.
</welcome>
<!-- The headline for the welcome message -->
<welcome-top>Welcome to Venice</welcome-top>
<!-- The headline for the "currents" box -->
<currents-top>Venice Currents</currents-top>
</messages>
</render-config>

View File

@ -1,4 +1,3 @@
# MySQL script for initializing the Venice database.
# Written by Eric J. Bowersox <erbo@silcom.com>
#---------------------------------------------------------------------------
@ -39,7 +38,8 @@ CREATE TABLE globals (
old_posts_at_top INT NOT NULL,
max_search_page INT NOT NULL,
max_sig_mbr_page INT NOT NULL,
max_conf_mbr_page INT NOT NULL
max_conf_mbr_page INT NOT NULL,
fp_posts INT NOT NULL
);
# The audit records table. Most "major" events add a record to this table.
@ -87,7 +87,7 @@ CREATE TABLE users (
CREATE TABLE userprefs (
uid INT NOT NULL PRIMARY KEY,
tzid VARCHAR(64) DEFAULT 'UTC',
localeid VARCHAR(64) DEFAULT 'en-US-'
localeid VARCHAR(64) DEFAULT 'en_US'
);
# Indicates what the top-level "sidebox" configuration is for any given user.
@ -377,6 +377,7 @@ CREATE TABLE postattach (
datalen INT,
filename VARCHAR(255),
mimetype VARCHAR(128),
stgmethod SMALLINT DEFAULT 0,
data MEDIUMBLOB
);
@ -387,6 +388,15 @@ CREATE TABLE postdogear (
PRIMARY KEY (uid, postid)
);
# "Front page" publishing table.
CREATE TABLE postpublish (
sigid INT NOT NULL,
postid BIGINT NOT NULL PRIMARY KEY,
by_uid INT NOT NULL,
on_date DATETIME NOT NULL,
INDEX display_order (on_date, postid)
);
##############################################################################
# Set table access rights
##############################################################################
@ -409,6 +419,7 @@ GRANT INSERT, DELETE, UPDATE, SELECT ON venice.*
# Types of audit records. This MUST be kept in sync with the constant definitions in
# com.silverwrist.venice.security.Audit!!!!
INSERT INTO refaudit (type, descr) VALUES
(1, 'Publish Message to Front Page'),
(101, 'Login OK'),
(102, 'Login Failure'),
(103, 'Account Created'),
@ -1312,8 +1323,9 @@ INSERT INTO refsigftr (ftr_code, is_default, is_locked, is_hidden, require_read,
##############################################################################
# Initialize the system globals table.
INSERT INTO globals (posts_per_page, old_posts_at_top, max_search_page, max_sig_mbr_page, max_conf_mbr_page)
VALUES (20, 2, 20, 50, 50);
INSERT INTO globals (posts_per_page, old_posts_at_top, max_search_page, max_sig_mbr_page, max_conf_mbr_page,
fp_posts)
VALUES (20, 2, 20, 50, 50, 10);
# Add the 'Anonymous Honyak' user to the users table.
# (Do 'SELECT * FROM users WHERE is_anon = 1' to retrieve the AC user details.)

View File

@ -0,0 +1,62 @@
/*
* 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.util;
import java.util.*;
public class LocaleFactory
{
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
private LocaleFactory()
{ // this object cannot be instantiated
} // end constructor
/*--------------------------------------------------------------------------------
* External static operations
*--------------------------------------------------------------------------------
*/
public static Locale createLocale(String streq)
{
if ((streq==null) || (streq.length()==0))
return Locale.getDefault();
int p1 = streq.indexOf('_');
if (p1<0)
return new Locale(streq,"");
String x_lang = streq.substring(0,p1);
int p2 = streq.indexOf('_',p1+1);
if (p2<0)
{ // there's only one underscore - figure out what part the last part is
String lastpart = streq.substring(p1+1);
if (lastpart.length()==2)
return new Locale(streq.substring(0,p1),lastpart);
else
return new Locale(streq.substring(0,p1),"",lastpart);
} // end if
// do all three variants
return new Locale(streq.substring(0,p1),streq.substring(p1+1,p2),streq.substring(p2+1));
} // end createLocale
} // end class LocaleFactory

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
@ -73,4 +73,8 @@ public interface TopicMessageContext
public abstract void attachData(String m_type, String file, int length, InputStream data)
throws AccessError, DataException;
public abstract boolean canPublish();
public abstract void publish() throws DataException, AccessError;
} // end interface TopicMessageContext

View File

@ -18,6 +18,8 @@
package com.silverwrist.venice.core;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
public interface UserContext extends SearchMode
{
@ -93,4 +95,12 @@ public interface UserContext extends SearchMode
public abstract AdminOperations getAdminInterface() throws AccessError;
public abstract Locale getLocale() throws DataException;
public abstract void setLocale(Locale locale) throws DataException;
public abstract TimeZone getTimeZone() throws DataException;
public abstract void setTimeZone(TimeZone timezone) throws DataException;
} // end interface UserContext

View File

@ -73,4 +73,6 @@ public interface VeniceEngine extends SearchMode
public abstract List getMasterSideBoxList();
public abstract List getPublishedMessages(boolean all) throws DataException;
} // end interface VeniceEngine

View File

@ -37,6 +37,7 @@ class BackgroundConferencePurge implements Runnable
*--------------------------------------------------------------------------------
*/
private EngineBackend engine;
private DataPool datapool;
private int confid;
private int num_topics;
@ -47,8 +48,10 @@ class BackgroundConferencePurge implements Runnable
*--------------------------------------------------------------------------------
*/
BackgroundConferencePurge(DataPool datapool, int confid, int num_topics, int max_topicid)
BackgroundConferencePurge(EngineBackend engine, DataPool datapool, int confid, int num_topics,
int max_topicid)
{
this.engine = engine;
this.datapool = datapool;
this.confid = confid;
this.num_topics = num_topics;
@ -100,7 +103,7 @@ class BackgroundConferencePurge implements Runnable
rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
throw new InternalStateError("BackgroundConferencePurge.run screwup on post SELECT");
rq.queue(new BackgroundTopicPurge(datapool,topicids[i],rs.getInt(1),rs.getLong(2)));
rq.queue(new BackgroundTopicPurge(engine,datapool,topicids[i],rs.getInt(1),rs.getLong(2)));
} // end for

View File

@ -39,6 +39,7 @@ class BackgroundSIGPurge implements Runnable
*--------------------------------------------------------------------------------
*/
private EngineBackend engine;
private DataPool datapool;
private UserBackend user;
private int sigid;
@ -51,9 +52,10 @@ class BackgroundSIGPurge implements Runnable
*--------------------------------------------------------------------------------
*/
BackgroundSIGPurge(DataPool datapool, UserBackend user, int sigid, int num_confs, int max_confid,
Hashtable conf_objects)
BackgroundSIGPurge(EngineBackend engine, DataPool datapool, UserBackend user, int sigid, int num_confs,
int max_confid, Hashtable conf_objects)
{
this.engine = engine;
this.datapool = datapool;
this.user = user;
this.sigid = sigid;
@ -137,7 +139,7 @@ class BackgroundSIGPurge implements Runnable
rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
throw new InternalStateError("BackgroundSIGPurge.run screwup on conference SELECT");
rq.queue(new BackgroundConferencePurge(datapool,key.intValue(),rs.getInt(1),rs.getInt(2)));
rq.queue(new BackgroundConferencePurge(engine,datapool,key.intValue(),rs.getInt(1),rs.getInt(2)));
} // end if (have to delete conference data)

View File

@ -35,6 +35,7 @@ class BackgroundTopicPurge implements Runnable
*--------------------------------------------------------------------------------
*/
private EngineBackend engine;
private DataPool datapool;
private int topicid;
private int num_posts;
@ -45,8 +46,9 @@ class BackgroundTopicPurge implements Runnable
*--------------------------------------------------------------------------------
*/
BackgroundTopicPurge(DataPool datapool, int topicid, int num_posts, long max_postid)
BackgroundTopicPurge(EngineBackend engine, DataPool datapool, int topicid, int num_posts, long max_postid)
{
this.engine = engine;
this.datapool = datapool;
this.topicid = topicid;
this.num_posts = num_posts;
@ -62,7 +64,7 @@ class BackgroundTopicPurge implements Runnable
public void run()
{
if (logger.isDebugEnabled())
logger.debug("BackgroundTopicPurge running on topic #" + String.valueOf(topicid));
logger.debug("BackgroundTopicPurge running on topic #" + topicid);
long[] postids = new long[num_posts]; // stores the post IDs
Connection conn = null; // pooled database connection
@ -82,22 +84,23 @@ class BackgroundTopicPurge implements Runnable
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]) + ";");
stmt.executeUpdate("DELETE FROM posts WHERE postid = " + postids[i] + ";");
stmt.executeUpdate("DELETE FROM postdata WHERE postid = " + postids[i] + ";");
stmt.executeUpdate("DELETE FROM postattach WHERE postid = " + postids[i] + ";");
stmt.executeUpdate("DELETE FROM postdogear WHERE postid = " + postids[i] + ";");
if (stmt.executeUpdate("DELETE FROM postpublish WHERE postid = " + postids[i] + ";")>0)
engine.unpublish(postids[i]);
} // end for
// all done, Bunky!
if (logger.isDebugEnabled())
logger.debug("BackgroundTopicPurge complete for topic #" + String.valueOf(topicid));
logger.debug("BackgroundTopicPurge complete for topic #" + topicid);
} // end try
catch (SQLException e)
{ // on an error, just die
logger.error("BackgroundTopicPurge FATAL EXCEPTION purging #" + String.valueOf(topicid) + ": "
+ e.getMessage(),e);
logger.error("BackgroundTopicPurge FATAL EXCEPTION purging #" + topicid + ": " + e.getMessage(),e);
} // end catch
finally

View File

@ -1238,7 +1238,8 @@ class ConferenceCoreData implements ConferenceData
} // end finally
// Delete the rest of the gunk in the background; spin off another thread to handle it.
BackgroundConferencePurge purger = new BackgroundConferencePurge(datapool,confid,topic_count,topic_max);
BackgroundConferencePurge purger = new BackgroundConferencePurge(engine,datapool,confid,topic_count,
topic_max);
Thread thrd = new Thread(purger);
thrd.setPriority(Thread.NORM_PRIORITY-1);
thrd.start();

View File

@ -789,7 +789,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
else
{ // need to insert a confsettings row
sql.append("INSERT INTO confsettings (confid, uid, default_pseud) VALUES (").append(confid);
sql.append(", ").append(sig.realUID()).append(", '").append(SQLUtil.encodeString(val)).append("';");
sql.append(", ").append(sig.realUID()).append(", '").append(SQLUtil.encodeString(val)).append("');");
} // end else

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
@ -19,12 +19,24 @@ package com.silverwrist.venice.core.impl;
import java.sql.*;
import java.util.*;
import org.apache.log4j.*;
import com.silverwrist.venice.core.*;
import com.silverwrist.venice.db.*;
class ContactInfoImpl implements ContactInfo, Stashable
{
// Attributes
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Category logger = Category.getInstance(ContactInfoImpl.class.getName());
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private int contactid; // ID of this contact record (-1 = new)
private String given_name; // given name ("first name")
private String family_name; // family name ("last name")
@ -53,6 +65,11 @@ class ContactInfoImpl implements ContactInfo, Stashable
private java.util.Date last_update; // date of last update
private boolean is_modified = false; // have we modified this ContactInfo?
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
/**
* Constructs a new blank <CODE>ContactInfoImpl</CODE> object.
*
@ -60,6 +77,8 @@ class ContactInfoImpl implements ContactInfo, Stashable
*/
ContactInfoImpl(int owner_uid)
{
if (logger.isDebugEnabled())
logger.debug("new ContactInfoImpl (empty) for UID = " + owner_uid);
makeEmpty(owner_uid,-1);
} // end constructor
@ -72,6 +91,8 @@ class ContactInfoImpl implements ContactInfo, Stashable
*/
ContactInfoImpl(int owner_uid, int owner_sigid)
{
if (logger.isDebugEnabled())
logger.debug("new ContactInfoImpl (empty) for UID = " + owner_uid + ", SIGID = " + owner_sigid);
makeEmpty(owner_uid,owner_sigid);
} // end constructor
@ -85,6 +106,8 @@ class ContactInfoImpl implements ContactInfo, Stashable
*/
ContactInfoImpl(DataPool dp, int contactid) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("new ContactInfoImpl (loading CID " + contactid + ")");
Connection conn = null;
try
@ -95,6 +118,7 @@ class ContactInfoImpl implements ContactInfo, Stashable
} // end try
catch (SQLException e)
{ // turn SQLExceptions at this level into DataExceptions
logger.error("DB error loading contact ID " + contactid + ": " + e.getMessage(),e);
throw new DataException("Unable to look up contact info: " + e.getMessage(),e);
} // end catch
@ -107,6 +131,11 @@ class ContactInfoImpl implements ContactInfo, Stashable
} // end constructor
/*--------------------------------------------------------------------------------
* Internal functions
*--------------------------------------------------------------------------------
*/
private void makeEmpty(int owner_uid, int owner_sigid)
{
this.contactid = -1;
@ -180,18 +209,28 @@ class ContactInfoImpl implements ContactInfo, Stashable
last_update = SQLUtil.getFullDateTime(rs,"lastupdate");
} // end if
else // contact was not found
else
{ // contact was not found
logger.error("contact ID " + contactid + " not found in database");
throw new DataException("Contact was not found.");
} // end else
} // end try
catch (SQLException e)
{ // map all SQLExceptions into DataExceptions
logger.error("DB error loading contact ID " + contactid + ": " + e.getMessage(),e);
throw new DataException("Unable to look up contact info: " + e.getMessage(),e);
} // end catch
} // end loadData
/*--------------------------------------------------------------------------------
* Implementations from interface ContactInfo
*--------------------------------------------------------------------------------
*/
public int getContactID()
{
return contactid;
@ -559,6 +598,11 @@ class ContactInfoImpl implements ContactInfo, Stashable
} // end getModified
/*--------------------------------------------------------------------------------
* Implementations from interface Stashable
*--------------------------------------------------------------------------------
*/
public int getStashableUID()
{
return getOwnerUID();
@ -567,6 +611,8 @@ class ContactInfoImpl implements ContactInfo, Stashable
public void stash(Connection conn) throws DataException, SQLException
{
if (logger.isDebugEnabled())
logger.debug("stashing contact ID " + contactid);
java.util.Date update = null;
Statement stmt = conn.createStatement();
StringBuffer buf;
@ -653,10 +699,19 @@ class ContactInfoImpl implements ContactInfo, Stashable
int new_contactid;
ResultSet rs = stmt.executeQuery("SELECT LAST_INSERT_ID();");
if (rs.next())
{ // found the contact ID...
new_contactid = rs.getInt(1);
if (logger.isDebugEnabled())
logger.debug("created new contact ID " + new_contactid);
} // end if
else
{ // error reading back the contact ID
logger.error("unable to read back contact ID");
throw new DataException("unable to read back new contact ID");
} // end else
// and patch the database table so we know what our contact ID is
buf.setLength(0);
if (owner_sigid>=0)

View File

@ -36,6 +36,7 @@ public interface EngineBackend
public static final int IP_MAXSEARCHRETURN = 2;
public static final int IP_MAXSIGMEMBERDISPLAY = 3;
public static final int IP_MAXCONFMEMBERDISPLAY = 4;
public static final int IP_NUMFRONTPAGEPOSTS = 5;
public abstract SimpleEmailer createEmailer();
@ -83,4 +84,10 @@ public interface EngineBackend
public abstract SideBoxDescriptor getMasterSideBoxDescriptor(int id);
public abstract void startPublish();
public abstract void publishNew(PublishedMessageImpl pubmsg);
public abstract void unpublish(long postid);
} // end interface EngineBackend

View File

@ -0,0 +1,426 @@
/*
* 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.io.*;
import java.sql.*;
import java.util.*;
import org.apache.log4j.*;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.db.*;
import com.silverwrist.venice.core.*;
class PublishedMessageImpl implements TopicMessageContext
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Category logger = Category.getInstance(PublishedMessageImpl.class.getName());
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private DataPool datapool;
private long postid;
private long parent;
private int num;
private int linecount;
private int creator_uid;
private java.util.Date posted;
private String pseud;
private String creator_cache = null;
private String text_cache = null;
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
PublishedMessageImpl(DataPool datapool, long postid, long parent, int num, int linecount, int creator_uid,
java.util.Date posted, String pseud, String creator_cache, String text_cache)
{
this.datapool = datapool;
this.postid = postid;
this.parent = parent;
this.num = num;
this.linecount = linecount;
this.creator_uid = creator_uid;
this.posted = posted;
this.pseud = pseud;
this.creator_cache = creator_cache;
this.text_cache = text_cache;
} // end constructor
protected PublishedMessageImpl(DataPool datapool, long postid, long parent, int num, int linecount,
int creator_uid, java.util.Date posted, String pseud)
{
this.datapool = datapool;
this.postid = postid;
this.parent = parent;
this.num = num;
this.linecount = linecount;
this.creator_uid = creator_uid;
this.posted = posted;
this.pseud = pseud;
} // end constructor
/*--------------------------------------------------------------------------------
* Internal functions
*--------------------------------------------------------------------------------
*/
private static String quickGetUserName(Connection conn, int uid) throws SQLException
{
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT username FROM users WHERE uid = " + String.valueOf(uid) + ";");
if (rs.next())
return rs.getString(1);
else
return "(unknown)";
} // end quickGetUserName
/*--------------------------------------------------------------------------------
* Implementations from interface TopicMessageContext
*--------------------------------------------------------------------------------
*/
public long getPostID()
{
return postid;
} // end getPostID
public long getParentPostID()
{
return parent;
} // end getParentPostID
public int getPostNumber()
{
return num;
} // end getPostNumber
public int getNumLines()
{
return linecount;
} // end getNumLines
public int getCreatorUID()
{
return creator_uid;
} // end getCreatorUID
public String getCreatorName() throws DataException
{
if (creator_cache==null)
{ // we don't have the user name yet, get it out of the database
Connection conn = null;
try
{ // use a database connection to get the user name
conn = datapool.getConnection();
creator_cache = quickGetUserName(conn,creator_uid);
} // end try
catch (SQLException e)
{ // turn this into a DataException
logger.error("DB error reading user name: " + e.getMessage(),e);
throw new DataException("unable to retrieve user name: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
} // end if
return creator_cache;
} // end getCreatorName
public java.util.Date getPostDate()
{
return posted;
} // end getPostDate
public boolean isHidden()
{
return false;
} // end isHidden
public boolean isScribbled()
{
return false;
} // end isScribbled
public boolean isNuked()
{
return false;
} // end isNuked
public java.util.Date getScribbleDate()
{
return null;
} // end getScribbleDate
public String getPseud()
{
return pseud;
} // end getPseud
public String getBodyText() throws DataException
{
if (text_cache==null)
{ // we don't have the body text yet, go get it
Connection conn = null;
try
{ // use a database connection to get the body text
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT data FROM postdata WHERE postid = "
+ String.valueOf(postid) + ";");
if (rs.next())
text_cache = rs.getString(1);
else
return "Data Missing"; // FUTURE: throw an exception?
} // end try
catch (SQLException e)
{ // turn this into a DataException
logger.error("DB error reading post data: " + e.getMessage(),e);
throw new DataException("unable to retrieve post data: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
} // end if
return text_cache;
} // end getBodyCache
public boolean hasAttachment()
{
return false; // FUTURE: allow publishing paperclips?
} // end hasAttachment
public String getAttachmentType()
{
return null; // FUTURE: allow publishing paperclips?
} // end getAttachmentType
public String getAttachmentFilename()
{
return null; // FUTURE: allow publishing paperclips?
} // end getAttachmentFilename
public int getAttachmentLength()
{
return 0; // FUTURE: allow publishing paperclips?
} // end getAttachmentLength
public InputStream getAttachmentData() throws AccessError, DataException
{
// FUTURE: allow publishing paperclips?
throw new AccessError("There is no attachment data for this message.");
} // end getAttachmentData
public boolean canHide()
{
return false;
} // end canHide
public boolean canScribble()
{
return false;
} // end canScribble
public boolean canNuke()
{
return false;
} // end canNuke
public void setHidden(boolean flag) throws DataException, AccessError
{
throw new AccessError("You are not permitted to change the hidden status of this message.");
} // end setHidden
public void scribble() throws DataException, AccessError
{
throw new AccessError("You are not permitted to scribble this message.");
} // end scribble
public void nuke() throws DataException, AccessError
{
throw new AccessError("You are not permitted to nuke this message.");
} // end nuke
public void attachData(String m_type, String file, int length, InputStream data)
throws AccessError, DataException
{
throw new AccessError("You are not permitted to add an attachment to this message.");
} // end attachData
public boolean canPublish()
{
return false;
} // end canPublish
public void publish() throws DataException, AccessError
{
throw new DataException("Cannot publish a message that has already been published.");
} // end publish
/*--------------------------------------------------------------------------------
* Static operations usable only within package
*--------------------------------------------------------------------------------
*/
static void backfillCache(List cache_list, int desired_size, DataPool datapool) throws DataException
{
Connection conn = null;
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// create the statement to retrieve the post information
StringBuffer sql =
new StringBuffer("SELECT p.postid, q.parent, q.num, q.linecount, q.creator_uid, q.posted, "
+ "q.pseud FROM postpublish p, posts q WHERE p.postid = q.postid "
+ "ORDER BY p.on_date DESC, p.postid ASC LIMIT ");
sql.append(cache_list.size()).append(", ").append(desired_size-cache_list.size()).append(';');
// execute the statement!
ResultSet rs = stmt.executeQuery(sql.toString());
while (rs.next())
cache_list.add(new PublishedMessageImpl(datapool,rs.getLong(1),rs.getLong(2),rs.getInt(3),rs.getInt(4),
rs.getInt(5),SQLUtil.getFullDateTime(rs,6),rs.getString(7)));
} // end try
catch (SQLException e)
{ // error retrieving post information
logger.error("DB error reading post information: " + e.getMessage(),e);
throw new DataException("unable to retrieve post information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
} // end backfillCache
static void backfillReturn(List return_list, DataPool datapool) throws DataException
{
Connection conn = null;
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// How many posts have been published anyway?
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM postpublish;");
if (!(rs.next()))
throw new InternalStateError("Count query screwup in PublishedMessageImpl.backfillReturn");
if (rs.getInt(1)<=return_list.size())
return; // nothing to do here!
// execute the statement to retrieve the post information
final String sql = "SELECT p.postid, q.parent, q.num, q.linecount, q.creator_uid, q.posted, q.pseud "
+ "FROM postpublish p, posts q WHERE p.postid = q.postid ORDER BY p.on_date DESC, "
+ "p.postid ASC;";
rs = stmt.executeQuery(sql);
// append to the output list
int ctr = return_list.size();
while (rs.next())
{ // we need to skip the first batch of output, because it's cached
if ((ctr--)<=0)
{ // append context, please
TopicMessageContext ctxt =
new PublishedMessageImpl(datapool,rs.getLong(1),rs.getLong(2),rs.getInt(3),rs.getInt(4),
rs.getInt(5),SQLUtil.getFullDateTime(rs,6),rs.getString(7));
return_list.add(ctxt);
} // end if
} // end while
} // end try
catch (SQLException e)
{ // error retrieving post information
logger.error("DB error reading post information: " + e.getMessage(),e);
throw new DataException("unable to retrieve post information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
} // end backfillReturn
} // end class PublishedMessageImpl

View File

@ -1852,7 +1852,8 @@ class SIGCoreData implements SIGData, SIGDataBackend
} // end finally
// Delete the rest of the gunk in the background; use another thread to do it.
BackgroundSIGPurge purger = new BackgroundSIGPurge(datapool,user,sigid,conf_count,conf_max,conf_objects);
BackgroundSIGPurge purger = new BackgroundSIGPurge(engine,datapool,user,sigid,conf_count,conf_max,
conf_objects);
Thread thrd = new Thread(purger);
thrd.setPriority(Thread.NORM_PRIORITY-1);
thrd.start();

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,7 @@ import org.apache.log4j.*;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.db.*;
import com.silverwrist.venice.security.AuditRecord;
import com.silverwrist.venice.security.Capability;
import com.silverwrist.venice.core.*;
class TopicMessageUserContextImpl implements TopicMessageContext
@ -123,7 +124,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext
private static String quickGetUserName(Connection conn, int uid) throws SQLException
{
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT username FROM users WHERE uid = " + String.valueOf(uid) + ";");
ResultSet rs = stmt.executeQuery("SELECT username FROM users WHERE uid = " + uid + ";");
if (rs.next())
return rs.getString(1);
else
@ -297,8 +298,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext
if (scribble_date==null)
{ // let's go get the body text!
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT data FROM postdata WHERE postid = "
+ String.valueOf(postid) + ";");
ResultSet rs = stmt.executeQuery("SELECT data FROM postdata WHERE postid = " + postid + ";");
if (rs.next())
text_cache = rs.getString(1);
else
@ -508,8 +508,8 @@ class TopicMessageUserContextImpl implements TopicMessageContext
// record what we did in an audit record
ar = new AuditRecord(AuditRecord.HIDE_MESSAGE,conf.realUID(),conf.userRemoteAddress(),
conf.realSIGID(),"conf=" + String.valueOf(conf.realConfID()) + ",post="
+ String.valueOf(postid),flag ? "hide" : "unhide");
conf.realSIGID(),"conf=" + conf.realConfID() + ",post=" + postid,
flag ? "hide" : "unhide");
} // end try
catch (SQLException e)
@ -562,7 +562,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext
Statement stmt = conn.createStatement();
// lock the tables we reference
stmt.executeUpdate("LOCK TABLES posts WRITE, postdata WRITE, postattach WRITE;");
stmt.executeUpdate("LOCK TABLES posts WRITE, postdata WRITE, postattach WRITE, postpublish WRITE;");
try
{ // first, make sure we have the right status for our post
refresh(conn);
@ -581,8 +581,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext
stmt.executeUpdate(sql.toString());
// Determine if we need to "rub out" the post before we delete it.
ResultSet rs = stmt.executeQuery("SELECT LENGTH(data) FROM postdata WHERE postid = "
+ String.valueOf(postid) + ";");
ResultSet rs = stmt.executeQuery("SELECT LENGTH(data) FROM postdata WHERE postid = " + postid + ";");
if (rs.next())
{ // use this data to overwrite the post with X's
int len = rs.getInt(1);
@ -617,6 +616,12 @@ class TopicMessageUserContextImpl implements TopicMessageContext
sql.append("DELETE FROM postattach WHERE postid = ").append(postid).append(';');
stmt.executeUpdate(sql.toString());
// Un-publish the posting.
sql.setLength(0);
sql.append("DELETE FROM postpublish WHERE postid = ").append(postid).append(';');
if (stmt.executeUpdate(sql.toString())>0)
engine.unpublish(postid);
// Update our internal data fields.
linecount = 0;
hidden = false;
@ -635,8 +640,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext
// record what we did in an audit record
ar = new AuditRecord(AuditRecord.SCRIBBLE_MESSAGE,conf.realUID(),conf.userRemoteAddress(),
conf.realSIGID(),"conf=" + String.valueOf(conf.realConfID()) + ",post="
+ String.valueOf(postid));
conf.realSIGID(),"conf=" + conf.realConfID() + ",post=" + postid);
} // end try
catch (SQLException e)
@ -687,7 +691,8 @@ class TopicMessageUserContextImpl implements TopicMessageContext
Statement stmt = conn.createStatement();
// lock the tables we reference
stmt.executeUpdate("LOCK TABLES posts WRITE, postdata WRITE, postattach WRITE, postdogear WRITE;");
stmt.executeUpdate("LOCK TABLES posts WRITE, postdata WRITE, postattach WRITE, postdogear WRITE, "
+ "postpublish WRITE;");
try
{ // first, make sure we have the right status for our post
@ -696,10 +701,12 @@ class TopicMessageUserContextImpl implements TopicMessageContext
return; // nuking a nuked post is futile
// Delete any and all references to this post!
stmt.executeUpdate("DELETE FROM posts WHERE postid = " + String.valueOf(postid) + ";");
stmt.executeUpdate("DELETE FROM postdata WHERE postid = " + String.valueOf(postid) + ";");
stmt.executeUpdate("DELETE FROM postattach WHERE postid = " + String.valueOf(postid) + ";");
stmt.executeUpdate("DELETE FROM postdogear WHERE postid = " + String.valueOf(postid) + ";");
stmt.executeUpdate("DELETE FROM posts WHERE postid = " + postid + ";");
stmt.executeUpdate("DELETE FROM postdata WHERE postid = " + postid + ";");
stmt.executeUpdate("DELETE FROM postattach WHERE postid = " + postid + ";");
stmt.executeUpdate("DELETE FROM postdogear WHERE postid = " + postid + ";");
if (stmt.executeUpdate("DELETE FROM postpublish WHERE postid = " + postid + ";")>0)
engine.unpublish(postid);
// Update our internal variables.
linecount = 0;
@ -726,8 +733,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext
// record what we did in an audit record
ar = new AuditRecord(AuditRecord.NUKE_MESSAGE,conf.realUID(),conf.userRemoteAddress(),
conf.realSIGID(),"conf=" + String.valueOf(conf.realConfID()) + ",post="
+ String.valueOf(postid));
conf.realSIGID(),"conf=" + conf.realConfID() + ",post=" + postid);
} // end try
catch (SQLException e)
@ -803,9 +809,9 @@ class TopicMessageUserContextImpl implements TopicMessageContext
} // end if
else if (length>MAX_ATTACH)
{ // the attachment is too damn long!
logger.error("attachment is too long (" + String.valueOf(length) + " bytes)");
throw new AccessError("The attachment is too long to store. Maximum available length is "
+ String.valueOf(MAX_ATTACH) + " bytes.");
logger.error("attachment is too long (" + length + " bytes)");
throw new AccessError("The attachment is too long to store. Maximum available length is " + MAX_ATTACH
+ " bytes.");
} // end else if
@ -844,9 +850,8 @@ class TopicMessageUserContextImpl implements TopicMessageContext
// Generate an audit record indicating what we did.
ar = new AuditRecord(AuditRecord.UPLOAD_ATTACHMENT,conf.realUID(),conf.userRemoteAddress(),
conf.realSIGID(),"conf=" + String.valueOf(conf.realConfID()) + ",post="
+ String.valueOf(postid),"len=" + String.valueOf(length) + ",type=" + m_type
+ ",name=" + file);
conf.realSIGID(),"conf=" + conf.realConfID() + ",post=" + postid,
"len=" + length + ",type=" + m_type + ",name=" + file);
} // end try
catch (SQLException e)
@ -876,6 +881,136 @@ class TopicMessageUserContextImpl implements TopicMessageContext
} // end attachData
public boolean canPublish()
{
if (!(Capability.canPublishToFrontPage(conf.realBaseLevel())))
return false; // must be a sysadmin to publish
if ((scribble_date!=null) || nuked)
return false; // cannot publish a scribbled or nuked message
Connection conn = null;
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// see if the post has already been published
ResultSet rs = stmt.executeQuery("SELECT by_uid FROM postpublish WHERE postid = " + postid
+ " LIMIT 1;");
return !(rs.next());
} // end try
catch (SQLException e)
{ // just trap SQL exceptions and log them
logger.error("SQL exception in TopicMessageUserContextImpl.canPublish: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return false; // assume we can't
} // end canPublish
public void publish() throws DataException, AccessError
{
if (!(Capability.canPublishToFrontPage(conf.realBaseLevel())))
{ // you aren't allowed to publish - naughty naughty!
logger.error("unable to publish because we're not allowed");
throw new AccessError("You are not permitted to publish postings to the front page.");
} // end if
if (nuked)
{ // we can't publish a nuked message!
logger.error("unable to publish because message nuked");
throw new DataException("Cannot publish a message that has been nuked.");
} // end if
if (scribble_date!=null)
{ // we can't publish a scribbled message!
logger.error("unable to publish because message scribbled");
throw new DataException("Cannot publish a message that has been scribbled.");
} // end if
Connection conn = null;
AuditRecord ar = null;
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// see if post has already been published
ResultSet rs = stmt.executeQuery("SELECT by_uid FROM postpublish WHERE postid = " + postid
+ " LIMIT 1;");
if (rs.next()) // can't do it, friend!
throw new DataException("This posting has already been published.");
boolean done = false;
engine.startPublish();
try
{ // insert the post reference into the database
StringBuffer sql =
new StringBuffer("INSERT INTO postpublish (sigid, postid, by_uid, on_date) VALUES (");
sql.append(conf.realSIGID()).append(", ").append(postid).append(", ").append(conf.realUID());
java.util.Date now = new java.util.Date();
sql.append(", '").append(SQLUtil.encodeDate(now)).append("');");
stmt.executeUpdate(sql.toString());
// generate an audit record indicating what we've done
ar = new AuditRecord(AuditRecord.PUBLISH_POST,conf.realUID(),conf.userRemoteAddress(),
conf.realSIGID(),"conf=" + conf.realConfID() + ",post=" + postid);
// establish cached data object for front page
engine.publishNew(new PublishedMessageImpl(datapool,postid,parent,num,linecount,creator_uid,
posted,pseud,creator_cache,text_cache));
done = true;
} // end try
finally
{ // make sure to release the lock if we goofed in here
if (!done)
engine.publishNew(null);
} // end finally
} // end try
catch (SQLException e)
{ // just trap SQL exceptions and log them
logger.error("unable to publish posting: " + e.getMessage(),e);
throw new DataException("unable to publish posting: " + 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
} // end publish
/*--------------------------------------------------------------------------------
* External static operations
*--------------------------------------------------------------------------------
@ -885,9 +1020,8 @@ class TopicMessageUserContextImpl implements TopicMessageContext
int post_low, int post_high) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("loadMessageRange for conf # " + String.valueOf(conf.realConfID()) + ", topic #"
+ String.valueOf(topicid) + ", range [" + String.valueOf(post_low) + ", "
+ String.valueOf(post_high) + "]");
logger.debug("loadMessageRange for conf # " + conf.realConfID() + ", topic #" + topicid + ", range ["
+ post_low + ", " + post_high + "]");
Vector rc = new Vector();
Connection conn = null; // pooled database connection
@ -942,8 +1076,8 @@ class TopicMessageUserContextImpl implements TopicMessageContext
int topicid, int message_num) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("loadMessage for conf # " + String.valueOf(conf.realConfID()) + ", topic #"
+ String.valueOf(topicid) + ", message " + String.valueOf(message_num));
logger.debug("loadMessage for conf # " + conf.realConfID() + ", topic #" + topicid + ", message "
+ message_num);
Connection conn = null; // pooled database connection
@ -993,8 +1127,7 @@ class TopicMessageUserContextImpl implements TopicMessageContext
long postid) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("getMessage for conf # " + String.valueOf(conf.realConfID()) + ", post #"
+ String.valueOf(postid));
logger.debug("getMessage for conf # " + conf.realConfID() + ", post #" + postid);
Connection conn = null; // pooled database connection

View File

@ -880,7 +880,7 @@ class TopicUserContextImpl implements TopicContext
} // 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);
BackgroundTopicPurge purger = new BackgroundTopicPurge(engine,datapool,topicid,post_count,post_max);
Thread thrd = new Thread(purger);
thrd.setPriority(Thread.NORM_PRIORITY-1);
thrd.start();

View File

@ -20,6 +20,7 @@ package com.silverwrist.venice.core.impl;
import java.util.*;
import java.sql.*;
import org.apache.log4j.*;
import com.silverwrist.util.LocaleFactory;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.*;
import com.silverwrist.venice.core.*;
@ -59,6 +60,8 @@ class UserContextImpl implements UserContext, UserBackend
private String my_email = null; // my email address (cached)
private String my_pseud = null; // my pseud (cached)
private String full_name = null; // my full name (cached)
private Locale my_locale = null; // my default locale (cached)
private TimeZone my_tz = null; // my default timezone (cached)
/*--------------------------------------------------------------------------------
* Constructor
@ -84,6 +87,12 @@ class UserContextImpl implements UserContext, UserBackend
username = null;
created = null;
last_access = null;
description = null;
my_email = null;
my_pseud = null;
full_name = null;
my_locale = null;
my_tz = null;
} // end finalize
@ -108,18 +117,64 @@ class UserContextImpl implements UserContext, UserBackend
// skip field "passreminder"
description = rs.getString("description");
// purge any "cached" fields that may be left over
my_email = null;
my_pseud = null;
full_name = null;
my_locale = null;
my_tz = null;
if (logger.isDebugEnabled())
{ // spit it all out to debug info
logger.debug("Loaded: UID " + String.valueOf(uid) + ", username \"" + username + "\", contactid "
+ String.valueOf(contactid));
logger.debug("...is_anon " + String.valueOf(is_anon) + ", email_verified "
+ String.valueOf(email_verified));
logger.debug("... level " + String.valueOf(level));
logger.debug("Loaded: UID " + uid + ", username \"" + username + "\", contactid " + contactid);
logger.debug("...is_anon " + is_anon + ", email_verified " + email_verified);
logger.debug("... level " + level);
} // end if
} // end loadUserData
private void loadPrefs(Connection conn) throws SQLException, DataException
{
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM userprefs WHERE uid = " + uid + ";");
if (!(rs.next()))
throw new DataException("cannot find preferences for user");
if (my_tz==null)
my_tz = TimeZone.getTimeZone(rs.getString("tzid"));
if (my_locale==null)
my_locale = LocaleFactory.createLocale(rs.getString("localeid"));
} // end loadPrefs
private void loadPrefs() throws DataException
{
Connection conn = null;
try
{ // call through to lower level function
conn = datapool.getConnection();
loadPrefs(conn);
} // end try
catch (SQLException e)
{ // translate into DataException, yadda yadda yadda
logger.error("SQL error reading preferences: " + e.getMessage(),e);
throw new DataException("Unable to read user preferences: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
} // end loadPrefs
private void sendEmailConfirmation() throws DataException, EmailException
{
if (logger.isDebugEnabled())
@ -180,7 +235,7 @@ class UserContextImpl implements UserContext, UserBackend
public boolean isLoggedIn()
{
if (logger.isDebugEnabled())
logger.debug("isLoggedIn(): uid = " + String.valueOf(uid) + ", is_anon = " + String.valueOf(is_anon));
logger.debug("isLoggedIn(): uid = " + uid + ", is_anon = " + is_anon);
return ((uid!=-1) && !is_anon);
} // end is_logged_in
@ -195,7 +250,7 @@ class UserContextImpl implements UserContext, UserBackend
{
if (isLoggedIn())
{ // already authenticated, can't authenticate again
logger.error("UserContext already authenticated (with uid " + String.valueOf(uid) + ")");
logger.error("UserContext already authenticated (with uid " + uid + ")");
throw new InternalStateError("context already authenticated");
} // end if
@ -302,7 +357,7 @@ class UserContextImpl implements UserContext, UserBackend
public void confirmEmail(int conf_num) throws AccessError, DataException
{
if (logger.isDebugEnabled())
logger.debug("confirmEmail(): confirming for UID " + String.valueOf(uid));
logger.debug("confirmEmail(): confirming for UID " + uid);
if ((email_verified) || Capability.exemptFromEmailVerification(level))
{ // already confirmed
if (logger.isDebugEnabled())
@ -368,7 +423,7 @@ class UserContextImpl implements UserContext, UserBackend
public void resendEmailConfirmation() throws DataException, EmailException
{
if (logger.isDebugEnabled())
logger.debug("resendEmailConfirmation(): resending for UID " + String.valueOf(uid));
logger.debug("resendEmailConfirmation(): resending for UID " + uid);
if ((email_verified) || Capability.exemptFromEmailVerification(level))
{ // already confirmed, no need to resend
if (logger.isDebugEnabled())
@ -433,6 +488,9 @@ class UserContextImpl implements UserContext, UserBackend
public ContactInfo getContactInfo() throws DataException
{
if (logger.isDebugEnabled())
logger.debug("getContactInfo() for UID " + uid);
ContactInfoImpl rc;
if (contactid>=0)
rc = new ContactInfoImpl(datapool,contactid);
@ -450,11 +508,14 @@ class UserContextImpl implements UserContext, UserBackend
public boolean putContactInfo(ContactInfo ci) throws DataException, EmailException
{
if (logger.isDebugEnabled())
logger.debug("putContactInfo() for UID " + uid);
boolean email_changed = false;
if ((ci.getOwnerUID()!=uid) || (ci.getOwnerSIGID()>=0))
{ // the contact information is not owned correctly
logger.error("ContactInfo ownership wrong (it's " + String.valueOf(ci.getOwnerUID()) + ", "
+ String.valueOf(ci.getOwnerSIGID()) + "), should be (" + String.valueOf(uid) + ", -1)");
logger.error("ContactInfo ownership wrong (it's " + ci.getOwnerUID() + ", " + ci.getOwnerSIGID()
+ "), should be (" + uid + ", -1)");
throw new DataException("invalid contact information record");
} // end if
@ -481,7 +542,7 @@ class UserContextImpl implements UserContext, UserBackend
{ // contact being established for the first time
contactid = ci.getContactID();
if (logger.isDebugEnabled())
logger.debug("...established initial contact (" + String.valueOf(contactid) + ") for user");
logger.debug("...established initial contact (" + contactid + ") for user");
my_email = ci.getEmail();
sendEmailConfirmation();
email_changed = true;
@ -524,8 +585,7 @@ class UserContextImpl implements UserContext, UserBackend
} // end else if
ar = new AuditRecord(AuditRecord.USER_CONTACT_INFO,uid,remote_addr,
"contactid=" + String.valueOf(contactid));
ar = new AuditRecord(AuditRecord.USER_CONTACT_INFO,uid,remote_addr,"contactid=" + contactid);
} // end try
catch (ClassCastException cce)
@ -597,7 +657,7 @@ class UserContextImpl implements UserContext, UserBackend
public UserProfile getProfile(int xuid) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("getProfile(#" + String.valueOf(xuid) + ")...");
logger.debug("getProfile(#" + xuid + ")...");
Connection conn = null;
try
@ -893,6 +953,94 @@ class UserContextImpl implements UserContext, UserBackend
} // end getAdminInterface
public Locale getLocale() throws DataException
{
if (my_locale==null)
loadPrefs();
return my_locale;
} // end getLocale
public void setLocale(Locale locale) throws DataException
{
Connection conn = null;
try
{ // retrieve a connection from the data pool
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// create the update statement
StringBuffer sql = new StringBuffer("UPDATE userprefs SET localeid = '");
sql.append(SQLUtil.encodeString(locale.toString())).append("' WHERE uid = ").append(uid).append(';');
// execute the statement
stmt.executeUpdate(sql.toString());
// replace the locale here
my_locale = locale;
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error setting user locale: " + e.getMessage(),e);
throw new DataException("unable to set user locale: " + e.getMessage(),e);
} // end catch
finally
{ // make sure the connection is released before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
} // end setLocale
public TimeZone getTimeZone() throws DataException
{
if (my_tz==null)
loadPrefs();
return my_tz;
} // end getTimeZone
public void setTimeZone(TimeZone timezone) throws DataException
{
Connection conn = null;
try
{ // retrieve a connection from the data pool
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// create the update statement
StringBuffer sql = new StringBuffer("UPDATE userprefs SET tzid = '");
sql.append(SQLUtil.encodeString(timezone.getID())).append("' WHERE uid = ").append(uid).append(';');
// execute the statement
stmt.executeUpdate(sql.toString());
// replace the locale here
my_tz = timezone;
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error setting user timezone: " + e.getMessage(),e);
throw new DataException("unable to set user timezone: " + e.getMessage(),e);
} // end catch
finally
{ // make sure the connection is released before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
} // end setTimeZone
/*--------------------------------------------------------------------------------
* Implementations from interface UserBackend
*--------------------------------------------------------------------------------
@ -918,6 +1066,8 @@ class UserContextImpl implements UserContext, UserBackend
public String userDefaultPseud() throws DataException
{
if (logger.isDebugEnabled())
logger.debug("userDefaultPseud() for UID " + uid);
if (my_pseud==null)
getContactInfo();
return my_pseud;
@ -999,8 +1149,8 @@ class UserContextImpl implements UserContext, UserBackend
java.util.Date created, java.util.Date last_access)
{
if (logger.isDebugEnabled())
logger.debug("loadNewUser() on UserContext: addr " + remote_addr + ", uid " + String.valueOf(uid)
+ ", level " + String.valueOf(level) + ", username \"" + username + "\"");
logger.debug("loadNewUser() on UserContext: addr " + remote_addr + ", uid " + uid + ", level "
+ level + ", username \"" + username + "\"");
this.remote_addr = remote_addr;
this.uid = uid;

View File

@ -304,6 +304,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
private int[] gp_ints; // global integer parameters
private MasterSideBox[] sideboxes; // master sidebox table
private Hashtable sidebox_ids = new Hashtable(); // maps sidebox IDs to MasterSideBox objects
private Vector cache_fp_posts = new Vector(); // all posts that have been published to front page
private boolean cache_fp_posts_busy = false; // busy flag for above vector
/*--------------------------------------------------------------------------------
* Constructor
@ -333,8 +335,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
private void loadDefaults(Statement stmt) throws SQLException, DataException
{
final String query =
"SELECT posts_per_page, old_posts_at_top, max_search_page, max_sig_mbr_page, max_conf_mbr_page "
+ "FROM globals;";
"SELECT posts_per_page, old_posts_at_top, max_search_page, max_sig_mbr_page, max_conf_mbr_page, "
+ "fp_posts FROM globals;";
ResultSet rs = stmt.executeQuery(query);
if (!(rs.next()))
throw new DataException("Globals table does not appear to be loaded!");
@ -345,6 +347,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
gp_ints[IP_MAXSEARCHRETURN] = rs.getInt(3);
gp_ints[IP_MAXSIGMEMBERDISPLAY] = rs.getInt(4);
gp_ints[IP_MAXCONFMEMBERDISPLAY] = rs.getInt(5);
gp_ints[IP_NUMFRONTPAGEPOSTS] = rs.getInt(6);
} // end loadDefaults
@ -489,7 +492,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end catch
// Allocate the global parameter arrays.
gp_ints = new int[5];
gp_ints = new int[6];
// initialize anything that requires us to pull from the database
Connection conn = null;
@ -1391,6 +1394,48 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getMasterSideBoxList
public List getPublishedMessages(boolean all) throws DataException
{
Vector rc = new Vector();
synchronized (this)
{ // Make sure the cache is in condition.
while (cache_fp_posts_busy)
{ // the list is busy, don't fsck with it until we're done
try
{ // wait to see if they can be un-busy
wait();
} // end try
catch (InterruptedException e)
{ // do nothing
} // end catch
} // end while
// If the cache list contains too few items, backfill it from the database.
if (cache_fp_posts.size()<gp_ints[IP_NUMFRONTPAGEPOSTS])
PublishedMessageImpl.backfillCache(cache_fp_posts,gp_ints[IP_NUMFRONTPAGEPOSTS],datapool);
// Copy the contents to the return vector, casting them to TopicMessageContext.
Iterator it = cache_fp_posts.iterator();
while (it.hasNext())
{ // cast each element and add the casted object to the output
PublishedMessageImpl pmi = (PublishedMessageImpl)(it.next());
TopicMessageContext ctxt = (TopicMessageContext)pmi;
rc.add(ctxt);
} // end while
} // end synchronized block
if (all) // add the extra postings to the list
PublishedMessageImpl.backfillReturn(rc,datapool);
return new ReadOnlyVector(rc);
} // end getPublishedMessages
/*--------------------------------------------------------------------------------
* Implementations from interface EngineBackend
*--------------------------------------------------------------------------------
@ -1805,4 +1850,42 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getMasterSideBoxDescriptor
public synchronized void startPublish()
{
cache_fp_posts_busy = true;
} // end startPublish
public synchronized void publishNew(PublishedMessageImpl pubmsg)
{
if (pubmsg!=null)
{ // add the new message
cache_fp_posts.add(0,pubmsg);
while (cache_fp_posts.size()>gp_ints[IP_NUMFRONTPAGEPOSTS])
cache_fp_posts.remove(cache_fp_posts.size()-1);
} // end pubmsg
cache_fp_posts_busy = false;
notifyAll();
} // end publishNew
public synchronized void unpublish(long postid)
{
Iterator it = cache_fp_posts.iterator();
while (it.hasNext())
{ // get each published message in the cache in turn, looking for the specified post ID
PublishedMessageImpl pmi = (PublishedMessageImpl)(it.next());
if (pmi.getPostID()==postid)
{ // drop the specified post ID like a hot rock
it.remove();
break;
} // end if
} // end while
} // end unpublish
} // 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
@ -19,7 +19,8 @@ package com.silverwrist.venice.security;
public interface Audit
{
// Codes 0-100 - System events
// Codes 1-100 - System events
public static final int PUBLISH_POST = 1;
// Codes 101-200 - Login/user events
public static final int LOGIN_OK = 101;

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
@ -103,4 +103,10 @@ public class Capability implements SecLevels
} // end canAdministerSystem
public static boolean canPublishToFrontPage(int level)
{
return (level>=GLOBAL_ANYADMIN);
} // end canPublishToFrontPage
} // end class Capability

View File

@ -172,6 +172,30 @@ public class PostOperations extends VeniceServlet
} // end if ("nuke")
if (cmd.equals("PU"))
{ // we want to publish the message to the front page
try
{ // attempt to publish the message
msg.publish();
// go back and display stuff
throw new RedirectResult(location);
} // end try
catch (DataException de)
{ // there was a database error
return new ErrorBox("Database Error","Database error publishing message: " + de.getMessage(),
location);
} // end catch
catch (AccessError ae)
{ // naughty naughty = you can't do this!
return new ErrorBox("Access Error",ae.getMessage(),location);
} // end catch
} // end if
// unrecognized command!
logger.error("invalid command to PostOperations.doGet: " + cmd);
return new ErrorBox("Internal Error","Invalid command to PostOperations.doGet",location);

View File

@ -76,7 +76,7 @@ public class Top extends VeniceServlet
try
{ // attempt to get the user content
return new TopDisplay(getServletContext(),user);
return new TopDisplay(getServletContext(),engine,user);
} // end try
catch (DataException de)

View File

@ -565,7 +565,7 @@ public abstract class VeniceServlet extends HttpServlet
ServletContext ctxt = getServletContext();
VeniceEngine engine = Variables.getVeniceEngine(ctxt);
UserContext user = Variables.getUserContext(ctxt,request,request.getSession(true));
RenderData rdat = RenderConfig.createRenderData(ctxt,request,response);
RenderData rdat = RenderConfig.createRenderData(ctxt,user,request,response);
ServletMultipartHandler mphandler = null;
VeniceContent content = null;

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,6 +25,11 @@ import com.silverwrist.venice.core.Country;
public class CDCountryListFormField extends CDPickListFormField
{
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
public CDCountryListFormField(String name, String caption, String caption2, boolean required,
List country_list)
{
@ -38,6 +43,11 @@ public class CDCountryListFormField extends CDPickListFormField
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class CDPickListFormField
*--------------------------------------------------------------------------------
*/
protected void renderChoice(Writer out, RenderData rdat, Object obj, String my_value) throws IOException
{
Country c = (Country)obj;
@ -48,6 +58,11 @@ public class CDCountryListFormField extends CDPickListFormField
} // end renderChoice
/*--------------------------------------------------------------------------------
* Implementations from interface CDFormField
*--------------------------------------------------------------------------------
*/
public CDFormField duplicate()
{
return new CDCountryListFormField(this);

View File

@ -0,0 +1,106 @@
/*
* 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.format;
import java.util.*;
import java.io.Writer;
import java.io.IOException;
import com.silverwrist.util.StringUtil;
public class CDLocaleListFormField extends CDPickListFormField
{
/*--------------------------------------------------------------------------------
* Private list implementation
*--------------------------------------------------------------------------------
*/
static class LocaleList extends AbstractList
{
private Locale[] array; // local array
LocaleList()
{
array = Locale.getAvailableLocales();
} // end constructor
protected void finalize() throws Throwable
{
array = null;
super.finalize();
} // end finalize
public Object get(int index)
{
return array[index];
} // end get
public int size()
{
return array.length;
} // end size
} // end class LocaleList
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
public CDLocaleListFormField(String name, String caption, String caption2, boolean required)
{
super(name,caption,caption2,required,new LocaleList());
} // end constructor
protected CDLocaleListFormField(CDLocaleListFormField other)
{
super(other);
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class CDPickListFormField
*--------------------------------------------------------------------------------
*/
protected void renderChoice(Writer out, RenderData rdat, Object obj, String my_value) throws IOException
{
Locale l = (Locale)obj;
out.write("<OPTION VALUE=\"" + l.toString() + "\"");
if (l.toString().equals(my_value))
out.write(" SELECTED");
out.write(">" + StringUtil.encodeHTML(l.getDisplayName()) + "</OPTION>\n");
} // end renderChoice
/*--------------------------------------------------------------------------------
* Implementations from interface CDFormField
*--------------------------------------------------------------------------------
*/
public CDFormField duplicate()
{
return new CDLocaleListFormField(this);
} // end duplicate
} // end class CDLocaleListFormField

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,8 +25,18 @@ import com.silverwrist.util.StringUtil;
public abstract class CDPickListFormField extends CDBaseFormField
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private List choices;
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
protected CDPickListFormField(String name, String caption, String caption2, boolean required,
List choices)
{
@ -42,9 +52,19 @@ public abstract class CDPickListFormField extends CDBaseFormField
} // end constructor
/*--------------------------------------------------------------------------------
* Abstract method declarations
*--------------------------------------------------------------------------------
*/
protected abstract void renderChoice(Writer out, RenderData rdat, Object obj, String my_value)
throws IOException;
/*--------------------------------------------------------------------------------
* Overrides from class CDBaseFormField
*--------------------------------------------------------------------------------
*/
protected void renderActualField(Writer out, RenderData rdat) throws IOException
{
out.write("<SELECT NAME=\"" + getName() + "\" SIZE=1");

View File

@ -0,0 +1,106 @@
/*
* 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.format;
import java.util.*;
import java.io.Writer;
import java.io.IOException;
import com.silverwrist.util.StringUtil;
public class CDTimeZoneListFormField extends CDPickListFormField
{
/*--------------------------------------------------------------------------------
* Private list implementation
*--------------------------------------------------------------------------------
*/
static class TimeZoneList extends AbstractList
{
private String[] array; // local array
TimeZoneList()
{
array = TimeZone.getAvailableIDs();
} // end constructor
protected void finalize() throws Throwable
{
array = null;
super.finalize();
} // end finalize
public Object get(int index)
{
return array[index];
} // end get
public int size()
{
return array.length;
} // end size
} // end class TimeZoneList
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
public CDTimeZoneListFormField(String name, String caption, String caption2, boolean required)
{
super(name,caption,caption2,required,new TimeZoneList());
} // end constructor
protected CDTimeZoneListFormField(CDTimeZoneListFormField other)
{
super(other);
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class CDPickListFormField
*--------------------------------------------------------------------------------
*/
protected void renderChoice(Writer out, RenderData rdat, Object obj, String my_value) throws IOException
{
String id = (String)obj;
out.write("<OPTION VALUE=\"" + id + "\"");
if (id.equals(my_value))
out.write(" SELECTED");
out.write(">" + StringUtil.encodeHTML(id) + "</OPTION>\n");
} // end renderChoice
/*--------------------------------------------------------------------------------
* Implementations from interface CDFormField
*--------------------------------------------------------------------------------
*/
public CDFormField duplicate()
{
return new CDTimeZoneListFormField(this);
} // end duplicate
} // end class CDTimeZoneListFormField

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
@ -17,13 +17,19 @@
*/
package com.silverwrist.venice.servlets.format;
import java.util.List;
import java.util.*;
import com.silverwrist.util.LocaleFactory;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.ValidationException;
import com.silverwrist.venice.core.*;
public class EditProfileDialog extends ContentDialog
{
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
public EditProfileDialog(List country_list)
{
super("Edit Your Profile",null,"profform","account");
@ -62,6 +68,9 @@ public class EditProfileDialog extends ContentDialog
addFormField(new CDFormCategoryHeader("Personal"));
addFormField(new CDTextFormField("descr","Personal description",null,false,32,255));
// TODO: add photo selection/uploading method here
addFormField(new CDFormCategoryHeader("User Preferences"));
addFormField(new CDLocaleListFormField("locale","Default locale","(for formatting dates/times)",true));
addFormField(new CDTimeZoneListFormField("tz","Default time zone",null,true));
addCommandButton(new CDImageButton("update","bn_update.gif","Update",80,24));
addCommandButton(new CDImageButton("cancel","bn_cancel.gif","Cancel",80,24));
@ -73,6 +82,22 @@ public class EditProfileDialog extends ContentDialog
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class Object
*--------------------------------------------------------------------------------
*/
public Object clone()
{
return new EditProfileDialog(this);
} // end clone
/*--------------------------------------------------------------------------------
* Overrides from class ContentDialog
*--------------------------------------------------------------------------------
*/
protected void validateWholeForm() throws ValidationException
{
String pass1 = getFieldValue("pass1");
@ -93,6 +118,11 @@ public class EditProfileDialog extends ContentDialog
} // end validateWholeForm
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public void setTarget(String target)
{
setHiddenField("tgt",target);
@ -132,6 +162,8 @@ public class EditProfileDialog extends ContentDialog
setFieldValue("pvt_email","Y");
setFieldValue("url",ci.getURL());
setFieldValue("descr",uc.getDescription());
setFieldValue("locale",uc.getLocale().toString());
setFieldValue("tz",uc.getTimeZone().getID());
} // end setupDialog
@ -172,8 +204,10 @@ public class EditProfileDialog extends ContentDialog
// Store the completed contact info.
boolean retval = uc.putContactInfo(ci);
// Save off the user's description.
// Save off the user's description and preferences.
uc.setDescription(getFieldValue("descr"));
uc.setLocale(LocaleFactory.createLocale(getFieldValue("locale")));
uc.setTimeZone(TimeZone.getTimeZone(getFieldValue("tz")));
// Finally, change the password if applicable.
foo = getFieldValue("pass1");
@ -192,10 +226,4 @@ public class EditProfileDialog extends ContentDialog
} // end resetOnError
public Object clone()
{
return new EditProfileDialog(this);
} // end clone
} // end class EditProfileDialog

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
@ -29,6 +29,8 @@ import org.xml.sax.SAXParseException;
import com.silverwrist.util.DOMElementHelper;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.core.ConfigException;
import com.silverwrist.venice.core.UserContext;
import com.silverwrist.venice.servlets.Variables;
public class RenderConfig
{
@ -56,6 +58,7 @@ public class RenderConfig
private String image_url;
private String static_url;
private String site_logo;
private Hashtable stock_messages;
/*--------------------------------------------------------------------------------
* Constructor
@ -171,6 +174,35 @@ public class RenderConfig
if (logger.isDebugEnabled())
logger.debug("Site logo: " + image_url);
Element msg_sect = root_h.getSubElement("messages");
if (msg_sect==null)
{ // no <messages/> section - bail out now!
logger.fatal("config document has no <messages/> section");
throw new ConfigException("no <messages/> section found in config file",root);
} // end if
// Initialize the stock messages list.
stock_messages = new Hashtable();
NodeList msg_nodes = msg_sect.getChildNodes();
for (int i=0; i<msg_nodes.getLength(); i++)
{ // examine all subnodes to add them to the message text
Node msgn = msg_nodes.item(i);
if (msgn.getNodeType()==Node.ELEMENT_NODE)
{ // add it to the hash table by its tag name
Element msgel = (Element)msgn;
DOMElementHelper h = new DOMElementHelper(msgel);
String txt = h.getElementText();
if (txt!=null)
stock_messages.put(msgel.getTagName(),txt.trim());
} // end if
} // end for
if (logger.isDebugEnabled())
logger.debug(stock_messages.size() + " stock messages loaded from config");
} // end constructor
/*--------------------------------------------------------------------------------
@ -335,6 +367,19 @@ public class RenderConfig
} // end writeContentHeader
String getStockMessage(String identifier)
{
return (String)(stock_messages.get(identifier));
} // end getStockMessage
void writeStockMessage(Writer out, String identifier) throws IOException
{
String text = (String)(stock_messages.get(identifier));
out.write(StringUtil.encodeHTML(text));
} // end writeStockMessage
/*--------------------------------------------------------------------------------
* Static operations for use by VeniceServlet
*--------------------------------------------------------------------------------
@ -370,7 +415,15 @@ public class RenderConfig
public static RenderData createRenderData(ServletContext ctxt, HttpServletRequest request,
HttpServletResponse response) throws ServletException
{
return new RenderData(getRenderConfig(ctxt),request,response);
UserContext uc = Variables.getUserContext(ctxt,request,request.getSession(true));
return new RenderData(getRenderConfig(ctxt),uc,request,response);
} // end createRenderData
public static RenderData createRenderData(ServletContext ctxt, UserContext uc, HttpServletRequest request,
HttpServletResponse response) throws ServletException
{
return new RenderData(getRenderConfig(ctxt),uc,request,response);
} // end createRenderData

View File

@ -24,7 +24,9 @@ import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.log4j.*;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.core.DataException;
import com.silverwrist.venice.core.IDUtils;
import com.silverwrist.venice.core.UserContext;
import com.silverwrist.venice.db.PostLinkRewriter;
import com.silverwrist.venice.db.UserNameRewriter;
@ -56,7 +58,7 @@ public class RenderData
*--------------------------------------------------------------------------------
*/
RenderData(RenderConfig rconf, HttpServletRequest request, HttpServletResponse response)
RenderData(RenderConfig rconf, UserContext uc, HttpServletRequest request, HttpServletResponse response)
{
this.rconf = rconf;
this.request = request;
@ -67,9 +69,29 @@ public class RenderData
if ((encodings!=null) && (encodings.indexOf("gzip")>=0))
can_gzip = true;
// TODO: replace with reading user's preferences
my_locale = Locale.getDefault();
my_timezone = TimeZone.getDefault();
// read the user's preferred locale
try
{ // get the user default locale
my_locale = uc.getLocale();
} // end try
catch (DataException de)
{ // locale problems...
my_locale = Locale.getDefault();
} // end catch
// read the user's preferred time zone
try
{ // get the user default timezone
my_timezone = uc.getTimeZone();
} // end try
catch (DataException de)
{ // time zone problems...
my_timezone = TimeZone.getDefault();
} // end catch
} // end constructor
@ -206,6 +228,18 @@ public class RenderData
} // end writeContentSelectorHeader
public String getStockMessage(String identifier)
{
return rconf.getStockMessage(identifier);
} // end getStockMessage
public void writeStockMessage(Writer out, String identifier) throws IOException
{
rconf.writeStockMessage(out,identifier);
} // end writeStockMessage
public String formatDateForDisplay(Date date)
{
DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,DateFormat.MEDIUM,my_locale);

View File

@ -40,7 +40,9 @@ public class TopDisplay implements ContentRender
*/
private ServletContext ctxt;
private VeniceEngine engine;
private UserContext uc;
private List top_posts;
private List descrs;
private VeniceContent[] sideboxes;
@ -49,11 +51,14 @@ public class TopDisplay implements ContentRender
*--------------------------------------------------------------------------------
*/
public TopDisplay(ServletContext ctxt, UserContext uc) throws DataException, AccessError, ErrorBox
public TopDisplay(ServletContext ctxt, VeniceEngine engine, UserContext uc)
throws DataException, AccessError, ErrorBox
{
// Stash some basic information.
this.ctxt = ctxt;
this.engine = engine;
this.uc = uc;
this.top_posts = engine.getPublishedMessages(false);
this.descrs = uc.getSideBoxList();
// Create the arrays used to construct sideboxes.
@ -242,4 +247,57 @@ public class TopDisplay implements ContentRender
} // end renderHere
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public static String getPosterName(TopicMessageContext msg)
{
try
{ // have to guard agains a DataException here
return msg.getCreatorName();
} // end try
catch (DataException de)
{ // just return "unknown" on failure
return "(unknown)";
} // end catch
} // end getPosterName
public static String getMessageBodyText(TopicMessageContext msg)
{
try
{ // have to guard against a DataException here
return msg.getBodyText();
} // end try
catch (DataException de)
{ // just return an error message
return "<EM>(Unable to retrieve message data: " + StringUtil.encodeHTML(de.getMessage()) + ")</EM>";
} // end catch
} // end getMessageBodyText
public int getNumTopPosts()
{
return top_posts.size();
} // end getNumTopPosts
public TopicMessageContext getTopPost(int index)
{
return (TopicMessageContext)(top_posts.get(index));
} // end getTopPost
public boolean displayWelcome()
{
return !(uc.isLoggedIn());
} // end displayWelcome
} // end class TopDisplay

View File

@ -220,6 +220,11 @@
SRC="<%= rdat.getFullImagePath("bn_nuke.gif") %>" ALT="Nuke" WIDTH=80 HEIGHT=24
BORDER=0></A><P>
<% } // end if (can nuke) %>
<% if (msg.canPublish()) { %>
<A HREF="<%= rdat.getEncodedServletPath("postops?" + po_loc + "&cmd=PU") %>"><IMG
SRC="<%= rdat.getFullImagePath("bn_publish.gif") %>" ALT="Publish" WIDTH=80 HEIGHT=24
BORDER=0></A><P>
<% } // end if (can publish) %>
</TD></TR></TABLE><BR>
<% } // end if (showing advanced controls) %>
<% can_line = true; %>

View File

@ -26,5 +26,29 @@
RenderData rdat = RenderConfig.createRenderData(application,request,response);
%>
<% if (rdat.useHTMLComments()) { %><!-- Top content panel --><% } %>
<% rdat.writeContentHeader(out,"Venice Currents",null); %>
TODO: Something profound goes here. :-)
<% if (data.displayWelcome()) { %>
<% rdat.writeContentHeader(out,rdat.getStockMessage("welcome-top"),null); %>
<%= rdat.getStdFontTag(null,1) %><% rdat.writeStockMessage(out,"welcome"); %></FONT><P>
<% } // end if %>
<% rdat.writeContentHeader(out,rdat.getStockMessage("currents-top"),null); %>
<% int ntp = data.getNumTopPosts(); %>
<% if (ntp>0) { %>
<% for (int i=0; i<ntp; i++) { %>
<% if (i>0) { %><HR WIDTH="70%"><% } %>
<%
TopicMessageContext msg = data.getTopPost(i);
String poster = data.getPosterName(msg);
%>
<%= rdat.getStdFontTag(null,1) %>
<B><%= msg.getPseud() %></B>
(<EM>
<A HREF="<%= rdat.getEncodedServletPath("user/" + poster) %>" TARGET="_blank"><%= poster %></A>,
<%= rdat.formatDateForDisplay(msg.getPostDate()) %>
</EM>)
<P>
<PRE><%= rdat.rewritePostData(data.getMessageBodyText(msg)) %></PRE>
</FONT>
<% } // end for %>
<% } else { %>
<%= rdat.getStdFontTag(null,1) %><EM>No front page postings found.</EM></FONT>
<% } // end if %>

BIN
web/images/bn_publish.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 B