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

@ -5,8 +5,8 @@ Software requirements:
You must install the following software on your system: You must install the following software on your system:
* Java 2 SDK version 1.2.2. Venice is normally run with the Blackdown * Java 2 SDK version 1.2.2. Venice is normally run with the Blackdown
JDK port, available at http://www.blackdown.org. Version 1.3.x has JDK port, available at http://www.blackdown.org. Version 1.3.0 is
not been tested. being tested, and will likely be required sometime in the future.
* Java API for XML Parsing (JAXP) version 1.0.1, available from * Java API for XML Parsing (JAXP) version 1.0.1, available from
http://java.sun.com. http://java.sun.com.
* Java Secure Socket Extension (JSSE) version 1.0.2, available from * Java Secure Socket Extension (JSSE) version 1.0.2, available from
@ -15,7 +15,8 @@ Software requirements:
* JavaMail API version 1.2, available from http://java.sun.com. * JavaMail API version 1.2, available from http://java.sun.com.
* JavaBeans Activation Framework (JAF) version 1.0.1, available from * JavaBeans Activation Framework (JAF) version 1.0.1, available from
http://java.sun.com. (Required by JavaMail.) http://java.sun.com. (Required by JavaMail.)
* Apache Jakarta LOG4J library, available from http://www.log4j.org. * Apache Jakarta LOG4J library 1.0.x, available from
http://jakarta.apache.org.
* MySQL 3.23.x (get the most recent 3.23 version), available from * MySQL 3.23.x (get the most recent 3.23 version), available from
http://www.mysql.com. http://www.mysql.com.
* The MM.MySQL JDBC drivers version 2.0.3, available from XXXX. * The MM.MySQL JDBC drivers version 2.0.3, available from XXXX.

2
TODO
View File

@ -2,11 +2,13 @@ Lots!
- Unimplemented functions on the SIG Administration page: - Unimplemented functions on the SIG Administration page:
Set SIG Features (sigadmin, command=F) Set SIG Features (sigadmin, command=F)
View Audit Records (needs to be added)
- Unimplemented functions in the system admin menu: - Unimplemented functions in the system admin menu:
Set Global Parameters Set Global Parameters
View/Edit Banned Users View/Edit Banned Users
User Account Management User Account Management
View Audit Records (needs to be added)
(More stuff needs to be added, I'm just not sure what.) (More stuff needs to be added, I'm just not sure what.)
- Should we provide the sysadmin the ability to disable SIG creation for - Should we provide the sysadmin the ability to disable SIG creation for

View File

@ -37,33 +37,53 @@
<!-- Used to configure URL paths to various global resources. --> <!-- Used to configure URL paths to various global resources. -->
<paths> <paths>
<!-- Base URL for all servlets on this server. MUST include the trailing slash. -->
<base>http://delenn:8080/venice/</base>
<!-- Base URL for all images loaded by the server code. MUST include the trailing slash. --> <!-- Base URL for all images loaded by the server code. MUST include the trailing slash. -->
<image>http://delenn:8080/venice/images/</image> <image>/venice/images/</image>
<!-- Base URL for all static pages linked to by the engine. MUST include the trailing slash. --> <!-- Base URL for all static pages linked to by the engine. MUST include the trailing slash. -->
<static>http://delenn:8080/venice/static/</static> <static>/venice/static/</static>
<!-- The fully-qualified URL to the site logo. The image should be 140x80 pixels. --> <!-- The site-relative URL to the site logo. The image should be 140x80 pixels. -->
<site-logo>http://delenn:8080/venice/images/powered-by-venice.gif</site-logo> <site-logo>/venice/images/powered-by-venice.gif</site-logo>
</paths> </paths>
<!-- Contains standard messages displayed by front end --> <!-- Contains standard messages displayed by front end -->
<messages> <messages>
<!-- The message displayed at the top of "top" when you're not logged in --> <!-- The message displayed at the top of "top" when you're not logged in (HTML). -->
<welcome> <welcome>
Welcome to the Venice Web Communities System. To get the most out of this site, you should log in or create <![CDATA[
an account, using one of the links above. Welcome to the <B>Venice Web Communities System</B>. To get the most out of this site, you should log in
or create an account, using one of the links above.
]]>
</welcome> </welcome>
<!-- The headline for the welcome message --> <!-- The headline for the welcome message. -->
<welcome-top>Welcome to Venice</welcome-top> <welcome-top>Welcome to Venice</welcome-top>
<!-- The headline for the "currents" box --> <!-- The headline for the "currents" box. -->
<currents-top>Venice Currents</currents-top> <currents-top>Venice Currents</currents-top>
<!-- The text displayed within the page footer (HTML). -->
<footer-text>
<![CDATA[
All trademarks and copyrights on this page are owned by their respective companies.<BR>
All messages posted by users on this page are owned by those users.<BR>
The rest: Copyright &copy; 2001 <A HREF="http://www.silverwrist.com">Silverwrist Design Studios</A>,
All Rights Reserved.<BR>
See our <A HREF="/TODO">Policy Page</A> for our copyright and privacy policies.
]]>
</footer-text>
<!-- The thing that users must click on "I Accept" for before they can create an account -->
<user-agreement>
<![CDATA[
Text of this agreement is TBD.
]]>
</user-agreement>
<!-- Title displayed for above. -->
<user-agreement-title>Venice User Agreement</user-agreement-title>
</messages> </messages>
</render-config> </render-config>

