added admin functions for viewing audit records; gave users the ability

to set their default language and time zone preferences; added footer text
and account signup accept/decline rules; added additional implementation
of dictyionary code for future; minor cleanup of rendering config; and
so forth
This commit is contained in:
Eric J. Bowersox
2001-03-25 08:10:07 +00:00
parent a258f6ee80
commit 15a7fa56d2
31 changed files with 1315 additions and 62 deletions

View File

@@ -0,0 +1,33 @@
package com.silverwrist.util.test;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class DumpAll extends HttpServlet
{
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
PrintWriter out = response.getWriter();
out.println("<HTML><HEAD><TITLE>DumpAll</TITLE></HEAD><BODY><PRE>");
out.println("Auth type: " + request.getAuthType());
out.println("Content length: " + request.getContentLength());
out.println("Content type: " + request.getContentType());
out.println("Path info: " + request.getPathInfo());
out.println("Query string: " + request.getQueryString());
out.println("Remote address: " + request.getRemoteAddr());
out.println("Remote host: " + request.getRemoteHost());
out.println("Remote user: " + request.getRemoteUser());
out.println("Request method: " + request.getMethod());
out.println("Servlet path: " + request.getServletPath());
out.println("Server name: " + request.getServerName());
out.println("Server port: " + request.getServerPort());
out.println("Server protocol: " + request.getProtocol());
out.println("Scheme: " + request.getScheme());
out.println("Context path: " + request.getContextPath());
out.println("Request URI: " + request.getRequestURI());
out.println("</PRE></BODY></HTML>");
}
}

View File

@@ -17,8 +17,12 @@
*/
package com.silverwrist.venice.core;
import java.util.List;
public interface AdminOperations
{
// TODO: fill this in
public abstract List getAuditRecords(int offset, int count) throws DataException;
public abstract int getAuditRecordCount() throws DataException;
} // end interface AdminOperations

View File