View File

@ -77,12 +77,15 @@
<messages> <messages>
<!-- A "signature" that gets appended to emailed messages. --> <!-- A "signature" that gets appended to emailed messages. -->
<signature> <signature>
Venice - community services, conferencing and more. http://venice.sourceforge.net <![CDATA[
Venice - community services, conferencing and more. <http://venice.sourceforge.net>
]]>
</signature> </signature>
<!-- This is the message sent out with the email confirmation number. --> <!-- This is the message sent out with the email confirmation number. -->
<!-- Parameters: $USERNAME - account user name, $CONFNUM - confirmation number --> <!-- Parameters: $USERNAME - account user name, $CONFNUM - confirmation number -->
<email-confirm> <email-confirm>
<![CDATA[
Welcome to the Venice conferencing system! In order to fully activate your Welcome to the Venice conferencing system! In order to fully activate your
account after you register or change your E-mail address, you must provide a account after you register or change your E-mail address, you must provide a
confirmation number to the system. Please enter this number into the "Confirm confirmation number to the system. Please enter this number into the "Confirm
@ -93,11 +96,13 @@ Your confirmation number for your account "$USERNAME" is $CONFNUM.
Thank you, and enjoy the Venice conferencing system! Thank you, and enjoy the Venice conferencing system!
-- The Management -- The Management
]]>
</email-confirm> </email-confirm>
<!-- This is the "password reminder" message. --> <!-- This is the "password reminder" message. -->
<!-- Parameters: $USERNAME - account user name, $REMINDER - password reminder --> <!-- Parameters: $USERNAME - account user name, $REMINDER - password reminder -->
<reminder> <reminder>
<![CDATA[
Here is the password reminder for your account "$USERNAME" as you requested: Here is the password reminder for your account "$USERNAME" as you requested:
$REMINDER $REMINDER
@ -106,15 +111,17 @@ If this reminder is not sufficient for you to remember what your password is,
please contact the server administrator for further assistance. please contact the server administrator for further assistance.
-- The Management -- The Management
]]>
</reminder> </reminder>
<!-- Invitation message to a public SIG --> <!-- Invitation message to a public SIG -->
<!-- Parameters: $SIGNAME = name of SIG, $SIGALIAS = alias of SIG, $PERSONAL = personal message, <!-- Parameters: $SIGNAME = name of SIG, $SIGALIAS = alias of SIG, $PERSONAL = personal message,
$FULLNAME = name of inviter, $USERNAME = user name of inviter --> $FULLNAME = name of inviter, $USERNAME = user name of inviter -->
<invite-public> <invite-public>
<![CDATA[
Hi! I would like to invite you to join the "$SIGNAME" Special Interest Group (SIG) on the Venice Hi! I would like to invite you to join the "$SIGNAME" Special Interest Group (SIG) on the Venice
conferencing system. To do so, you must register as a user, which is absolutely free! Just point conferencing system. To do so, you must register as a user, which is absolutely free! Just point
your Web browser at &lt;http://delenn:8080/venice/sig/$SIGALIAS&gt; and click the "Create Account" link your Web browser at <http://delenn:8080/venice/sig/$SIGALIAS> and click the "Create Account" link
at the top of the page, or click the "Log In" link if you already have a Venice account. Once you have at the top of the page, or click the "Log In" link if you already have a Venice account. Once you have
completed the process, click the "Join Now" button. You will then be able to take part in the conferences completed the process, click the "Join Now" button. You will then be able to take part in the conferences
that are going on in the SIG. that are going on in the SIG.
@ -124,6 +131,7 @@ $PERSONAL
Hope to see you in "$SIGNAME" soon! Hope to see you in "$SIGNAME" soon!
-- $FULLNAME (Venice user ID: $USERNAME) -- $FULLNAME (Venice user ID: $USERNAME)
]]>
</invite-public> </invite-public>
<!-- Invitation message to a private SIG --> <!-- Invitation message to a private SIG -->
@ -131,9 +139,10 @@ Hope to see you in "$SIGNAME" soon!
$PERSONAL = personal message, $FULLNAME = name of inviter, $PERSONAL = personal message, $FULLNAME = name of inviter,
$USERNAME = user name of inviter --> $USERNAME = user name of inviter -->
<invite-private> <invite-private>
<![CDATA[
Hi! I would like to invite you to join the "$SIGNAME" Special Interest Group (SIG) on the Venice Hi! I would like to invite you to join the "$SIGNAME" Special Interest Group (SIG) on the Venice
conferencing system. To do so, you must register as a user, which is absolutely free! Just point conferencing system. To do so, you must register as a user, which is absolutely free! Just point
your Web browser at &lt;http://delenn:8080/venice/sig/$SIGALIAS&gt; and click the "Create Account" link your Web browser at <http://delenn:8080/venice/sig/$SIGALIAS> and click the "Create Account" link
at the top of the page, or click the "Log In" link if you already have a Venice account. Once you have at the top of the page, or click the "Log In" link if you already have a Venice account. Once you have
completed the process, click the "Join Now" button. You will be prompted for the "password" for this completed the process, click the "Join Now" button. You will be prompted for the "password" for this
SIG, which is "$JOINKEY". You will then be able to take part in the conferences that are going on in the SIG. SIG, which is "$JOINKEY". You will then be able to take part in the conferences that are going on in the SIG.
@ -143,6 +152,7 @@ $PERSONAL
Hope to see you in "$SIGNAME" soon! Hope to see you in "$SIGNAME" soon!
-- $FULLNAME (Venice user ID: $USERNAME) -- $FULLNAME (Venice user ID: $USERNAME)
]]>
</invite-private> </invite-private>
<!-- Subject line for invitation messages --> <!-- Subject line for invitation messages -->