@@ -0,0 +1,47 @@
/*
* 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;
import java.util.Date;
import com.silverwrist.venice.security.Audit;
public interface AuditData extends Audit
{
public static final int DATA_COUNT = 4;
public abstract long getRecord();
public abstract Date getDateTime();
public abstract int getType();
public abstract int getUID();
public abstract int getSIGID();
public abstract String getIPAddress();
public abstract String getData(int ndx);
public abstract String getDescription();
public abstract String getUserName();
public abstract String getSIGName();
} // end interface AuditData

View File

@@ -167,4 +167,8 @@ public interface SIGContext extends SearchMode
public abstract boolean canSendInvitation();
public abstract List getAuditRecords(int offset, int count) throws AccessError, DataException;
public abstract int getAuditRecordCount() throws AccessError, DataException;
} // end interface SIGContext

View File

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

View File

@@ -18,9 +18,11 @@
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.*;
import com.silverwrist.venice.security.AuditRecord;
class AdminOperationsImpl implements AdminOperations
{
@@ -58,4 +60,60 @@ class AdminOperationsImpl implements AdminOperations
*--------------------------------------------------------------------------------
*/
public List getAuditRecords(int offset, int count) throws DataException
{
Connection conn = null;
List rc = null;
try
{ // retrieve a connection from the data pool and get the audit records
conn = datapool.getConnection();
rc = AuditRecord.getAuditRecords(conn,-1,offset,count);
} // end try
catch (SQLException e)
{ // database error - this is a DataException
logger.error("error loading audit records: " + e.getMessage(),e);
throw new DataException("unable to load audit records: " + e.getMessage(),e);
} // end catch
finally
{ // make sure the connection is released before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return rc;
} // end getAuditRecords
public int getAuditRecordCount() throws DataException
{
Connection conn = null;
int rc = -1;
try
{ // retrieve a connection from the data pool and get the audit records
conn = datapool.getConnection();
rc = AuditRecord.getAuditRecordCount(conn,-1);
} // end try
catch (SQLException e)
{ // database error - this is a DataException
logger.error("error loading audit record count: " + e.getMessage(),e);
throw new DataException("unable to load audit record count: " + e.getMessage(),e);
} // end catch
finally
{ // make sure the connection is released before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return rc;
} // end getAuditRecordCount
} // end class AdminOperationsImpl

View File

@@ -37,6 +37,7 @@ public interface EngineBackend
public static final int IP_MAXSIGMEMBERDISPLAY = 3;
public static final int IP_MAXCONFMEMBERDISPLAY = 4;
public static final int IP_NUMFRONTPAGEPOSTS = 5;
public static final int IP_NUMAUDITRECSPERPAGE = 6;
public abstract SimpleEmailer createEmailer();

View File

@@ -22,6 +22,7 @@ import java.util.*;
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.security.DefaultLevels;
import com.silverwrist.venice.core.*;
@@ -1271,6 +1272,78 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
} // end canSendInvitation
public List getAuditRecords(int offset, int count) throws AccessError, DataException
{
SIGData sd = getSIGData();
if (!sd.canDeleteSIG(level) && !sd.canModifySIGProfile(level) && !sd.canCreateSIGSubObjects(level))
{ // user not permitted to retrieve audit records - naughty naughty
logger.error("user not permitted to retrieve audit records for SIG");
throw new AccessError("You are not permitted to retrieve audit records for this SIG.");
} // end if
Connection conn = null;
List rc = null;
try
{ // retrieve a connection from the data pool and get the audit records
conn = datapool.getConnection();
rc = AuditRecord.getAuditRecords(conn,sigid,offset,count);
} // end try
catch (SQLException e)
{ // database error - this is a DataException
logger.error("error loading audit records: " + e.getMessage(),e);
throw new DataException("unable to load audit records: " + e.getMessage(),e);
} // end catch
finally
{ // make sure the connection is released before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return rc;
} // end getAuditRecords
public int getAuditRecordCount() throws AccessError, DataException
{
SIGData sd = getSIGData();
if (!sd.canDeleteSIG(level) && !sd.canModifySIGProfile(level) && !sd.canCreateSIGSubObjects(level))
{ // user not permitted to retrieve audit records - naughty naughty
logger.error("user not permitted to retrieve audit records for SIG");
throw new AccessError("You are not permitted to retrieve audit records for this SIG.");
} // end if
Connection conn = null;
int rc = -1;
try
{ // retrieve a connection from the data pool and get the audit records
conn = datapool.getConnection();
rc = AuditRecord.getAuditRecordCount(conn,sigid);
} // end try
catch (SQLException e)
{ // database error - this is a DataException
logger.error("error loading audit record count: " + e.getMessage(),e);
throw new DataException("unable to load audit record count: " + e.getMessage(),e);
} // end catch
finally
{ // make sure the connection is released before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return rc;
} // end getAuditRecordCount
/*--------------------------------------------------------------------------------
* Implementations from interface UserBackend
*--------------------------------------------------------------------------------

View File

@@ -336,7 +336,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
{
final String query =
"SELECT posts_per_page, old_posts_at_top, max_search_page, max_sig_mbr_page, max_conf_mbr_page, "
+ "fp_posts FROM globals;";
+ "fp_posts, num_audit_page FROM globals;";
ResultSet rs = stmt.executeQuery(query);
if (!(rs.next()))
throw new DataException("Globals table does not appear to be loaded!");
@@ -348,6 +348,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
gp_ints[IP_MAXSIGMEMBERDISPLAY] = rs.getInt(4);
gp_ints[IP_MAXCONFMEMBERDISPLAY] = rs.getInt(5);
gp_ints[IP_NUMFRONTPAGEPOSTS] = rs.getInt(6);
gp_ints[IP_NUMAUDITRECSPERPAGE] = rs.getInt(7);
} // end loadDefaults
@@ -492,7 +493,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end catch
// Allocate the global parameter arrays.
gp_ints = new int[6];
gp_ints = new int[7];
// initialize anything that requires us to pull from the database
Connection conn = null;
@@ -1436,6 +1437,12 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getPublishedMessages
public int getNumAuditRecordsPerPage()
{
return gp_ints[IP_NUMAUDITRECSPERPAGE];
} // end getNumAuditRecordsPerPage
/*--------------------------------------------------------------------------------
* Implementations from interface EngineBackend
*--------------------------------------------------------------------------------

View File

@@ -0,0 +1,366 @@
/*
* 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 Community 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.htmlcheck.dict;
import com.silverwrist.venice.htmlcheck.ModSpellingDictionary;
public class TernaryLexicon implements ModSpellingDictionary
{
/*--------------------------------------------------------------------------------
* Inner class representing the nodes in the ternary search tree
*--------------------------------------------------------------------------------
*/
protected class TLNode
{
protected static final int PARENT = 0;
protected static final int LT_CHILD = 1;
protected static final int EQ_CHILD = 2;
protected static final int GT_CHILD = 3;
protected char splitchar;
protected TLNode[] relatives = new TLNode[4];
protected boolean term = false;
protected TLNode(char splitchar, TLNode parent)
{
this.splitchar = splitchar;
relatives[PARENT] = parent;
} // end constructor
} // end class TLNode
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private TLNode root_node;
private int num_entries;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public TernaryLexicon()
{
root_node = null;
num_entries = 0;
} // end constructor
/*--------------------------------------------------------------------------------
* Internal functions
*--------------------------------------------------------------------------------
*/
private TLNode getNode(String key, TLNode start)
{
if ((key==null) || (start==null) || (key.length()==0))
return null; // no node can be found
TLNode current = start;
int ndx = 0;
char c = key.charAt(0);
for (;;)
{ // look for
if (current==null)
break; // fell off the tree...
if (c==current.splitchar)
{ // found an equal character - may be at end of string
if (++ndx==key.length())
return current; // found the node!
current = current.relatives[TLNode.EQ_CHILD];
c = key.charAt(ndx);
} // end if
else if (c<current.splitchar)
current = current.relatives[TLNode.LT_CHILD];
else
current = current.relatives[TLNode.GT_CHILD];
} // end for (ever)
return null; // not found
} // end getNode
private TLNode getOrCreateNode(String key)
{
// Do necessary shorts-checking of the input.
if (key==null)
throw new NullPointerException("getOrCreateNode(null)");
if (key.length()==0)
throw new IllegalArgumentException("getOrCreateNode(\"\")");
if (root_node==null) // create the root node
root_node = new TLNode(key.charAt(0),null);
TLNode current = root_node;
int ndx = 0;
char c = key.charAt(0);
for (;;)
{ // cycle around adding or traversing nodes as needed
if (c==current.splitchar)
{ // go to equal branch, add if necessary
if (++ndx==key.length())
return current; // all done!
c = key.charAt(ndx);
if (current.relatives[TLNode.EQ_CHILD]==null)
current.relatives[TLNode.EQ_CHILD] = new TLNode(c,current);
current = current.relatives[TLNode.EQ_CHILD];
} // end if
else if (c<current.splitchar)
{ // go to lesser branch, add if necessary
if (current.relatives[TLNode.LT_CHILD]==null)
current.relatives[TLNode.LT_CHILD] = new TLNode(c,current);
current = current.relatives[TLNode.LT_CHILD];
} // end else if
else
{ // go to greater branch, add if necessary
if (current.relatives[TLNode.GT_CHILD]==null)
current.relatives[TLNode.GT_CHILD] = new TLNode(c,current);
current = current.relatives[TLNode.GT_CHILD];
} // end else
} // end for (ever)
} // end getOrCreateNode
private TLNode deleteNodeRecursion(TLNode node)
{
if (node==null)
return null; // no node
if ((node.relatives[TLNode.EQ_CHILD]!=null) || node.term)
return null; // can't delete the node if it has an equal child or is a terminal
// get our current parent node
TLNode parent = node.relatives[TLNode.PARENT];
// are either our low or high children null?
boolean low_null = (node.relatives[TLNode.LT_CHILD]==null);
boolean high_null = (node.relatives[TLNode.GT_CHILD]==null);
// what kind of child are we of our parent?
int childtype;
if (parent.relatives[TLNode.LT_CHILD]==node)
childtype = TLNode.LT_CHILD;
else if (parent.relatives[TLNode.GT_CHILD]==node)
childtype = TLNode.GT_CHILD;
else if (parent.relatives[TLNode.EQ_CHILD]==node)
childtype = TLNode.EQ_CHILD;
else
{ // if this executes, then current node is root node
root_node = null;
return null;
} // end else
if (low_null && high_null)
{ // we have no children, we can just kill ourselves
parent.relatives[childtype] = null;
return parent;
} // end if
if (low_null)
{ // no low tree, just chain the high tree in in our place
parent.relatives[childtype] = node.relatives[TLNode.GT_CHILD];
node.relatives[TLNode.GT_CHILD].relatives[TLNode.PARENT] = parent;
return parent;
} // end if
if (high_null)
{ // no high tree, just chain the low tree in in our place
parent.relatives[childtype] = node.relatives[TLNode.LT_CHILD];
node.relatives[TLNode.LT_CHILD].relatives[TLNode.PARENT] = parent;
return parent;
} // end if
// OK, we need to move a node from either the low tree or the high tree into our
// place...but which one?
int delta_hi = node.relatives[TLNode.GT_CHILD].splitchar - node.splitchar;
int delta_lo = node.splitchar - node.relatives[TLNode.LT_CHILD].splitchar;
int ndx_move;
TLNode target;
if (delta_hi==delta_lo)
{ // distances are equal, flip a coin to figure out who gets moved
if (Math.random()<0.5)
delta_hi++;
else
delta_lo++;
} // end if
if (delta_hi>delta_lo)
{ // move the low child into the slot
ndx_move = TLNode.GT_CHILD;
target = node.relatives[TLNode.LT_CHILD];
} // end if
else
{ // move the high child into the slot
ndx_move = TLNode.LT_CHILD;
target = node.relatives[TLNode.GT_CHILD];
} // end else
// find the edge of the subtree that doesn't get moved, and put the other subtree there
while (target.relatives[ndx_move]!=null)
target = target.relatives[ndx_move];
target.relatives[ndx_move] = node.relatives[ndx_move];
node.relatives[ndx_move].relatives[TLNode.PARENT] = target;
// put the target node where the current one used to be
parent.relatives[childtype] = target;
target.relatives[TLNode.PARENT] = parent;
// clean up the current node
node.relatives[TLNode.LT_CHILD] = node.relatives[TLNode.GT_CHILD] = null;
return parent;
} // end deleteNodeRecursion
private void deleteNode(TLNode node)
{
if (node==null)
return;
node.term = false;
while (node!=null)
node = deleteNodeRecursion(node);
} // end deleteNode
private boolean getEntry(String word)
{
TLNode node = getNode(word,root_node);
if (node!=null)
return node.term;
else
return false;
} // end getEntry
private boolean checkHyphenates(String word)
{
if (word.indexOf('-')<0)
return false; // non-hyphenated
int st = 0;
int p;
boolean ok = true;
do
{ // break the word up into hyphenated compounds
p = word.indexOf('-',st);
String frag;
if (p>=0)
{ // get the middle fragment of the word
frag = word.substring(st,p);
st = p + 1;
} // end if
else // get it from the end
frag = word.substring(st);
// check this fragment...
if (frag.length()<=1)
ok = true; // fragments of length 0 or 1 are always OK
else // anything else goes through getEntry
ok = getEntry(frag);
} while (ok && (p>=0));
return ok;
} // end checkHyphenates
/*--------------------------------------------------------------------------------
* Implementations from interface SpellingDictionary
*--------------------------------------------------------------------------------
*/
public synchronized int size()
{
return num_entries;
} // end size
public synchronized boolean checkWord(String word)
{
if (word.length()<=1)
return true; // words of length 1 get a free pass
String real_word = word.toLowerCase();
if (getEntry(real_word))
return true; // word is in lexicon - we're OK to go
if ((real_word.indexOf('\'')==(real_word.length()-2)) && (real_word.charAt(real_word.length()-1)=='s'))
{ // drop the apostrophe-s from the end of the word and retry
String base = real_word.substring(0,real_word.length()-2);
if (getEntry(base))
return true;
return checkHyphenates(base);
} // end if
else // try hyphenated forms
return checkHyphenates(real_word);
} // end checkWord
/*--------------------------------------------------------------------------------
* Implementations from interface ModSpellingDictionary
*--------------------------------------------------------------------------------
*/
public synchronized void addWord(String word)
{
TLNode node = getOrCreateNode(word.toLowerCase());
node.term = true;
num_entries++;
} // end addWord
public synchronized void delWord(String word)
{
TLNode node = getNode(word.toLowerCase(),root_node);
if (node!=null)
{ // delete the node and any unnecessary subnodes
deleteNode(node);
num_entries--;
} // end if
} // end delWord
public synchronized void clear()
{
root_node = null;
num_entries = 0;
} // end clear
} // end class TernaryLexicon

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
@@ -20,10 +20,125 @@ package com.silverwrist.venice.security;
import java.sql.*;
import java.util.*;
import com.silverwrist.venice.db.SQLUtil;
import com.silverwrist.venice.core.AuditData;
import com.silverwrist.venice.core.DataException;
import com.silverwrist.venice.core.InternalStateError;
public class AuditRecord implements Audit
public class AuditRecord implements AuditData
{
/*--------------------------------------------------------------------------------
* Private implementation of ReadOnlyVector
*--------------------------------------------------------------------------------
*/
static class ReadOnlyVector extends AbstractList
{
private Vector my_vec; // local vector
ReadOnlyVector(Vector vec)
{
my_vec = vec;
my_vec.trimToSize();
} // end constructor
protected void finalize() throws Throwable
{
my_vec = null;
super.finalize();
} // end finalize
public Object get(int index)
{
return my_vec.elementAt(index);
} // end get
public int size()
{
return my_vec.size();
} // end size
} // end class ReadOnlyVector
/*--------------------------------------------------------------------------------
* Internal class for caching description strings on load
*--------------------------------------------------------------------------------
*/
static class DescrStringCache
{
private Hashtable descr_cache = new Hashtable();
private Hashtable uname_cache = new Hashtable();
private Hashtable signame_cache = new Hashtable();
private Statement stmt;
DescrStringCache(Connection conn) throws SQLException
{
stmt = conn.createStatement();
} // end constructor
String getDescription(int code) throws SQLException, DataException
{
Integer code_x = new Integer(code);
String rc = (String)(descr_cache.get(code_x));
if (rc==null)
{ // OK, get it from the database...
ResultSet rs = stmt.executeQuery("SELECT descr FROM refaudit WHERE type = " + code + ";");
if (!(rs.next()))
throw new DataException("description string not found for code " + code);
rc = rs.getString(1);
descr_cache.put(code_x,rc);
} // end if
return rc;
} // end getDescription
String getUserName(int uid) throws SQLException, DataException
{
Integer uid_x = new Integer(uid);
String rc = (String)(uname_cache.get(uid_x));
if (rc==null)
{ // OK, get it from the database
ResultSet rs = stmt.executeQuery("SELECT username FROM users WHERE uid = " + uid + ";");
if (!(rs.next()))
throw new DataException("user name not found for UID " + uid);
rc = rs.getString(1);
uname_cache.put(uid_x,rc);
} // end if
return rc;
} // end getUserName
String getSIGName(int sigid) throws SQLException, DataException
{
if (sigid<=0)
return ""; // no SIG
Integer sigid_x = new Integer(sigid);
String rc = (String)(signame_cache.get(sigid_x));
if (rc==null)
{ // OK, get it from the database
ResultSet rs = stmt.executeQuery("SELECT signame FROM sigs WHERE sigid = " + sigid + ";");
if (!(rs.next()))
throw new DataException("SIG name not found for SIGID " + sigid);
rc = rs.getString(1);
signame_cache.put(sigid_x,rc);
} // end if
return rc;
} // end getSIGName
} // end class DescrStringCache
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
@@ -37,6 +152,8 @@ public class AuditRecord implements Audit
private String ip; // the IP address of the user
private String[] data; // the data values associated with the record
private String descr = null; // audit record description
private String uname = null; // user name of user
private String signame = null; // name of SIG
/*--------------------------------------------------------------------------------
* Constructors
@@ -124,6 +241,25 @@ public class AuditRecord implements Audit
} // end constructor
protected AuditRecord(ResultSet rs, DescrStringCache cache) throws SQLException, DataException
{
record = rs.getLong("record");
when = SQLUtil.getFullDateTime(rs,"on_date");
type = rs.getInt("event");
uid = rs.getInt("uid");
sigid = rs.getInt("sigid");
ip = rs.getString("ip");
data = new String[DATA_COUNT];
data[0] = rs.getString("data1");
data[1] = rs.getString("data2");
data[2] = rs.getString("data3");
data[3] = rs.getString("data4");
descr = cache.getDescription(type);
uname = cache.getUserName(uid);
signame = cache.getSIGName(sigid);
} // end constructor
/*--------------------------------------------------------------------------------
* Internal functions
*--------------------------------------------------------------------------------
@@ -141,7 +277,7 @@ public class AuditRecord implements Audit
private void setData(String data1, String data2, String data3, String data4)
{
data = new String[4];
data = new String[DATA_COUNT];
data[0] = data1;
data[1] = data2;
data[2] = data3;
@@ -150,7 +286,7 @@ public class AuditRecord implements Audit
} // end setData
/*--------------------------------------------------------------------------------
* External operations
* Implementations from interface AuditData
*--------------------------------------------------------------------------------
*/
@@ -202,6 +338,23 @@ public class AuditRecord implements Audit
} // end getDescription
public String getUserName()
{
return uname;
} // end getUserName
public String getSIGName()
{
return signame;
} // end getSIGName
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public void store(Connection conn) throws SQLException
{
if (record!=0)
@@ -238,4 +391,47 @@ public class AuditRecord implements Audit
} // end store
/*--------------------------------------------------------------------------------
* External static operations
*--------------------------------------------------------------------------------
*/
public static List getAuditRecords(Connection conn, int sigid, int offset, int count)
throws SQLException, DataException
{
Vector rc = new Vector();
DescrStringCache cache = new DescrStringCache(conn);
Statement stmt = conn.createStatement();
StringBuffer sql = new StringBuffer("SELECT * FROM audit");
if (sigid>0)
sql.append(" WHERE sigid = ").append(sigid);
sql.append(" ORDER BY on_date DESC LIMIT ").append(offset).append(", ").append(count).append(';');
ResultSet rs = stmt.executeQuery(sql.toString());
while (rs.next())
{ // load the results
AuditData dta = new AuditRecord(rs,cache);
rc.add(dta);
} // end while
return new ReadOnlyVector(rc);
} // end getAuditRecords
public static int getAuditRecordCount(Connection conn, int sigid) throws SQLException
{
Statement stmt = conn.createStatement();
StringBuffer sql = new StringBuffer("SELECT COUNT(*) FROM audit");
if (sigid>0)
sql.append(" WHERE sigid = ").append(sigid);
sql.append(';');
ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
throw new InternalStateError("query failure on getAuditRecordCount");
return rs.getInt(1);
} // end getAuditRecordCount
} // end class AuditRecord