View File

@ -205,6 +205,11 @@
<servlet-class>com.silverwrist.util.test.FormDataTest</servlet-class> <servlet-class>com.silverwrist.util.test.FormDataTest</servlet-class>
</servlet> </servlet>
<servlet>
<servlet-name>dumpall</servlet-name>
<servlet-class>com.silverwrist.util.test.DumpAll</servlet-class>
</servlet>
<!-- Mappings from URLs in the server to Venice servlets. --> <!-- Mappings from URLs in the server to Venice servlets. -->
<servlet-mapping> <servlet-mapping>
<servlet-name>top</servlet-name> <servlet-name>top</servlet-name>
@ -297,10 +302,19 @@
<url-pattern>/testformdata</url-pattern> <url-pattern>/testformdata</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping>
<servlet-name>dumpall</servlet-name>
<url-pattern>/dumpall</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>dumpall</servlet-name>
<url-pattern>/dump/*</url-pattern>
</servlet-mapping>
<!-- Global parameters for the HTTP session --> <!-- Global parameters for the HTTP session -->
<session-config> <session-config>
<session-timeout>60</session-timeout> <!-- 1 hour --> <session-timeout>60</session-timeout> <!-- 1 hour -->
</session-config> </session-config>
</web-app> </web-app>

View File

@ -39,7 +39,8 @@ CREATE TABLE globals (
max_search_page INT NOT NULL, max_search_page INT NOT NULL,
max_sig_mbr_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 fp_posts INT NOT NULL,
num_audit_page INT NOT NULL
); );
# The audit records table. Most "major" events add a record to this table. # The audit records table. Most "major" events add a record to this table.
@ -1324,8 +1325,8 @@ INSERT INTO refsigftr (ftr_code, is_default, is_locked, is_hidden, require_read,
# Initialize the system globals table. # 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, INSERT INTO globals (posts_per_page, old_posts_at_top, max_search_page, max_sig_mbr_page, max_conf_mbr_page,
fp_posts) fp_posts, num_audit_page)
VALUES (20, 2, 20, 50, 50, 10); VALUES (20, 2, 20, 50, 50, 10, 100);
# Add the 'Anonymous Honyak' user to the users table. # Add the 'Anonymous Honyak' user to the users table.
# (Do 'SELECT * FROM users WHERE is_anon = 1' to retrieve the AC user details.) # (Do 'SELECT * FROM users WHERE is_anon = 1' to retrieve the AC user details.)

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; package com.silverwrist.venice.core;
import java.util.List;
public interface AdminOperations 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 } // 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 boolean canSendInvitation();
public abstract List getAuditRecords(int offset, int count) throws AccessError, DataException;
public abstract int getAuditRecordCount() throws AccessError, DataException;
} // end interface SIGContext } // end interface SIGContext

View File

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

View File

@ -18,9 +18,11 @@
package com.silverwrist.venice.core.impl; package com.silverwrist.venice.core.impl;
import java.sql.*; import java.sql.*;
import java.util.*;
import org.apache.log4j.*; import org.apache.log4j.*;
import com.silverwrist.venice.core.*; import com.silverwrist.venice.core.*;
import com.silverwrist.venice.db.*; import com.silverwrist.venice.db.*;
import com.silverwrist.venice.security.AuditRecord;
class AdminOperationsImpl implements AdminOperations 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 } // end class AdminOperationsImpl

View File

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

View File

@ -22,6 +22,7 @@ import java.util.*;
import org.apache.log4j.*; import org.apache.log4j.*;
import com.silverwrist.util.StringUtil; import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.db.*; import com.silverwrist.venice.db.*;
import com.silverwrist.venice.security.AuditRecord;
import com.silverwrist.venice.security.Capability; import com.silverwrist.venice.security.Capability;
import com.silverwrist.venice.security.DefaultLevels; import com.silverwrist.venice.security.DefaultLevels;
import com.silverwrist.venice.core.*; import com.silverwrist.venice.core.*;
@ -1271,6 +1272,78 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
} // end canSendInvitation } // 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 * Implementations from interface UserBackend
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------

View File

@ -336,7 +336,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
{ {
final String query = final String query =
"SELECT posts_per_page, old_posts_at_top, max_search_page, max_sig_mbr_page, max_conf_mbr_page, " "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); ResultSet rs = stmt.executeQuery(query);
if (!(rs.next())) if (!(rs.next()))
throw new DataException("Globals table does not appear to be loaded!"); 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_MAXSIGMEMBERDISPLAY] = rs.getInt(4);
gp_ints[IP_MAXCONFMEMBERDISPLAY] = rs.getInt(5); gp_ints[IP_MAXCONFMEMBERDISPLAY] = rs.getInt(5);
gp_ints[IP_NUMFRONTPAGEPOSTS] = rs.getInt(6); gp_ints[IP_NUMFRONTPAGEPOSTS] = rs.getInt(6);
gp_ints[IP_NUMAUDITRECSPERPAGE] = rs.getInt(7);
} // end loadDefaults } // end loadDefaults
@ -492,7 +493,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end catch } // end catch
// Allocate the global parameter arrays. // 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 // initialize anything that requires us to pull from the database
Connection conn = null; Connection conn = null;
@ -1436,6 +1437,12 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getPublishedMessages } // end getPublishedMessages
public int getNumAuditRecordsPerPage()
{
return gp_ints[IP_NUMAUDITRECSPERPAGE];
} // end getNumAuditRecordsPerPage
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Implementations from interface EngineBackend * 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 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License. * 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>, * 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 * 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.sql.*;
import java.util.*; import java.util.*;
import com.silverwrist.venice.db.SQLUtil; import com.silverwrist.venice.db.SQLUtil;
import com.silverwrist.venice.core.AuditData;
import com.silverwrist.venice.core.DataException;
import com.silverwrist.venice.core.InternalStateError; 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 * Attributes
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -37,6 +152,8 @@ public class AuditRecord implements Audit
private String ip; // the IP address of the user private String ip; // the IP address of the user
private String[] data; // the data values associated with the record private String[] data; // the data values associated with the record
private String descr = null; // audit record description private String descr = null; // audit record description
private String uname = null; // user name of user
private String signame = null; // name of SIG
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Constructors * Constructors
@ -124,6 +241,25 @@ public class AuditRecord implements Audit
} // end constructor } // 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 * Internal functions
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -141,7 +277,7 @@ public class AuditRecord implements Audit
private void setData(String data1, String data2, String data3, String data4) private void setData(String data1, String data2, String data3, String data4)
{ {
data = new String[4]; data = new String[DATA_COUNT];
data[0] = data1; data[0] = data1;
data[1] = data2; data[1] = data2;
data[2] = data3; data[2] = data3;
@ -150,7 +286,7 @@ public class AuditRecord implements Audit
} // end setData } // end setData
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* External operations * Implementations from interface AuditData
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
*/ */
@ -202,6 +338,23 @@ public class AuditRecord implements Audit
} // end getDescription } // 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 public void store(Connection conn) throws SQLException
{ {
if (record!=0) if (record!=0)
@ -238,4 +391,47 @@ public class AuditRecord implements Audit
} // end store } // 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 } // 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 " return new ErrorBox("Error","You cannot create a new account while logged in on an existing "
+ "one. You must log out first.",tgt); + "one. You must log out first.",tgt);
// display the "Create Account" dialog final String yes = "yes";
NewAccountDialog dlg = makeNewAccountDialog(); if (yes.equals(request.getParameter("agree")))
dlg.setEngine(engine); { // display the "Create Account" dialog
dlg.setTarget(tgt); NewAccountDialog dlg = makeNewAccountDialog();
dlg.setFieldValue("country","US"); dlg.setEngine(engine);
return dlg; 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) } // end if ("C" command)

View File

@ -254,6 +254,47 @@ public class SIGAdmin extends VeniceServlet
} // end if ("M" command) } // 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")) if (cmd.equals("DEL"))
{ // "DEL" = "Delete SIG" (requires a confirmation) { // "DEL" = "Delete SIG" (requires a confirmation)
if (!(sig.canDelete())) if (!(sig.canDelete()))

View File

@ -18,9 +18,11 @@
package com.silverwrist.venice.servlets; package com.silverwrist.venice.servlets;
import java.io.*; import java.io.*;
import java.util.*;
import javax.servlet.*; import javax.servlet.*;
import javax.servlet.http.*; import javax.servlet.http.*;
import org.apache.log4j.*; import org.apache.log4j.*;
import com.silverwrist.util.StringUtil;
import com.silverwrist.venice.core.*; import com.silverwrist.venice.core.*;
import com.silverwrist.venice.servlets.format.*; import com.silverwrist.venice.servlets.format.*;
@ -82,7 +84,50 @@ public class SystemAdmin extends VeniceServlet
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("SystemAdmin/doGet command value = " + cmd); 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())) if (!(user.hasAdminAccess()))
return new ErrorBox("Access Error","You do not have permission to administer the system.",null); 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() TimeZoneList()
{ {
array = TimeZone.getAvailableIDs(); array = TimeZone.getAvailableIDs();
Arrays.sort(array);
} // end constructor } // end constructor

View File

@ -54,7 +54,6 @@ public class RenderConfig
private boolean want_comments; private boolean want_comments;
private boolean allow_gzip; private boolean allow_gzip;
private String font_face; private String font_face;
private String base_url;
private String image_url; private String image_url;
private String static_url; private String static_url;
private String site_logo; private String site_logo;
@ -130,17 +129,6 @@ public class RenderConfig
} // end if } // end if
DOMElementHelper paths_sect_h = new DOMElementHelper(paths_sect); 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"); image_url = paths_sect_h.getSubElementText("image");
if (image_url==null) if (image_url==null)
{ // no <image/> tag - bail out now! { // no <image/> tag - bail out now!
@ -284,14 +272,6 @@ public class RenderConfig
} // end isGZIPAllowed } // 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) String getFullImagePath(String name)
{ {
StringBuffer buf = new StringBuffer(); StringBuffer buf = new StringBuffer();
@ -341,6 +321,14 @@ public class RenderConfig
} // end getStdFontTag } // 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() public String getRequiredBullet()
{ {
StringBuffer buf = new StringBuffer("<FONT FACE=\""); StringBuffer buf = new StringBuffer("<FONT FACE=\"");
@ -351,9 +339,15 @@ public class RenderConfig
void writeFooter(Writer out) throws IOException 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(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 } // end writeFooter

View File

@ -137,13 +137,15 @@ public class RenderData
public String getFullServletPath(String name) public String getFullServletPath(String name)
{ {
return rconf.getFullServletPath(name); StringBuffer buf = new StringBuffer(request.getContextPath());
buf.append('/').append(name);
return buf.toString();
} // end getFullServletPath } // end getFullServletPath
public String getEncodedServletPath(String name) public String getEncodedServletPath(String name)
{ {
return response.encodeURL(rconf.getFullServletPath(name)); return response.encodeURL(this.getFullServletPath(name));
} // end getEncodedServletPath } // end getEncodedServletPath
@ -171,6 +173,12 @@ public class RenderData
} // end getStdFontTag } // end getStdFontTag
public String getStdBaseFontTag(int size)
{
return rconf.getStdBaseFontTag(size);
} // end getStdBaseFontTag
public String getTitleTag(String specific) public String getTitleTag(String specific)
{ {
return rconf.getTitleTag(specific); return rconf.getTitleTag(specific);
@ -306,7 +314,7 @@ public class RenderData
public void redirectTo(String servlet) throws IOException public void redirectTo(String servlet) throws IOException
{ {
String url = response.encodeRedirectURL(rconf.getFullServletPath(servlet)); String url = response.encodeRedirectURL(this.getFullServletPath(servlet));
response.sendRedirect(url); response.sendRedirect(url);
} // end redirectTo } // 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 Category","sigadmin?sig=$s&cmd=T");
addChoice("Set SIG Features","sigadmin?sig=$s&cmd=F"); addChoice("Set SIG Features","sigadmin?sig=$s&cmd=F");
addChoice("Membership Control","sigadmin?sig=$s&cmd=M"); addChoice("Membership Control","sigadmin?sig=$s&cmd=M");
addChoice("Display Audit Records","sigadmin?sig=$s&cmd=A");
// TODO: More options // TODO: More options
addChoice("Delete SIG","sigadmin?sig=$s&cmd=DEL"); 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("Set Global Parameters","TODO");
addChoice("View/Edit Banned Users","TODO"); addChoice("View/Edit Banned Users","TODO");
addChoice("User Account Management","TODO"); addChoice("User Account Management","TODO");
addChoice("System Audit Logs","sysadmin?cmd=A");
} // end constructor } // 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

View File

@ -43,6 +43,7 @@ private static void renderMenu(HttpSession session, java.io.Writer out, RenderDa
<HTML> <HTML>
<HEAD> <HEAD>
<%= rdat.getTitleTag(basedat.getTitle(rdat)) %> <%= rdat.getTitleTag(basedat.getTitle(rdat)) %>
<%= rdat.getStdBaseFontTag(3) %>
</HEAD> </HEAD>
<BODY BGCOLOR="#9999FF"> <BODY BGCOLOR="#9999FF">

View File

@ -28,7 +28,7 @@
<% if (rdat.useHTMLComments()) { %><!-- Top content panel --><% } %> <% if (rdat.useHTMLComments()) { %><!-- Top content panel --><% } %>
<% if (data.displayWelcome()) { %> <% if (data.displayWelcome()) { %>
<% rdat.writeContentHeader(out,rdat.getStockMessage("welcome-top"),null); %> <% rdat.writeContentHeader(out,rdat.getStockMessage("welcome-top"),null); %>
<%= rdat.getStdFontTag(null,1) %><% rdat.writeStockMessage(out,"welcome"); %></FONT><P> <%= rdat.getStdFontTag(null,1) %><%= rdat.getStockMessage(out,"welcome"); %></FONT><P>
<% } // end if %> <% } // end if %>
<% rdat.writeContentHeader(out,rdat.getStockMessage("currents-top"),null); %> <% rdat.writeContentHeader(out,rdat.getStockMessage("currents-top"),null); %>
<% int ntp = data.getNumTopPosts(); %> <% int ntp = data.getNumTopPosts(); %>

BIN
web/images/bn_i_accept.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 B

BIN
web/images/bn_i_decline.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 944 B