View File

@@ -176,12 +176,26 @@ public class Account extends VeniceServlet
return new ErrorBox("Error","You cannot create a new account while logged in on an existing "
+ "one. You must log out first.",tgt);
// display the "Create Account" dialog
NewAccountDialog dlg = makeNewAccountDialog();
dlg.setEngine(engine);
dlg.setTarget(tgt);
dlg.setFieldValue("country","US");
return dlg;
final String yes = "yes";
if (yes.equals(request.getParameter("agree")))
{ // display the "Create Account" dialog
NewAccountDialog dlg = makeNewAccountDialog();
dlg.setEngine(engine);
dlg.setTarget(tgt);
dlg.setFieldValue("country","US");
return dlg;
} // end if
else
{ // display the account terms dialog
String[] choices = new String[2];
choices[0] = "account?cmd=C&agree=yes&tgt=" + URLEncoder.encode(tgt);
choices[1] = "top";
return new TextMessageDialog(TextMessageDialog.TYPE_ACCEPT_DECLINE,
rdat.getStockMessage("user-agreement-title"),
rdat.getStockMessage("user-agreement"),choices);
} // end else
} // end if ("C" command)

View File

@@ -254,6 +254,47 @@ public class SIGAdmin extends VeniceServlet
} // end if ("M" command)
if (cmd.equals("A"))
{ // "A" = "Display Audit Records"
try
{
int offset = 0;
try
{ // convert the offset parameter
String s_ofs = request.getParameter("ofs");
if (!StringUtil.isStringEmpty(s_ofs))
offset = Integer.parseInt(s_ofs);
} // end try
catch (NumberFormatException nfe)
{ // if it's untranslatable, set it at 0
offset = 0;
} // end catch
// generate the lists
List audit_list = sig.getAuditRecords(offset,engine.getNumAuditRecordsPerPage());
int audit_count = sig.getAuditRecordCount();
// return the audit viewer
return new AuditDataViewer(engine,audit_list,offset,audit_count,"Audit Records for SIG \""
+ sig.getName() + "\"","sigadmin?sig=" + sig.getSIGID() + "&cmd=A&ofs=%");
} // end try
catch (AccessError ae)
{ // you don't have access
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
catch (DataException de)
{ // something wrong in the database
return new ErrorBox("Database Error","Database error getting audit records: " + de.getMessage(),
on_error);
} // end catch
} // end if ("A" command)
if (cmd.equals("DEL"))
{ // "DEL" = "Delete SIG" (requires a confirmation)
if (!(sig.canDelete()))

View File

@@ -18,9 +18,11 @@
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.core.*;
import com.silverwrist.venice.servlets.format.*;
@@ -82,7 +84,50 @@ public class SystemAdmin extends VeniceServlet
if (logger.isDebugEnabled())
logger.debug("SystemAdmin/doGet command value = " + cmd);
// TODO: command handling
if (cmd.equals("A"))
{ // "A" = View System Audit Records
try
{ // get the list of audit records
AdminOperations adm = user.getAdminInterface();
int offset = 0;
try
{ // convert the offset parameter
String s_ofs = request.getParameter("ofs");
if (!StringUtil.isStringEmpty(s_ofs))
offset = Integer.parseInt(s_ofs);
} // end try
catch (NumberFormatException nfe)
{ // if it's untranslatable, set it at 0
offset = 0;
} // end catch
// generate the lists
List audit_list = adm.getAuditRecords(offset,engine.getNumAuditRecordsPerPage());
int audit_count = adm.getAuditRecordCount();
// return the audit viewer
setMyLocation(request,"sysadmin?cmd=A&ofs=" + offset);
return new AuditDataViewer(engine,audit_list,offset,audit_count,"System Audit Records",
"sysadmin?cmd=A&ofs=%");
} // end try
catch (AccessError ae)
{ // an access error generally means we're not an administrator
return new ErrorBox("Access Error","You do not have permission to administer the system.",null);
} // end catch
catch (DataException de)
{ // error pulling the audit records
return new ErrorBox("Database Error","Unable to retrieve audit records: " + de.getMessage(),
"sysadmin");
} // end catch
} // end if ("A" command)
// TODO: other command handling
if (!(user.hasAdminAccess()))
return new ErrorBox("Access Error","You do not have permission to administer the system.",null);

View File

@@ -0,0 +1,152 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at <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.io.*;
import java.util.*;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.core.*;
public class AuditDataViewer implements ContentRender
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private List audit_list;
private int offset;
private int total_count;
private int last_index;
private String title;
private String next_url;
private String prev_url;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public AuditDataViewer(VeniceEngine engine, List audit_list, int offset, int total_count, String title,
String template_url)
{
this.audit_list = audit_list;
this.offset = offset;
this.total_count = total_count;
int npage = engine.getNumAuditRecordsPerPage();
this.last_index = offset + npage;
if (this.last_index>total_count)
this.last_index = total_count;
this.title = title;
if (this.last_index<total_count)
this.next_url = StringUtil.replaceAllInstances(template_url,"%",String.valueOf(offset+npage));
else
this.next_url = null;
if (offset>0)
this.prev_url = StringUtil.replaceAllInstances(template_url,"%",String.valueOf(offset-npage));
else
this.prev_url = null;
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface VeniceContent
*--------------------------------------------------------------------------------
*/
public String getPageTitle(RenderData rdat)
{
return title;
} // end getPageTitle
/*--------------------------------------------------------------------------------
* Implementations from interface ContentRender
*--------------------------------------------------------------------------------
*/
public void renderHere(Writer out, RenderData rdat) throws IOException
{
rdat.writeContentHeader(out,title,null);
// Write the informational and navigational table
out.write("<TABLE WIDTH=\"100%\" BORDER=0><TR VALIGN=MIDDLE><TD ALIGN=LEFT>" + rdat.getStdFontTag(null,2));
out.write("\nDisplaying records <B>" + (offset+1) + "</B> to <B>" + last_index + "</B> of <B>"
+ total_count + "</B>\n");
out.write("</FONT></TD><TD ALIGN=RIGHT>\n");
if (prev_url==null)
out.write("<IMG SRC=\"" + rdat.getFullImagePath("bn_transparent.gif")
+ "\" ALT=\"\" WIDTH=80 HEIGHT=24 BORDER=0>\n");
else
out.write("<A HREF=\"" + rdat.getEncodedServletPath(prev_url) + "\"><IMG SRC=\""
+ rdat.getFullImagePath("bn_ar_previous.gif")
+ "\" ALT=\"Previous\" WIDTH=80 HEIGHT=24 BORDER=0></A>");
out.write("&nbsp;");
if (next_url==null)
out.write("<IMG SRC=\"" + rdat.getFullImagePath("bn_transparent.gif")
+ "\" ALT=\"\" WIDTH=80 HEIGHT=24 BORDER=0>\n");
else
out.write("<A HREF=\"" + rdat.getEncodedServletPath(next_url) + "\"><IMG SRC=\""
+ rdat.getFullImagePath("bn_ar_next.gif")
+ "\" ALT=\"Next\" WIDTH=80 HEIGHT=24 BORDER=0></A>");
out.write("\n</TD></TR></TABLE>\n");
// Start writing the table containing the actual audit records.
String tb_font = rdat.getStdFontTag(null,2);
out.write("<TABLE BORDER=0 CELLPADDING=0 CELLSPACING=3>\n");
out.write("<TR>\n<TH ALIGN=LEFT NOWRAP>" + tb_font + "<B>Date/Time</B></FONT></TH>\n");
out.write("<TH ALIGN=LEFT NOWRAP>" + tb_font + "<B>Description</B></FONT></TH>\n");
out.write("<TH ALIGN=LEFT NOWRAP>" + tb_font + "<B>User</B></FONT></TH>\n");
out.write("<TH ALIGN=LEFT NOWRAP>" + tb_font + "<B>SIG</B></FONT></TH>\n");
out.write("<TH ALIGN=LEFT NOWRAP>" + tb_font + "<B>IP Address</B></FONT></TH>\n");
out.write("<TH ALIGN=LEFT COLSPAN=4 NOWRAP>" + tb_font + "<B>Additional Data</B></FONT></TH>\n</TR>\n");
Iterator it = audit_list.iterator();
while (it.hasNext())
{ // display each record in turn
AuditData dat = (AuditData)(it.next());
out.write("<TR>\n<TD ALIGN=LEFT NOWRAP>" + tb_font
+ rdat.formatDateForDisplay(dat.getDateTime()) + "</FONT></TD>\n");
out.write("<TD ALIGN=LEFT NOWRAP>" + tb_font
+ StringUtil.encodeHTML(dat.getDescription()) + "</FONT></TD>\n");
out.write("<TD ALIGN=LEFT NOWRAP>" + tb_font
+ StringUtil.encodeHTML(dat.getUserName()) + "</FONT></TD>\n");
out.write("<TD ALIGN=LEFT NOWRAP>" + tb_font
+ StringUtil.encodeHTML(dat.getSIGName()) + "</FONT></TD>\n");
out.write("<TD ALIGN=LEFT NOWRAP>" + tb_font
+ StringUtil.encodeHTML(dat.getIPAddress()) + "</FONT></TD>\n");
for (int i=0; i<AuditData.DATA_COUNT; i++)
{ // write the data values
out.write("<TD ALIGN=LEFT NOWRAP>" + tb_font);
if (dat.getData(i)!=null)
out.write(StringUtil.encodeHTML(dat.getData(i)));
else
out.write("&nbsp;");
out.write("</FONT></TD>\n");
} // end for
out.write("</TR>\n");
} // end while
out.write("</TABLE>\n");
rdat.writeFooter(out);
} // end renderHere
} // end class AuditDataViewer

View File

@@ -36,6 +36,7 @@ public class CDTimeZoneListFormField extends CDPickListFormField
TimeZoneList()
{
array = TimeZone.getAvailableIDs();
Arrays.sort(array);
} // end constructor

View File

@@ -54,7 +54,6 @@ public class RenderConfig
private boolean want_comments;
private boolean allow_gzip;
private String font_face;
private String base_url;
private String image_url;
private String static_url;
private String site_logo;
@@ -130,17 +129,6 @@ public class RenderConfig
} // end if
DOMElementHelper paths_sect_h = new DOMElementHelper(paths_sect);
base_url = paths_sect_h.getSubElementText("base");
if (base_url==null)
{ // no <base/> tag - bail out now!
logger.fatal("<paths/> section has no <base/> element");
throw new ConfigException("no <base/> found in <paths/> section",paths_sect);
} // end if
if (logger.isDebugEnabled())
logger.debug("Base path: " + base_url);
image_url = paths_sect_h.getSubElementText("image");
if (image_url==null)
{ // no <image/> tag - bail out now!
@@ -284,14 +272,6 @@ public class RenderConfig
} // end isGZIPAllowed
String getFullServletPath(String name)
{
StringBuffer buf = new StringBuffer();
buf.append(base_url).append(name);
return buf.toString();
} // end getFullServletPath
String getFullImagePath(String name)
{
StringBuffer buf = new StringBuffer();
@@ -341,6 +321,14 @@ public class RenderConfig
} // end getStdFontTag
String getStdBaseFontTag(int size)
{
StringBuffer buf = new StringBuffer("<BASEFONT FACE=\"");
buf.append(font_face).append("\" SIZE=").append(size).append('>');
return buf.toString();
} // end getStdBaseFontTag
public String getRequiredBullet()
{
StringBuffer buf = new StringBuffer("<FONT FACE=\"");
@@ -351,9 +339,15 @@ public class RenderConfig
void writeFooter(Writer out) throws IOException
{
out.write("<HR WIDTH=\"80%\"><DIV ALIGN=\"CENTER\">\n<IMG SRC=\"");
out.write("<HR WIDTH=\"80%\">\n<TABLE ALIGN=CENTER BORDER=0 CELLPADDING=0 CELLSPACING=6><TR VALIGN=TOP>"
+ "\n<TD ALIGN=RIGHT>\n");
out.write(getStdFontTag(null,1));
out.write(getStockMessage("footer-text"));
out.write("</FONT>\n</TD>\n<TD ALIGN=LEFT>\n<A HREF=\"http://venice.sourceforge.net\" TARGET=\"_blank\">"
+ "<IMG SRC=\"");
out.write(getFullImagePath("powered-by-venice.gif"));
out.write("\" ALT=\"Powered by Venice\" WIDTH=140 HEIGHT=80 HSPACE=0 VSPACE=0>\n</DIV>\n");
out.write("\" ALT=\"Powered by Venice\" WIDTH=140 HEIGHT=80 BORDER=0 HSPACE=0 VSPACE=0></A>\n</TD>\n"
+ "</TR></TABLE>\n");
} // end writeFooter

View File

@@ -137,13 +137,15 @@ public class RenderData
public String getFullServletPath(String name)
{
return rconf.getFullServletPath(name);
StringBuffer buf = new StringBuffer(request.getContextPath());
buf.append('/').append(name);
return buf.toString();
} // end getFullServletPath
public String getEncodedServletPath(String name)
{
return response.encodeURL(rconf.getFullServletPath(name));
return response.encodeURL(this.getFullServletPath(name));
} // end getEncodedServletPath
@@ -171,6 +173,12 @@ public class RenderData
} // end getStdFontTag
public String getStdBaseFontTag(int size)
{
return rconf.getStdBaseFontTag(size);
} // end getStdBaseFontTag
public String getTitleTag(String specific)
{
return rconf.getTitleTag(specific);
@@ -306,7 +314,7 @@ public class RenderData
public void redirectTo(String servlet) throws IOException
{
String url = response.encodeRedirectURL(rconf.getFullServletPath(servlet));
String url = response.encodeRedirectURL(this.getFullServletPath(servlet));
response.sendRedirect(url);
} // end redirectTo

View File

@@ -36,6 +36,7 @@ public class SIGAdminTop extends ContentMenuPanel
addChoice("Set SIG Category","sigadmin?sig=$s&cmd=T");
addChoice("Set SIG Features","sigadmin?sig=$s&cmd=F");
addChoice("Membership Control","sigadmin?sig=$s&cmd=M");
addChoice("Display Audit Records","sigadmin?sig=$s&cmd=A");
// TODO: More options
addChoice("Delete SIG","sigadmin?sig=$s&cmd=DEL");

View File

@@ -34,6 +34,7 @@ public class SystemAdminTop extends ContentMenuPanel
addChoice("Set Global Parameters","TODO");
addChoice("View/Edit Banned Users","TODO");
addChoice("User Account Management","TODO");
addChoice("System Audit Logs","sysadmin?cmd=A");
} // end constructor

View File

@@ -0,0 +1,156 @@
/*
* 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.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.htmlcheck.*;
import com.silverwrist.venice.core.*;
public class TextMessageDialog implements ContentRender
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
// Dialog types
public static final int TYPE_ACCEPT_DECLINE = 0;
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private int type;
private String title;
private String text;
private String[] choices;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public TextMessageDialog(int type, String title, String text, String[] choices)
{
this.type = type;
this.title = title;
this.text = text;
this.choices = choices;
int nbutton = getNumButtons(type);
if (choices.length<nbutton)
throw new InternalStateError("insufficient elements in choices array");
} // end constructor
/*--------------------------------------------------------------------------------
* Internal overrideable operations
*--------------------------------------------------------------------------------
*/
protected int getNumButtons(int xtype)
{
if (xtype==TYPE_ACCEPT_DECLINE)
return 2;
throw new InternalStateError("invalid TextMessageDialog type :" + type);
} // end getNumButtons
protected String getImageNameForButton(int xtype, int ndx)
{
if (xtype==TYPE_ACCEPT_DECLINE)
{ // accept or decline
if (ndx==0)
return "bn_i_accept.gif";
else if (ndx==1)
return "bn_i_decline.gif";
throw new InternalStateError("invalid button index: " + ndx);
} // end if
throw new InternalStateError("invalid TextMessageDialog type :" + type);
} // end getImageNameForButton
protected String getAltTextForButton(int xtype, int ndx)
{
if (xtype==TYPE_ACCEPT_DECLINE)
{ // accept or decline
if (ndx==0)
return "I Accept";
else if (ndx==1)
return "I Decline";
throw new InternalStateError("invalid button index: " + ndx);
} // end if
throw new InternalStateError("invalid TextMessageDialog type :" + type);
} // end getImageNameForButton
/*--------------------------------------------------------------------------------
* Implementations from interface VeniceContent
*--------------------------------------------------------------------------------
*/
public String getPageTitle(RenderData rdat)
{
return title;
} // end getPageTitle
/*--------------------------------------------------------------------------------
* Implementations from interface ContentRender
*--------------------------------------------------------------------------------
*/
public void renderHere(Writer out, RenderData rdat) throws IOException
{
rdat.writeContentHeader(out,title,null);
out.write(rdat.getStdFontTag(null,2));
out.write("\n");
out.write(text);
out.write("</FONT><P>\n<DIV ALIGN=\"center\">\n");
int nbutton = getNumButtons(type);
for (int i=0; i<nbutton; i++)
{ // write out the individual buttons
if (i>0)
out.write("&nbsp;\n");
out.write("<A HREF=\"");
out.write(rdat.getEncodedServletPath(choices[i]));
out.write("\"><IMG SRC=\"");
out.write(rdat.getFullImagePath(getImageNameForButton(type,i)));
out.write("\" ALT=\"");
out.write(getAltTextForButton(type,i));
out.write("\" WIDTH=80 HEIGHT=24 BORDER=0></A>\n");
} // end for
out.write("</DIV>\n");
rdat.writeFooter(out);
} // end renderHere
} // end class TextMessageDialog