fully implemented conference membership management and delete conference -

now almost all the conference functionality is in place
This commit is contained in:
Eric J. Bowersox 2001-02-15 04:28:00 +00:00
parent 0070e4fb44
commit 36f7c7f10f
28 changed files with 1978 additions and 146 deletions

7
TODO
View File

@ -31,12 +31,9 @@ Lots!
- Functions still to do on conferencing "topics" page: - Functions still to do on conferencing "topics" page:
Add Conference To Hotlist Add Conference To Hotlist
- Functions still to do on "manage conference" page:
Manage members
Delete conference
- We need a "manage" button at conference list level so we can use that to - We need a "manage" button at conference list level so we can use that to
manage the ordering of conferences. manage the ordering of conferences. This operation should be accessible
only to users with "create" privilege on the SIG.
- Implement conference hotlist for users. - Implement conference hotlist for users.

View File

@ -35,7 +35,10 @@ USE venice;
# in the XML config file. This table has ONLY ONE ROW! # in the XML config file. This table has ONLY ONE ROW!
CREATE TABLE globals ( CREATE TABLE globals (
posts_per_page INT NOT NULL, posts_per_page INT NOT NULL,
old_posts_at_top INT NOT NULL old_posts_at_top INT NOT NULL,
max_search_page INT NOT NULL,
max_sig_mbr_page INT NOT NULL,
max_conf_mbr_page INT NOT NULL
); );
# 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.
@ -429,6 +432,7 @@ INSERT INTO refaudit (type, descr) VALUES
(312, 'Scribble Message'), (312, 'Scribble Message'),
(313, 'Nuke Message'), (313, 'Nuke Message'),
(314, 'Upload Message Attachment'), (314, 'Upload Message Attachment'),
(315, 'Delete Conference'),
(9999999, 'DUMMY'); (9999999, 'DUMMY');
# The ISO 3166 two-letter country codes. Source is # The ISO 3166 two-letter country codes. Source is
@ -1291,8 +1295,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) INSERT INTO globals (posts_per_page, old_posts_at_top, max_search_page, max_sig_mbr_page, max_conf_mbr_page)
VALUES (20, 2); VALUES (20, 2, 20, 50, 50);
# 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,101 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.util;
import java.util.Vector;
public class ParallelRunQueue implements Runnable
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private Thread[] thrds;
private Vector queue;
private int priority;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public ParallelRunQueue(int nthread)
{
thrds = new Thread[nthread];
for (int i=0; i<nthread; i++)
thrds[i] = null;
queue = new Vector();
priority = Thread.currentThread().getPriority();
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface Runnable
*--------------------------------------------------------------------------------
*/
public void run()
{
while (queue.size()>0)
{ // unqueue a new Runnable
Runnable r = (Runnable)(queue.remove(0));
for (int i=0; i<thrds.length; i++)
{ // scan through our threads list...
if ((thrds[i]==null) || !(thrds[i].isAlive()))
{ // a worker thread is available - start it running
thrds[i] = new Thread(r);
thrds[i].setPriority(priority);
thrds[i].start();
return;
} // end if
} // end for
r.run(); // if all else fails, run it ourselves
} // end while
} // end run
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public void queue(Runnable r)
{
for (int i=0; i<thrds.length; i++)
{ // scan through our threads list...
if ((thrds[i]==null) || !(thrds[i].isAlive()))
{ // a worker thread is available - start it running
thrds[i] = new Thread(r);
thrds[i].setPriority(priority);
thrds[i].start();
return;
} // end if
} // end for
queue.add(r); // if all else fails, queue it up
} // end queue
} // end class ParallelRunQueue

View File

@ -84,6 +84,8 @@ public interface ConferenceContext
public abstract void removeAlias(String alias) throws DataException, AccessError; public abstract void removeAlias(String alias) throws DataException, AccessError;
public abstract void setMembership(int uid, int grant_level) throws DataException, AccessError;
public abstract void addMember(int uid, boolean as_host) throws DataException, AccessError; public abstract void addMember(int uid, boolean as_host) throws DataException, AccessError;
public abstract void removeMember(int uid) throws DataException, AccessError; public abstract void removeMember(int uid) throws DataException, AccessError;
@ -117,18 +119,26 @@ public interface ConferenceContext
public abstract HTMLChecker getNewTopicPreviewChecker(); public abstract HTMLChecker getNewTopicPreviewChecker();
public abstract void fixSeen() throws DataException; public abstract void fixSeen() throws DataException, AccessError;
public abstract List getActivePosters(int skip, int limit) throws DataException; public abstract List getActivePosters(int skip, int limit) throws DataException, AccessError;
public abstract List getActivePosters(int limit) throws DataException; public abstract List getActivePosters(int limit) throws DataException, AccessError;
public abstract List getActivePosters() throws DataException; public abstract List getActivePosters() throws DataException, AccessError;
public abstract List getActiveReaders(int skip, int limit) throws DataException; public abstract List getActiveReaders(int skip, int limit) throws DataException, AccessError;
public abstract List getActiveReaders(int limit) throws DataException; public abstract List getActiveReaders(int limit) throws DataException, AccessError;
public abstract List getActiveReaders() throws DataException; public abstract List getActiveReaders() throws DataException, AccessError;
public abstract List getMemberList() throws DataException, AccessError;
public abstract int getMemberLevel(int uid) throws DataException, AccessError;
public abstract void delete() throws DataException, AccessError;
public abstract boolean canDeleteConference();
} // end interface ConferenceContext } // end interface ConferenceContext

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
@ -21,7 +21,7 @@ import java.util.BitSet;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
public interface SIGContext public interface SIGContext extends SearchMode
{ {
public static final int HIDE_NONE = 0; public static final int HIDE_NONE = 0;
public static final int HIDE_DIRECTORY = 1; public static final int HIDE_DIRECTORY = 1;
@ -144,4 +144,11 @@ public interface SIGContext
public abstract boolean canCreateConference(); public abstract boolean canCreateConference();
public abstract List searchForMembers(int field, int mode, String term, int offset, int count)
throws DataException;
public abstract int getSearchMemberCount(int field, int mode, String term) throws DataException;
public abstract List getMemberList() throws DataException;
} // end interface SIGContext } // end interface SIGContext

View File

@ -37,4 +37,6 @@ public interface UserFound
public abstract int getLevel(); public abstract int getLevel();
public abstract UserFound createNewLevel(int level);
} // end interface UserFound } // end interface UserFound

View File

@ -67,4 +67,8 @@ public interface VeniceEngine extends SearchMode
public abstract int getNumOldPostsBeforeNew(); public abstract int getNumOldPostsBeforeNew();
public abstract int getMaxNumConferenceMembersDisplay();
public abstract int getMaxNumSIGMembersDisplay();
} // end interface VeniceEngine } // end interface VeniceEngine

View File

@ -0,0 +1,131 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.core.impl;
import java.sql.*;
import org.apache.log4j.*;
import com.silverwrist.util.ParallelRunQueue;
import com.silverwrist.venice.db.*;
import com.silverwrist.venice.core.InternalStateError;
class BackgroundConferencePurge implements Runnable
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Category logger = Category.getInstance(BackgroundConferencePurge.class.getName());
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private DataPool datapool;
private int confid;
private int num_topics;
private int max_topicid;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
BackgroundConferencePurge(DataPool datapool, int confid, int num_topics, int max_topicid)
{
this.datapool = datapool;
this.confid = confid;
this.num_topics = num_topics;
this.max_topicid = max_topicid;
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface Runnable
*--------------------------------------------------------------------------------
*/
public void run()
{
if (logger.isDebugEnabled())
logger.debug("BackgroundConferencePurge running on conference #" + confid);
Connection conn = null; // pooled database connection
ParallelRunQueue rq = new ParallelRunQueue(2);
try
{ // get a database connection from the pool
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// purge out some auxiliary tables first
stmt.executeUpdate("DELETE FROM confmember WHERE confid = " + confid + ";");
stmt.executeUpdate("DELETE FROM confsettings WHERE confid = " + confid + ";");
stmt.executeUpdate("DELETE FROM confhotlist WHERE confid = " + confid + ";");
stmt.executeUpdate("DELETE FROM confbozo WHERE confid = " + confid + ";");
// look up all the topic IDs that are present in this conference
int[] topicids = new int[num_topics];
StringBuffer sql = new StringBuffer("SELECT topicid FROM topics WHERE confid = ");
sql.append(confid).append(" AND topicid <= ").append(max_topicid).append(" ORDER BY topicid;");
ResultSet rs = stmt.executeQuery(sql.toString());
int topics = 0;
while (rs.next())
topicids[topics++] = rs.getInt(1);
for (int i=0; i<topics; i++)
{ // delete the topic header and settings rows first
stmt.executeUpdate("DELETE FROM topics WHERE topicid = " + topicids[i] + ";");
stmt.executeUpdate("DELETE FROM topicsettings WHERE topicid = " + topicids[i] + ";");
// figure out how many posts are in this topic and create a BackgroundTopicPurge.
sql.setLength(0);
sql.append("SELECT COUNT(*), MAX(postid) FROM posts WHERE topicid = ").append(topicids[i]).append(';');
rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
throw new InternalStateError("BackgroundConferencePurge.run screwup on post SELECT");
rq.queue(new BackgroundTopicPurge(datapool,topicids[i],rs.getInt(1),rs.getLong(2)));
} // end for
if (logger.isDebugEnabled())
logger.debug("BackgroundConferencePurge basic delete complete for conf #" + confid);
} // end try
catch (SQLException e)
{ // on an error, just die
logger.error("BackgroundConferencePurge FATAL EXCEPTION purging #" + confid + ": " + e.getMessage(),e);
return;
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
rq.run(); // now run the parallel queue to finish processing
if (logger.isDebugEnabled())
logger.debug("BackgroundConferencePurge COMPLETE for conf #" + confid);
} // end run
} // end class BackgroundConferencePurge

View File

@ -57,6 +57,7 @@ class ConferenceCoreData implements ConferenceData
private String description; // the conference's description private String description; // the conference's description
private String cached_alias = null; // the cached alias (for getAnAlias) private String cached_alias = null; // the cached alias (for getAnAlias)
private boolean creating_topic = false; // is somebody creating a topic? private boolean creating_topic = false; // is somebody creating a topic?
private boolean deleted = false; // has this conference been deleted?
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Constructors * Constructors
@ -66,7 +67,7 @@ class ConferenceCoreData implements ConferenceData
ConferenceCoreData(EngineBackend engine, DataPool datapool, int confid) throws DataException ConferenceCoreData(EngineBackend engine, DataPool datapool, int confid) throws DataException
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("new ConferenceCoreData for conference " + String.valueOf(confid)); logger.debug("new ConferenceCoreData for conference " + confid);
this.engine = engine; this.engine = engine;
this.datapool = datapool; this.datapool = datapool;
this.confid = confid; this.confid = confid;
@ -83,7 +84,7 @@ class ConferenceCoreData implements ConferenceData
sql.append(confid).append(';'); sql.append(confid).append(';');
ResultSet rs = stmt.executeQuery(sql.toString()); ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next())) if (!(rs.next()))
throw new DataException("Conference #" + String.valueOf(confid) + " does not exist in the database."); throw new DataException("Conference #" + confid + " does not exist in the database.");
loadData(rs); // load the conference data loadData(rs); // load the conference data
@ -107,7 +108,7 @@ class ConferenceCoreData implements ConferenceData
boolean pvt, String name, String descr) boolean pvt, String name, String descr)
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("new ConferenceCoreData for NEW conference " + String.valueOf(confid)); logger.debug("new ConferenceCoreData for NEW conference " + confid);
this.engine = engine; this.engine = engine;
this.datapool = datapool; this.datapool = datapool;
this.confid = confid; this.confid = confid;
@ -221,6 +222,9 @@ class ConferenceCoreData implements ConferenceData
public List getAliases() throws DataException public List getAliases() throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; Connection conn = null;
Vector rc = new Vector(); Vector rc = new Vector();
@ -258,6 +262,9 @@ class ConferenceCoreData implements ConferenceData
public List getHosts() throws DataException public List getHosts() throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; Connection conn = null;
Vector rc = new Vector(); Vector rc = new Vector();
@ -304,24 +311,32 @@ class ConferenceCoreData implements ConferenceData
public boolean canReadConference(int level) public boolean canReadConference(int level)
{ {
if (deleted)
return false;
return (level>=read_level); return (level>=read_level);
} // end canReadConference } // end canReadConference
public boolean canPostToConference(int level) public boolean canPostToConference(int level)
{ {
if (deleted)
return false;
return (level>=post_level); return (level>=post_level);
} // end canReadConference } // end canReadConference
public boolean canCreateTopic(int level) public boolean canCreateTopic(int level)
{ {
if (deleted)
return false;
return (level>=create_level); return (level>=create_level);
} // end canCreateTopic } // end canCreateTopic
public boolean canChangeConference(int level) public boolean canChangeConference(int level)
{ {
if (deleted)
return false;
return (level>=change_level); return (level>=change_level);
} // end canChangeConference } // end canChangeConference
@ -371,6 +386,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized void setSecurityLevels(SIGBackend sig, int read, int post, int create, int hide, public synchronized void setSecurityLevels(SIGBackend sig, int read, int post, int create, int hide,
int nuke, int change, int delete) throws DataException int nuke, int change, int delete) throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection Connection conn = null; // database connection
AuditRecord ar = null; // audit record AuditRecord ar = null; // audit record
@ -402,7 +420,7 @@ class ConferenceCoreData implements ConferenceData
// create an audit record reflecting the change // create an audit record reflecting the change
ar = new AuditRecord(AuditRecord.CONF_SECURITY,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(), ar = new AuditRecord(AuditRecord.CONF_SECURITY,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"conf=" + String.valueOf(confid)); "conf=" + confid);
} // end try } // end try
catch (SQLException e) catch (SQLException e)
@ -434,6 +452,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized void setName(SIGBackend sig, String val) throws DataException public synchronized void setName(SIGBackend sig, String val) throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection Connection conn = null; // database connection
AuditRecord ar = null; // audit record AuditRecord ar = null; // audit record
@ -457,7 +478,7 @@ class ConferenceCoreData implements ConferenceData
// create an audit record reflecting the change // create an audit record reflecting the change
ar = new AuditRecord(AuditRecord.CONF_SECURITY,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(), ar = new AuditRecord(AuditRecord.CONF_SECURITY,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"conf=" + String.valueOf(confid)); "conf=" + confid);
} // end try } // end try
catch (SQLException e) catch (SQLException e)
@ -489,6 +510,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized void setDescription(String val) throws DataException public synchronized void setDescription(String val) throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection Connection conn = null; // database connection
try try
@ -526,6 +550,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized void addAlias(SIGBackend sig, String alias) throws DataException public synchronized void addAlias(SIGBackend sig, String alias) throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection Connection conn = null; // database connection
AuditRecord ar = null; // audit record AuditRecord ar = null; // audit record
@ -566,7 +593,7 @@ class ConferenceCoreData implements ConferenceData
// set the database's update date and generate a new audit record // set the database's update date and generate a new audit record
touchUpdate(conn); touchUpdate(conn);
ar = new AuditRecord(AuditRecord.CONF_ALIAS,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(), ar = new AuditRecord(AuditRecord.CONF_ALIAS,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"conf=" + String.valueOf(confid),"add=" + alias); "conf=" + confid,"add=" + alias);
} // end try } // end try
catch (SQLException e) catch (SQLException e)
@ -598,6 +625,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized void removeAlias(SIGBackend sig, String alias) throws DataException public synchronized void removeAlias(SIGBackend sig, String alias) throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection Connection conn = null; // database connection
AuditRecord ar = null; // audit record AuditRecord ar = null; // audit record
@ -651,7 +681,7 @@ class ConferenceCoreData implements ConferenceData
if ((cached_alias!=null) && cached_alias.equals(alias)) if ((cached_alias!=null) && cached_alias.equals(alias))
cached_alias = null; // also release the cached alias and force a re-get cached_alias = null; // also release the cached alias and force a re-get
ar = new AuditRecord(AuditRecord.CONF_ALIAS,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(), ar = new AuditRecord(AuditRecord.CONF_ALIAS,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"conf=" + String.valueOf(confid),"remove=" + alias); "conf=" + confid,"remove=" + alias);
} // end if } // end if
@ -685,6 +715,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized void setMembership(SIGBackend sig, int uid, int grant_level) throws DataException public synchronized void setMembership(SIGBackend sig, int uid, int grant_level) throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection Connection conn = null; // database connection
AuditRecord ar = null; // audit record AuditRecord ar = null; // audit record
@ -742,8 +775,7 @@ class ConferenceCoreData implements ConferenceData
{ // set the database's update date and generate a new audit record { // set the database's update date and generate a new audit record
touchUpdate(conn); touchUpdate(conn);
ar = new AuditRecord(AuditRecord.CONF_MEMBERSHIP,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(), ar = new AuditRecord(AuditRecord.CONF_MEMBERSHIP,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"conf=" + String.valueOf(confid),"uid=" + String.valueOf(uid), "conf=" + confid,"uid=" + uid,"level=" + grant_level);
"level=" + String.valueOf(grant_level));
} // end if } // end if
@ -777,12 +809,17 @@ class ConferenceCoreData implements ConferenceData
public boolean canHideTopics(int level) public boolean canHideTopics(int level)
{ {
if (deleted)
return false;
return (level>=hide_level); return (level>=hide_level);
} // end canHideTopics } // end canHideTopics
public synchronized String getAnAlias() throws DataException public synchronized String getAnAlias() throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
if (cached_alias!=null) if (cached_alias!=null)
return cached_alias; return cached_alias;
@ -821,6 +858,9 @@ class ConferenceCoreData implements ConferenceData
public synchronized ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud, public synchronized ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud,
String body, int body_lines) throws DataException String body, int body_lines) throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection Connection conn = null; // database connection
AuditRecord ar = null; // audit record AuditRecord ar = null; // audit record
short new_topic_num; // sequential number of the new topic short new_topic_num; // sequential number of the new topic
@ -891,8 +931,7 @@ class ConferenceCoreData implements ConferenceData
// create an audit record indicating we were successful // create an audit record indicating we were successful
ar = new AuditRecord(AuditRecord.CREATE_TOPIC,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(), ar = new AuditRecord(AuditRecord.CREATE_TOPIC,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"confid=" + String.valueOf(confid),"num=" + String.valueOf(new_topic_num), "confid=" + confid,"num=" + new_topic_num,"title=" + title);
"title=" + title);
} // end try } // end try
finally finally
@ -935,18 +974,25 @@ class ConferenceCoreData implements ConferenceData
public boolean canScribblePosts(int level) public boolean canScribblePosts(int level)
{ {
if (deleted)
return false;
return (level>=nuke_level); return (level>=nuke_level);
} // end canScribblePosts } // end canScribblePosts
public boolean canNukePosts(int level) public boolean canNukePosts(int level)
{ {
if (deleted)
return false;
return (level>=nuke_level); return (level>=nuke_level);
} // end canNukePosts } // end canNukePosts
public synchronized void touchUpdate(Connection conn, java.util.Date date) throws DataException public synchronized void touchUpdate(Connection conn, java.util.Date date) throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
try try
{ // update the last update date { // update the last update date
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
@ -998,6 +1044,207 @@ class ConferenceCoreData implements ConferenceData
} // end getTopTopic } // end getTopTopic
public List getMemberList() throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
if (logger.isDebugEnabled())
logger.debug("Member list: conference = " + confid);
Vector rc = new Vector(); // return from this function
Connection conn = null; // pooled database connection
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// create a new SQL statement
StringBuffer sql = new StringBuffer("SELECT u.uid, u.username, u.description, c.given_name, "
+ "c.family_name, c.locality, c.region, c.country, m.granted_lvl "
+ "FROM users u, contacts c, confmember m WHERE "
+ "u.contactid = c.contactid AND u.uid = m.uid AND m.confid = ");
sql.append(confid).append(" AND u.is_anon = 0 ORDER BY u.username;");
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
// launch the search!
ResultSet rs = stmt.executeQuery(sql.toString());
while (rs.next())
{ // add all the found users to the list
UserFoundImpl ufi = new UserFoundImpl(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),
rs.getString(5),rs.getString(6),rs.getString(7),rs.getString(8),
rs.getInt(9));
UserFound tmp = (UserFound)ufi;
rc.add(tmp);
} // end while
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error reading member entries: " + e.getMessage(),e);
throw new DataException("unable to retrieve member information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return new ReadOnlyVector(rc);
} // end getMemberList
public int getMemberLevel(int uid) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // pooled database connection
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// create the statement
StringBuffer sql = new StringBuffer("SELECT granted_lvl FROM confmember WHERE confid = ");
sql.append(confid).append(" AND uid = ").append(uid).append(';');
// execute the statement and return the retrieved value
ResultSet rs = stmt.executeQuery(sql.toString());
if (rs.next())
return rs.getInt(1);
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error reading member entries: " + e.getMessage(),e);
throw new DataException("unable to retrieve member information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return -1; // default return if no member level present
} // end getMemberLevel
public boolean isDeleted()
{
return deleted;
} // end isDeleted
public boolean canDeleteConference(int level)
{
if (deleted)
return false;
return (level>=delete_level);
} // end canDeleteConference
public synchronized void delete(SIGBackend sig) throws DataException
{
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection
AuditRecord ar = null; // audit record
int topic_count, topic_max; // count and maximum topic
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// lock tables on the critical stuff that MUST be deleted now
stmt.executeUpdate("LOCK TABLES confs WRITE, confalias WRITE, topics READ;");
try
{ // first delete the conference record itself
StringBuffer sql = new StringBuffer("DELETE FROM confs WHERE confid = ");
sql.append(confid).append(';');
stmt.executeUpdate(sql.toString());
// now delete all its alias records
sql.setLength(0);
sql.append("DELETE FROM confalias WHERE confid = ").append(confid).append(';');
stmt.executeUpdate(sql.toString());
// determine the number of topics in this conference, and the maximum topic ID
sql.setLength(0);
sql.append("SELECT COUNT(*), MAX(topicid) FROM topics WHERE confid = ").append(confid).append(';');
ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
throw new InternalStateError("ConferenceCoreData.delete screwup on topic SELECT");
topic_count = rs.getInt(1);
topic_max = rs.getInt(2);
// record that we're now deleted
create_date = null;
last_update = null;
top_topic = -1;
name = null;
description = null;
cached_alias = null;
deleted = true;
} // end try
finally
{ // unlock the tables before we go
Statement ulk_stmt = conn.createStatement();
ulk_stmt.executeUpdate("UNLOCK TABLES;");
} // end finally
// create an audit record indicating we were successful
ar = new AuditRecord(AuditRecord.DELETE_CONF,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"confid=" + confid);
} // end try
catch (SQLException e)
{ // database error - this is a DataException
logger.error("DB error deleting conference: " + e.getMessage(),e);
throw new DataException("unable to delete conference: " + e.getMessage(),e);
} // end catch
finally
{ // make sure the connection is released before we go
try
{ // save off the audit record before we go, though
if ((ar!=null) && (conn!=null))
ar.store(conn);
} // end try
catch (SQLException e)
{ // we couldn't store the audit record!
logger.error("DB error saving audit record: " + e.getMessage(),e);
} // end catch
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
// Delete the rest of the gunk in the background; spin off another thread to handle it.
BackgroundConferencePurge purger = new BackgroundConferencePurge(datapool,confid,topic_count,topic_max);
Thread thrd = new Thread(purger);
thrd.setPriority(Thread.NORM_PRIORITY-1);
thrd.start();
} // end delete
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* External static operations (usable only from within package) * External static operations (usable only from within package)
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -1100,13 +1347,13 @@ class ConferenceCoreData implements ConferenceData
// create an audit record indicating we were successful // create an audit record indicating we were successful
ar = new AuditRecord(AuditRecord.CREATE_CONF,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(), ar = new AuditRecord(AuditRecord.CREATE_CONF,sig.realUID(),sig.userRemoteAddress(),sig.realSIGID(),
"confid=" + String.valueOf(new_confid),"name=" + name,"alias=" + alias); "confid=" + new_confid,"name=" + name,"alias=" + alias);
} // end try } // end try
catch (SQLException e) catch (SQLException e)
{ // database error - this is a DataException { // database error - this is a DataException
logger.error("DB error creating SIG: " + e.getMessage(),e); logger.error("DB error creating conference: " + e.getMessage(),e);
throw new DataException("unable to create SIG: " + e.getMessage(),e); throw new DataException("unable to create conference: " + e.getMessage(),e);
} // end catch } // end catch
finally finally

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
@ -92,4 +92,14 @@ public interface ConferenceData extends ReferencedData
public abstract short getTopTopic(); public abstract short getTopTopic();
public abstract List getMemberList() throws DataException;
public abstract int getMemberLevel(int uid) throws DataException;
public abstract boolean isDeleted();
public abstract boolean canDeleteConference(int level);
public abstract void delete(SIGBackend sig) throws DataException;
} // end interface ConferenceData } // end interface ConferenceData

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
@ -100,4 +100,12 @@ public interface ConferenceSIGContext extends ReferencedData
public abstract short getTopTopic(); public abstract short getTopTopic();
public abstract List getMemberList() throws DataException;
public abstract int getMemberLevel(int uid) throws DataException;
public abstract boolean canDeleteConference(int level);
public abstract void delete(SIGBackend sig) throws DataException;
} // end interface ConferenceSIGContext } // end interface ConferenceSIGContext

View File

@ -88,6 +88,7 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
private boolean hide_list; // hide the conference in the list? private boolean hide_list; // hide the conference in the list?
private ConfCache cache; // cache of locally-important information private ConfCache cache; // cache of locally-important information
private ConferenceData confdata = null; // the inner conference data object private ConferenceData confdata = null; // the inner conference data object
private boolean deleted = false; // has this conference been deleted?
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Constructors * Constructors
@ -170,6 +171,23 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
} // end constructor } // end constructor
/*--------------------------------------------------------------------------------
* finalize() function
*--------------------------------------------------------------------------------
*/
protected void finalize()
{
if (confdata!=null)
confdata.rd_release();
confdata = null;
engine = null;
sig = null;
datapool = null;
cache = null;
} // end finalize
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Internal functions * Internal functions
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -179,6 +197,8 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
{ {
if (confdata==null) if (confdata==null)
{ // attempt to load the ConferenceSIGContext { // attempt to load the ConferenceSIGContext
if (deleted)
throw new DataException("This conference has been deleted.");
confdata = engine.getConferenceDataObject(confid); confdata = engine.getConferenceDataObject(confid);
// clear cache when we get the real confdata // clear cache when we get the real confdata
@ -194,6 +214,9 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
{ {
if (confdata==null) if (confdata==null)
{ // we need to load the ConferenceSIGContext... { // we need to load the ConferenceSIGContext...
if (deleted)
return null; // no return on deletion
try try
{ // attempt to load the ConferenceSIGContext { // attempt to load the ConferenceSIGContext
confdata = engine.getConferenceDataObject(confid); confdata = engine.getConferenceDataObject(confid);
@ -442,6 +465,9 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
public synchronized void setSIGGrantedLevel(SIGBackend sig, int new_level) throws DataException public synchronized void setSIGGrantedLevel(SIGBackend sig, int new_level) throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection Connection conn = null; // database connection
AuditRecord ar = null; // audit record AuditRecord ar = null; // audit record
@ -501,6 +527,9 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
public synchronized void setSequence(short seq) throws DataException public synchronized void setSequence(short seq) throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection Connection conn = null; // database connection
try try
@ -543,6 +572,9 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
public void setHideList(SIGBackend sig, boolean flag) throws DataException public void setHideList(SIGBackend sig, boolean flag) throws DataException
{ {
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // database connection Connection conn = null; // database connection
AuditRecord ar = null; // audit record AuditRecord ar = null; // audit record
@ -697,4 +729,86 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
} // end getTopTopic } // end getTopTopic
public List getMemberList() throws DataException
{
return getConferenceData().getMemberList();
} // end getMemberList
public int getMemberLevel(int uid) throws DataException
{
return getConferenceData().getMemberLevel(uid);
} // end getMemberLevel
public boolean canDeleteConference(int level)
{
ConferenceData c = getConferenceDataNE();
if (c==null)
return false;
if (level<this.level)
return c.canDeleteConference(this.level);
else
return c.canDeleteConference(level);
} // end canDeleteConference
public void delete(SIGBackend sig) throws DataException
{
ConferenceData c = getConferenceData();
Connection conn = null;
boolean delete_core = true;
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// see if we have to delete the core object as well
StringBuffer sql = new StringBuffer("SELECT sigid FROM sigtoconf WHERE confid = ");
sql.append(confid).append(" AND sigid <> ").append(this.sig.realSIGID()).append(" LIMIT 1;");
ResultSet rs = stmt.executeQuery(sql.toString());
if (rs.next())
delete_core = false; // we don't delete the core yet
// remove the row that links this conference to this SIG
sql.setLength(0);
sql.append("DELETE FROM sigtoconf WHERE confid = ").append(confid).append(" AND sigid = ");
sql.append(this.sig.realSIGID()).append(';');
stmt.executeUpdate(sql.toString());
// record that we've been deleted
level = 0;
sequence = -1;
hide_list = true;
cache = null;
deleted = true;
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error deleting conference entry: " + e.getMessage(),e);
throw new DataException("unable to delete conference information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
if (delete_core)
{ // the conference is not linked to any other SIGs - we need to delete the core as well
c.delete(sig);
engine.detachConferenceDataObject(confid);
} // end if
// detach our own reference from the lower-level object
confdata = null;
c.rd_release();
} // end delete
} // end class ConferenceSIGContextImpl } // end class ConferenceSIGContextImpl

View File

@ -139,6 +139,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
private String pseud; // default pseud to use in this conference private String pseud; // default pseud to use in this conference
private java.util.Date last_read; // last date we read this conference private java.util.Date last_read; // last date we read this conference
private java.util.Date last_post; // last date we posted to this conference private java.util.Date last_post; // last date we posted to this conference
private boolean deleted = false; // has conference been deleted?
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Constructors * Constructors
@ -202,6 +203,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
{ {
if (confdata==null) if (confdata==null)
{ // attempt to load the ConferenceSIGContext { // attempt to load the ConferenceSIGContext
if (deleted)
throw new DataException("This conference has been deleted.");
confdata = sig.getConferenceDataObject(confid); confdata = sig.getConferenceDataObject(confid);
// clear cache when we get the real confdata // clear cache when we get the real confdata
@ -217,6 +220,9 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
{ {
if (confdata==null) if (confdata==null)
{ // we need to load the ConferenceSIGContext... { // we need to load the ConferenceSIGContext...
if (deleted)
return null; // no return on deletion
try try
{ // attempt to load the ConferenceSIGContext { // attempt to load the ConferenceSIGContext
confdata = sig.getConferenceDataObject(confid); confdata = sig.getConferenceDataObject(confid);
@ -262,6 +268,9 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
private void tryLoadSettings(Connection conn) throws DataException private void tryLoadSettings(Connection conn) throws DataException
{ {
if (deleted)
return; // this is a no-op
try try
{ // look up the conference settings for this user { // look up the conference settings for this user
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
@ -609,7 +618,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end removeAlias } // end removeAlias
public void addMember(int uid, boolean as_host) throws DataException, AccessError public void setMembership(int uid, int grant_level) throws DataException, AccessError
{ {
if (!(getConferenceData().canChangeConference(level))) if (!(getConferenceData().canChangeConference(level)))
{ // this user can't modify the conference security { // this user can't modify the conference security
@ -618,13 +627,6 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if } // end if
// figure out which level to grant the user
int grant_level;
if (as_host)
grant_level = DefaultLevels.hostConference();
else
grant_level = DefaultLevels.memberConference();
// call down to set the level // call down to set the level
getConferenceData().setMembership(sig,uid,grant_level); getConferenceData().setMembership(sig,uid,grant_level);
@ -632,28 +634,23 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
if (uid==sig.realUID()) if (uid==sig.realUID())
recalcLevel(grant_level); recalcLevel(grant_level);
} // end setMembership
public void addMember(int uid, boolean as_host) throws DataException, AccessError
{
setMembership(uid,(as_host ? DefaultLevels.hostConference() : DefaultLevels.memberConference()));
} // end addMember } // end addMember
public void removeMember(int uid) throws DataException, AccessError public void removeMember(int uid) throws DataException, AccessError
{ {
if (!(getConferenceData().canChangeConference(level))) setMembership(uid,-1);
{ // this user can't modify the conference security
logger.error("user not permitted to change membership");
throw new AccessError("You are not permitted to change the membership of this conference.");
} // end if
// call down to set the level
getConferenceData().setMembership(sig,uid,-1);
// If we adjusted our OWN level, reflect that change.
if (uid==sig.realUID())
recalcLevel(-1);
} // end removeMember } // end removeMember
public int getSIGGrantedLevel() throws DataException, AccessError public int getSIGGrantedLevel() throws DataException, AccessError
{ {
ConferenceSIGContext c = getConferenceData();
if (!(sig.userCanCreateSubobjects())) if (!(sig.userCanCreateSubobjects()))
{ // this user can't modify the conference security { // this user can't modify the conference security
logger.error("user not permitted to retrieve security info"); logger.error("user not permitted to retrieve security info");
@ -661,12 +658,13 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if } // end if
return getConferenceData().getSIGGrantedLevel(); return c.getSIGGrantedLevel();
} // end getSIGGrantedLevel } // end getSIGGrantedLevel
public void setSIGGrantedLevel(int new_level) throws DataException, AccessError public void setSIGGrantedLevel(int new_level) throws DataException, AccessError
{ {
ConferenceSIGContext c = getConferenceData();
if (!(sig.userCanCreateSubobjects())) if (!(sig.userCanCreateSubobjects()))
{ // this user can't modify the conference security { // this user can't modify the conference security
logger.error("user not permitted to change security info"); logger.error("user not permitted to change security info");
@ -674,12 +672,13 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if } // end if
getConferenceData().setSIGGrantedLevel(sig,new_level); c.setSIGGrantedLevel(sig,new_level);
} // end setSIGGrantedLevel } // end setSIGGrantedLevel
public short getSequence() throws DataException, AccessError public short getSequence() throws DataException, AccessError
{ {
ConferenceSIGContext c = getConferenceData();
if (!(sig.userCanCreateSubobjects())) if (!(sig.userCanCreateSubobjects()))
{ // this user can't modify the conference security { // this user can't modify the conference security
logger.error("user not permitted to retrieve layout info"); logger.error("user not permitted to retrieve layout info");
@ -687,12 +686,13 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if } // end if
return getConferenceData().getSequence(); return c.getSequence();
} // end getSequence } // end getSequence
public void setSequence(short seq) throws DataException, AccessError public void setSequence(short seq) throws DataException, AccessError
{ {
ConferenceSIGContext c = getConferenceData();
if (!(sig.userCanCreateSubobjects())) if (!(sig.userCanCreateSubobjects()))
{ // this user can't modify the conference security { // this user can't modify the conference security
logger.error("user not permitted to set layout info"); logger.error("user not permitted to set layout info");
@ -700,12 +700,13 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if } // end if
getConferenceData().setSequence(seq); c.setSequence(seq);
} // end setSequence } // end setSequence
public boolean getHideList() throws DataException, AccessError public boolean getHideList() throws DataException, AccessError
{ {
ConferenceSIGContext c = getConferenceData();
if (!(sig.userCanCreateSubobjects())) if (!(sig.userCanCreateSubobjects()))
{ // this user can't modify the conference security { // this user can't modify the conference security
logger.error("user not permitted to retrieve security info"); logger.error("user not permitted to retrieve security info");
@ -713,12 +714,13 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if } // end if
return getConferenceData().getHideList(); return c.getHideList();
} // end getHideList } // end getHideList
public void setHideList(boolean flag) throws DataException, AccessError public void setHideList(boolean flag) throws DataException, AccessError
{ {
ConferenceSIGContext c = getConferenceData();
if (!(sig.userCanCreateSubobjects())) if (!(sig.userCanCreateSubobjects()))
{ // this user can't modify the conference security { // this user can't modify the conference security
logger.error("user not permitted to change security info"); logger.error("user not permitted to change security info");
@ -726,7 +728,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end if } // end if
getConferenceData().setHideList(sig,flag); c.setHideList(sig,flag);
} // end setHideList } // end setHideList
@ -740,6 +742,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
{ {
if (sig.userIsAnonymous()) if (sig.userIsAnonymous())
return; // anonymous user can't change pseud return; // anonymous user can't change pseud
if (deleted)
throw new DataException("This conference has been deleted.");
Connection conn = null; // pooled database connection Connection conn = null; // pooled database connection
@ -787,6 +791,8 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
public boolean anyUnread() public boolean anyUnread()
{ {
if (deleted)
return false;
Connection conn = null; // pooled database connection Connection conn = null; // pooled database connection
try try
@ -832,7 +838,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
{ {
if (!(getConferenceData().canReadConference(level))) if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference... { // the luser can't even read the conference...
logger.error("user not permitted to change membership"); logger.error("user not permitted to get topics");
throw new AccessError("You are not permitted to read this conference."); throw new AccessError("You are not permitted to read this conference.");
} // end if } // end if
@ -929,7 +935,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
{ {
if (!(getConferenceData().canReadConference(level))) if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference... { // the luser can't even read the conference...
logger.error("user not permitted to change membership"); logger.error("user not permitted to get messages");
throw new AccessError("You are not permitted to read this conference."); throw new AccessError("You are not permitted to read this conference.");
} // end if } // end if
@ -953,8 +959,15 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end getNewTopicPreviewChecker } // end getNewTopicPreviewChecker
public void fixSeen() throws DataException public void fixSeen() throws DataException, AccessError
{ {
if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference...
logger.error("user not permitted to set unread messages");
throw new AccessError("You are not permitted to read this conference.");
} // end if
if (sig.userIsAnonymous()) if (sig.userIsAnonymous())
return; // anonymous user can't fixseen return; // anonymous user can't fixseen
@ -1018,8 +1031,15 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end fixSeen } // end fixSeen
public List getActivePosters(int skip, int limit) throws DataException public List getActivePosters(int skip, int limit) throws DataException, AccessError
{ {
if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference...
logger.error("user not permitted to get posters list");
throw new AccessError("You are not permitted to read this conference.");
} // end if
Connection conn = null; Connection conn = null;
Vector rc = new Vector(); Vector rc = new Vector();
@ -1066,20 +1086,27 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end getActivePosters } // end getActivePosters
public List getActivePosters(int limit) throws DataException public List getActivePosters(int limit) throws DataException, AccessError
{ {
return getActivePosters(0,limit); return getActivePosters(0,limit);
} // end getActivePosters } // end getActivePosters
public List getActivePosters() throws DataException public List getActivePosters() throws DataException, AccessError
{ {
return getActivePosters(-1,-1); return getActivePosters(-1,-1);
} // end getActivePosters } // end getActivePosters
public List getActiveReaders(int skip, int limit) throws DataException public List getActiveReaders(int skip, int limit) throws DataException, AccessError
{ {
if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference...
logger.error("user not permitted to get readers list");
throw new AccessError("You are not permitted to read this conference.");
} // end if
Connection conn = null; Connection conn = null;
Vector rc = new Vector(); Vector rc = new Vector();
@ -1126,18 +1153,81 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end getActiveReaders } // end getActiveReaders
public List getActiveReaders(int limit) throws DataException public List getActiveReaders(int limit) throws DataException, AccessError
{ {
return getActiveReaders(0,limit); return getActiveReaders(0,limit);
} // end getActiveReaders } // end getActiveReaders
public List getActiveReaders() throws DataException public List getActiveReaders() throws DataException, AccessError
{ {
return getActiveReaders(-1,-1); return getActiveReaders(-1,-1);
} // end getActiveReaders } // end getActiveReaders
public List getMemberList() throws DataException, AccessError
{
if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference...
logger.error("user not permitted to get member list");
throw new AccessError("You are not permitted to read this conference.");
} // end if
return getConferenceData().getMemberList();
} // end getMemberList
public int getMemberLevel(int uid) throws DataException, AccessError
{
if (!(getConferenceData().canReadConference(level)))
{ // the luser can't even read the conference...
logger.error("user not permitted to get member data");
throw new AccessError("You are not permitted to read this conference.");
} // end if
return getConferenceData().getMemberLevel(uid);
} // end getMemberLevel
public void delete() throws DataException, AccessError
{
ConferenceSIGContext ctxt = getConferenceData();
if (!(ctxt.canDeleteConference(level)) || !(sig.userCanDeleteSubobjects()))
{ // no way can we delete this conference, not NO way!
logger.error("user not permitted to delete conference");
throw new AccessError("You are not permitted to delete this conference.");
} // end if
// call the methods required to delete the conference
ctxt.delete(sig);
sig.detachConferenceDataObject(confid);
// flag that we've been deleted
cache = null;
settings_loaded = true;
pseud = null;
last_read = null;
last_post = null;
deleted = true;
// detach our references from the lower-level object
confdata = null;
ctxt.rd_release();
} // end delete
public boolean canDeleteConference()
{
ConferenceSIGContext c = getConferenceDataNE();
if (c==null)
return false;
return (c.canDeleteConference(level) && sig.userCanDeleteSubobjects());
} // end canDeleteConference
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Implementations from interface UserBackend * Implementations from interface UserBackend
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -1214,6 +1304,18 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
} // end realSIGAlias } // end realSIGAlias
public void detachConferenceDataObject(int confid) throws DataException
{
sig.detachConferenceDataObject(confid);
} // end detachConferenceDataObject
public boolean userCanDeleteSubobjects()
{
return sig.userCanDeleteSubobjects();
} // end userCanDeleteSubobjects
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Implementations from interface ConferenceBackend * Implementations from interface ConferenceBackend
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -1236,7 +1338,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
public void touchRead(Connection conn) throws SQLException public void touchRead(Connection conn) throws SQLException
{ {
if (sig.userIsAnonymous()) if (deleted || sig.userIsAnonymous())
return; // anonymous user can't update squat return; // anonymous user can't update squat
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
@ -1268,7 +1370,7 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
public void touchPost(Connection conn, java.util.Date post_date) throws SQLException public void touchPost(Connection conn, java.util.Date post_date) throws SQLException
{ {
if (sig.userIsAnonymous()) if (deleted || sig.userIsAnonymous())
return; // anonymous user can't update squat return; // anonymous user can't update squat
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
@ -1299,6 +1401,9 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
public String realConfAlias() public String realConfAlias()
{ {
if (deleted)
return null;
try try
{ // just pull it from the lower-level object { // just pull it from the lower-level object
return getConferenceData().getAnAlias(); return getConferenceData().getAnAlias();

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
@ -32,6 +32,9 @@ public interface EngineBackend
public static final int IP_POSTSPERPAGE = 0; public static final int IP_POSTSPERPAGE = 0;
public static final int IP_POSTSATTOP = 1; public static final int IP_POSTSATTOP = 1;
public static final int IP_MAXSEARCHRETURN = 2;
public static final int IP_MAXSIGMEMBERDISPLAY = 3;
public static final int IP_MAXCONFMEMBERDISPLAY = 4;
public abstract SimpleEmailer createEmailer(); public abstract SimpleEmailer createEmailer();
@ -45,6 +48,8 @@ public interface EngineBackend
public abstract SIGData getSIGDataObject(int sigid) throws DataException; public abstract SIGData getSIGDataObject(int sigid) throws DataException;
public abstract void detachSIGDataObject(int sigid);
public abstract BitSet getLockedFeaturesMask(); public abstract BitSet getLockedFeaturesMask();
public abstract List getSIGFeatureSet(BitSet enabled_features, int level, boolean read_privs); public abstract List getSIGFeatureSet(BitSet enabled_features, int level, boolean read_privs);
@ -63,6 +68,8 @@ public interface EngineBackend
public abstract ConferenceData getConferenceDataObject(int confid) throws DataException; public abstract ConferenceData getConferenceDataObject(int confid) throws DataException;
public abstract void detachConferenceDataObject(int confid);
public abstract void saveAuditRecord(AuditRecord ar); public abstract void saveAuditRecord(AuditRecord ar);
public abstract void registerNewConference(ConferenceData conf); public abstract void registerNewConference(ConferenceData conf);

View File

@ -33,4 +33,8 @@ public interface SIGBackend extends UserBackend
public abstract String realSIGAlias(); public abstract String realSIGAlias();
public abstract void detachConferenceDataObject(int confid) throws DataException;
public abstract boolean userCanDeleteSubobjects();
} // end interface SIGBackend } // end interface SIGBackend

View File

@ -78,7 +78,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
SIGCoreData(EngineBackend engine, DataPool datapool, int sigid) throws DataException SIGCoreData(EngineBackend engine, DataPool datapool, int sigid) throws DataException
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("new SIGCoreData for SIG " + String.valueOf(sigid)); logger.debug("new SIGCoreData for SIG " + sigid);
this.engine = engine; this.engine = engine;
this.datapool = datapool; this.datapool = datapool;
this.sigid = sigid; this.sigid = sigid;
@ -95,7 +95,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
sql.append(sigid).append(';'); sql.append(sigid).append(';');
ResultSet rs = stmt.executeQuery(sql.toString()); ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next())) if (!(rs.next()))
throw new DataException("SIG #" + String.valueOf(sigid) + " does not exist in the database."); throw new DataException("SIG #" + sigid + " does not exist in the database.");
loadData(rs); // load the SIG data loadData(rs); // load the SIG data
@ -129,7 +129,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
BitSet features) BitSet features)
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("new SIGCoreData for BRAND NEW SIG " + String.valueOf(sigid)); logger.debug("new SIGCoreData for BRAND NEW SIG " + sigid);
this.engine = engine; this.engine = engine;
this.datapool = datapool; this.datapool = datapool;
this.sigid = sigid; this.sigid = sigid;
@ -218,8 +218,8 @@ class SIGCoreData implements SIGData, SIGDataBackend
alias = rs.getString("alias"); alias = rs.getString("alias");
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("Loaded data for SIG \"" + name + "\" (ID " + String.valueOf(sigid) + ", alias '" logger.debug("Loaded data for SIG \"" + name + "\" (ID " + sigid + ", alias '" + alias
+ alias + "') successfully"); + "') successfully");
} // end loadData } // end loadData
@ -438,13 +438,13 @@ class SIGCoreData implements SIGData, SIGDataBackend
{ // contact being established for the first time { // contact being established for the first time
contactid = ci.getContactID(); contactid = ci.getContactID();
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("established new contact ID (" + String.valueOf(contactid) + ") for this SIG"); logger.debug("established new contact ID (" + contactid + ") for this SIG");
} // end if } // end if
touchUpdate(conn); touchUpdate(conn);
ar = new AuditRecord(AuditRecord.SIG_CONTACT_INFO,user.realUID(),user.userRemoteAddress(),sigid, ar = new AuditRecord(AuditRecord.SIG_CONTACT_INFO,user.realUID(),user.userRemoteAddress(),sigid,
"contactid=" + String.valueOf(contactid)); "contactid=" + contactid);
} // end try } // end try
catch (ClassCastException cce) catch (ClassCastException cce)
@ -691,7 +691,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
this.category_id = catid; this.category_id = catid;
last_update = now; last_update = now;
ar = new AuditRecord(AuditRecord.SIG_CATEGORY,user.realUID(),user.userRemoteAddress(),sigid, ar = new AuditRecord(AuditRecord.SIG_CATEGORY,user.realUID(),user.userRemoteAddress(),sigid,
"catid=" + String.valueOf(catid)); "catid=" + catid);
} // end try } // end try
catch (SQLException e) catch (SQLException e)
@ -879,7 +879,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
hidden_search = search; hidden_search = search;
last_update = now; last_update = now;
ar = new AuditRecord(AuditRecord.SIG_HIDE_INFO,user.realUID(),user.userRemoteAddress(),sigid, ar = new AuditRecord(AuditRecord.SIG_HIDE_INFO,user.realUID(),user.userRemoteAddress(),sigid,
"dir=" + String.valueOf(directory) + ",search=" + String.valueOf(search)); "dir=" + directory + ",search=" + search);
} // end try } // end try
catch (SQLException e) catch (SQLException e)
@ -932,7 +932,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
members_only = flag; members_only = flag;
last_update = now; last_update = now;
ar = new AuditRecord(AuditRecord.SIG_MEMBERS_ONLY,user.realUID(),user.userRemoteAddress(),sigid, ar = new AuditRecord(AuditRecord.SIG_MEMBERS_ONLY,user.realUID(),user.userRemoteAddress(),sigid,
"flag=" + String.valueOf(flag)); "flag=" + flag);
} // end try } // end try
catch (SQLException e) catch (SQLException e)
@ -1013,7 +1013,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
ResultSet rs = stmt.executeQuery(sql.toString()); ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next())) if (!(rs.next()))
{ // can't find the join key? { // can't find the join key?
logger.error("SIG " + String.valueOf(sigid) + "appears to not be there"); logger.error("SIG " + sigid + "appears to not be there");
throw new DataException("Unable to find join key for SIG"); throw new DataException("Unable to find join key for SIG");
} // end if } // end if
@ -1241,7 +1241,7 @@ class SIGCoreData implements SIGData, SIGDataBackend
{ // update the SIG data and generate an audit record { // update the SIG data and generate an audit record
touchUpdate(conn); touchUpdate(conn);
ar = new AuditRecord(AuditRecord.SET_MEMBERSHIP,user.realUID(),user.userRemoteAddress(),sigid, ar = new AuditRecord(AuditRecord.SET_MEMBERSHIP,user.realUID(),user.userRemoteAddress(),sigid,
"uid=" + String.valueOf(uid),"level=" + String.valueOf(grant_level)); "uid=" + uid,"level=" + grant_level);
} // end if } // end if
} // end try } // end try
@ -1319,10 +1319,10 @@ class SIGCoreData implements SIGData, SIGDataBackend
} // end isFeaturePresent } // end isFeaturePresent
public ConferenceSIGContext getConferenceDataObject(int confid) throws DataException public synchronized ConferenceSIGContext getConferenceDataObject(int confid) throws DataException
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("getConferenceDataObject(" + String.valueOf(confid) + ")..."); logger.debug("getConferenceDataObject(" + confid + ")...");
Integer the_confid = new Integer(confid); Integer the_confid = new Integer(confid);
ConferenceSIGContext csc = (ConferenceSIGContext)(conf_objects.get(the_confid)); ConferenceSIGContext csc = (ConferenceSIGContext)(conf_objects.get(the_confid));
@ -1346,6 +1346,24 @@ class SIGCoreData implements SIGData, SIGDataBackend
} // end getConferenceDataObject } // end getConferenceDataObject
public synchronized void detachConferenceDataObject(int confid)
{
if (logger.isDebugEnabled())
logger.debug("detachConferenceDataObject(" + confid + ")...");
Integer the_confid = new Integer(confid);
ConferenceSIGContext csc = (ConferenceSIGContext)(conf_objects.get(the_confid));
if (csc!=null)
{ // remove from the hashtable
conf_objects.remove(the_confid);
csc.rd_release();
if (logger.isDebugEnabled())
logger.debug("...reference released");
} // end if
} // end detachConferenceDataObject
public ConferenceSIGContext createConference(SIGBackend sig, String name, String alias, String description, public ConferenceSIGContext createConference(SIGBackend sig, String name, String alias, String description,
boolean pvt, boolean hide_list) throws DataException boolean pvt, boolean hide_list) throws DataException
{ {
@ -1362,19 +1380,271 @@ class SIGCoreData implements SIGData, SIGDataBackend
cdata.rd_release(); cdata.rd_release();
rcs = null; rcs = null;
// Register this object with our local cache of ConferenceSIGData objects. synchronized (this)
{ // Register this object with our local cache of ConferenceSIGData objects.
Integer the_confid = new Integer(conf.getConfID()); Integer the_confid = new Integer(conf.getConfID());
if (conf_objects.get(the_confid)!=null) if (conf_objects.get(the_confid)!=null)
throw new InternalStateError("ConfID " + the_confid.toString() + " already exists...but it CAN'T HAVE!"); throw new InternalStateError("ConfID " + the_confid + " already exists...but it CAN'T HAVE!");
// throw an extra reference on it and dump it in the object cache // throw an extra reference on it and dump it in the object cache
conf.rd_addRef(); conf.rd_addRef();
conf_objects.put(the_confid,conf); conf_objects.put(the_confid,conf);
} // end synchronized block
return conf; // pass it up to the next level return conf; // pass it up to the next level
} // end createConference } // end createConference
public List searchForMembers(int field, int mode, String term, int offset, int count,
boolean include_hidden) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("Member search: SIG = " + sigid + ", field = " + field + ", mode = " + mode + ", term '"
+ term + "', offset = " + offset + ", count = " + count);
Vector rc = new Vector(); // return from this function
Connection conn = null; // pooled database connection
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// create a new SQL statement
StringBuffer sql = new StringBuffer("SELECT u.uid, u.username, u.description, c.given_name, "
+ "c.family_name, c.locality, c.region, c.country, m.granted_lvl "
+ "FROM users u, contacts c, sigmember m WHERE "
+ "u.contactid = c.contactid AND u.uid = m.uid AND m.sigid = ");
sql.append(sigid).append(" AND ");
switch (field)
{ // determine which field to search on
case SearchMode.FIELD_USER_NAME:
sql.append("u.username ");
break;
case SearchMode.FIELD_USER_DESCRIPTION:
sql.append("u.description ");
break;
case SearchMode.FIELD_USER_GIVEN_NAME:
sql.append("c.given_name ");
break;
case SearchMode.FIELD_USER_FAMILY_NAME:
sql.append("c.family_name ");
break;
default:
throw new DataException("invalid search field specified");
} // end switch
switch (mode)
{ // compose SQL in different ways depending on the search term
case SearchMode.SEARCH_PREFIX:
sql.append("LIKE '").append(SQLUtil.encodeStringWildcards(term)).append("%'");
break;
case SearchMode.SEARCH_SUBSTRING:
sql.append("LIKE '%").append(SQLUtil.encodeStringWildcards(term)).append("%'");
break;
case SearchMode.SEARCH_REGEXP:
sql.append("REGEXP '").append(SQLUtil.encodeString(term)).append('\'');
break;
default:
throw new DataException("invalid search mode specified");
} // end switch
if (!include_hidden)
sql.append(" AND m.hidden = 0");
sql.append(" AND u.is_anon = 0 ORDER BY u.username LIMIT ").append(offset).append(", ");
sql.append(count+1).append(';');
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
// launch the search!
ResultSet rs = stmt.executeQuery(sql.toString());
while (rs.next())
{ // add all the found users to the list
UserFoundImpl ufi = new UserFoundImpl(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),
rs.getString(5),rs.getString(6),rs.getString(7),rs.getString(8),
rs.getInt(9));
UserFound tmp = (UserFound)ufi;
rc.add(tmp);
} // end while
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error reading member entries: " + e.getMessage(),e);
throw new DataException("unable to retrieve member information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return new ReadOnlyVector(rc);
} // end searchForMembers
public int getSearchMemberCount(int field, int mode, String term, boolean include_hidden)
throws DataException
{
if (logger.isDebugEnabled())
logger.debug("User search: SIG = " + sigid + ", field = " + field + ", mode = " + mode + ", term '"
+ term + "'");
Connection conn = null; // pooled database connection
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
StringBuffer sql = new StringBuffer("SELECT COUNT(*) FROM users u, contacts c, sigmember m WHERE "
+ "u.contactid = c.contactid AND u.uid = m.uid AND m.sigid = ");
sql.append(sigid).append(" AND ");
switch (field)
{ // determine which field to search on
case SearchMode.FIELD_USER_NAME:
sql.append("u.username ");
break;
case SearchMode.FIELD_USER_DESCRIPTION:
sql.append("u.description ");
break;
case SearchMode.FIELD_USER_GIVEN_NAME:
sql.append("c.given_name ");
break;
case SearchMode.FIELD_USER_FAMILY_NAME:
sql.append("c.family_name ");
break;
default:
throw new DataException("invalid search field specified");
} // end switch
switch (mode)
{ // compose SQL in different ways depending on the search term
case SearchMode.SEARCH_PREFIX:
sql.append("LIKE '").append(SQLUtil.encodeStringWildcards(term)).append("%'");
break;
case SearchMode.SEARCH_SUBSTRING:
sql.append("LIKE '%").append(SQLUtil.encodeStringWildcards(term)).append("%'");
break;
case SearchMode.SEARCH_REGEXP:
sql.append("REGEXP '").append(SQLUtil.encodeString(term)).append('\'');
break;
default:
throw new DataException("invalid search mode specified");
} // end switch
if (!include_hidden)
sql.append(" AND m.hidden = 0");
sql.append(" AND u.is_anon = 0;");
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
// launch the search!
ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next()))
throw new InternalStateError("getSearchMemberCount failure (MUST have 1 row!)");
return rs.getInt(1);
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error reading member entries: " + e.getMessage(),e);
throw new DataException("unable to retrieve member information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
} // end getSearchMemberCount
public List getMemberList(boolean include_hidden) throws DataException
{
if (logger.isDebugEnabled())
logger.debug("Member list: SIG = " + sigid);
Vector rc = new Vector(); // return from this function
Connection conn = null; // pooled database connection
try
{ // get a database connection
conn = datapool.getConnection();
Statement stmt = conn.createStatement();
// create a new SQL statement
StringBuffer sql = new StringBuffer("SELECT u.uid, u.username, u.description, c.given_name, "
+ "c.family_name, c.locality, c.region, c.country, m.granted_lvl "
+ "FROM users u, contacts c, sigmember m WHERE "
+ "u.contactid = c.contactid AND u.uid = m.uid AND m.sigid = ");
sql.append(sigid);
if (!include_hidden)
sql.append(" AND m.hidden = 0");
sql.append(" AND u.is_anon = 0 ORDER BY u.username;");
if (logger.isDebugEnabled())
logger.debug("SQL: " + sql.toString());
// launch the search!
ResultSet rs = stmt.executeQuery(sql.toString());
while (rs.next())
{ // add all the found users to the list
UserFoundImpl ufi = new UserFoundImpl(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),
rs.getString(5),rs.getString(6),rs.getString(7),rs.getString(8),
rs.getInt(9));
UserFound tmp = (UserFound)ufi;
rc.add(tmp);
} // end while
} // end try
catch (SQLException e)
{ // turn SQLException into data exception
logger.error("DB error reading member entries: " + e.getMessage(),e);
throw new DataException("unable to retrieve member information: " + e.getMessage(),e);
} // end catch
finally
{ // make sure we release the connection before we go
if (conn!=null)
datapool.releaseConnection(conn);
} // end finally
return new ReadOnlyVector(rc);
} // end getMemberList
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Implementations from interface SIGDataBackend * Implementations from interface SIGDataBackend
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------

View File

@ -132,8 +132,18 @@ public interface SIGData extends ReferencedData
public abstract ConferenceSIGContext getConferenceDataObject(int confid) throws DataException; public abstract ConferenceSIGContext getConferenceDataObject(int confid) throws DataException;
public abstract void detachConferenceDataObject(int confid);
public abstract ConferenceSIGContext createConference(SIGBackend sig, String name, String alias, public abstract ConferenceSIGContext createConference(SIGBackend sig, String name, String alias,
String description, boolean pvt, boolean hide_list) String description, boolean pvt, boolean hide_list)
throws DataException; throws DataException;
public abstract List searchForMembers(int field, int mode, String term, int offset, int count,
boolean include_hidden) throws DataException;
public abstract int getSearchMemberCount(int field, int mode, String term, boolean include_hidden)
throws DataException;
public abstract List getMemberList(boolean include_hidden) throws DataException;
} // end interface SIGData } // end interface SIGData

View File

@ -1073,6 +1073,25 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
} // end canCreateConference } // end canCreateConference
public List searchForMembers(int field, int mode, String term, int offset, int count)
throws DataException
{
return getSIGData().searchForMembers(field,mode,term,offset,count,Capability.showHiddenSIGMembers(level));
} // end searchForMembers
public int getSearchMemberCount(int field, int mode, String term) throws DataException
{
return getSIGData().getSearchMemberCount(field,mode,term,Capability.showHiddenSIGMembers(level));
} // end getSearchMemberCount
public List getMemberList() throws DataException
{
return getSIGData().getMemberList(Capability.showHiddenSIGMembers(level));
} // end getMemberList
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Implementations from interface UserBackend * Implementations from interface UserBackend
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -1155,6 +1174,18 @@ class SIGUserContextImpl implements SIGContext, SIGBackend
} // end realSIGAlias } // end realSIGAlias
public void detachConferenceDataObject(int confid) throws DataException
{
getSIGData().detachConferenceDataObject(confid);
} // end detachConferenceDataObject
public boolean userCanDeleteSubobjects()
{
return userCanCreateSubobjects();
} // end userCanDeleteSubobjects
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Static operations for use within the implementation package * Static operations for use within the implementation package
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------

View File

@ -129,4 +129,11 @@ class UserFoundImpl implements UserFound
} // end getLevel } // end getLevel
public UserFound createNewLevel(int level)
{
return new UserFoundImpl(this.uid,this.name,this.description,this.given_name,this.family_name,
this.locality,this.region,this.country,level);
} // end createNewLevel
} // end class UserFoundImpl } // end class UserFoundImpl

View File

@ -242,7 +242,9 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
private void loadDefaults(Statement stmt) throws SQLException, DataException private void loadDefaults(Statement stmt) throws SQLException, DataException
{ {
final String query = "SELECT posts_per_page, old_posts_at_top FROM globals;"; final String query =
"SELECT posts_per_page, old_posts_at_top, max_search_page, max_sig_mbr_page, max_conf_mbr_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!");
@ -250,6 +252,9 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
// stash the globals from the database // stash the globals from the database
gp_ints[IP_POSTSPERPAGE] = rs.getInt(1); gp_ints[IP_POSTSPERPAGE] = rs.getInt(1);
gp_ints[IP_POSTSATTOP] = rs.getInt(2); gp_ints[IP_POSTSATTOP] = rs.getInt(2);
gp_ints[IP_MAXSEARCHRETURN] = rs.getInt(3);
gp_ints[IP_MAXSIGMEMBERDISPLAY] = rs.getInt(4);
gp_ints[IP_MAXCONFMEMBERDISPLAY] = rs.getInt(5);
} // end loadDefaults } // end loadDefaults
@ -381,7 +386,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end for } // end for
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug(String.valueOf(stock_messages.size()) + " stock messages loaded from config"); logger.debug(stock_messages.size() + " stock messages loaded from config");
} // end try } // end try
catch (ConfigException ce) catch (ConfigException ce)
@ -393,7 +398,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[2]; gp_ints = new int[5];
// 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;
@ -419,7 +424,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
features = new VeniceFeatureDef[++max_value]; features = new VeniceFeatureDef[++max_value];
System.arraycopy(tmp_array,0,features,0,max_value); System.arraycopy(tmp_array,0,features,0,max_value);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug(String.valueOf(max_value) + " features loaded from database"); logger.debug(max_value + " features loaded from database");
// load the global defaults // load the global defaults
loadDefaults(stmt); loadDefaults(stmt);
@ -556,13 +561,13 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
while (rs.next()) while (rs.next())
{ // load up a stack of memory objects with the country list { // load up a stack of memory objects with the country list
Country c = new CountryImpl(rs.getString("code"),rs.getString("name")); Country c = new CountryImpl(rs.getString(1),rs.getString(2));
rc.add(c); rc.add(c);
} // end while } // end while
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("getCountryList(): loaded " + String.valueOf(rc.size()) + " country names"); logger.debug("getCountryList(): loaded " + rc.size() + " country names");
} // end try } // end try
catch (SQLException e) catch (SQLException e)
@ -596,13 +601,13 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
while (rs.next()) while (rs.next())
{ // load up a stack of memory objects with the country list { // load up a stack of memory objects with the country list
Language l = new LanguageImpl(rs.getString("code"),rs.getString("name")); Language l = new LanguageImpl(rs.getString(1),rs.getString(2));
rc.add(l); rc.add(l);
} // end while } // end while
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("getLanguageList(): loaded " + String.valueOf(rc.size()) + " language names"); logger.debug("getLanguageList(): loaded " + rc.size() + " language names");
} // end try } // end try
catch (SQLException e) catch (SQLException e)
@ -649,9 +654,9 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
{ // look for a user name matching this user record { // look for a user name matching this user record
conn = datapool.getConnection(); conn = datapool.getConnection();
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT c.email AS email FROM users u, contacts c " ResultSet rs = stmt.executeQuery("SELECT c.email FROM users u, contacts c WHERE u.contactid = "
+ "WHERE u.contactid = c.contactid AND u.username = '" + "c.contactid AND u.username = '" + SQLUtil.encodeString(username)
+ SQLUtil.encodeString(username) + "';"); + "';");
if (!(rs.next())) if (!(rs.next()))
{ // could not find email address { // could not find email address
logger.warn("getEmailAddressForUser(\"" + username + "\") => not found!"); logger.warn("getEmailAddressForUser(\"" + username + "\") => not found!");
@ -660,7 +665,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end if } // end if
String rc = rs.getString("email"); String rc = rs.getString(1);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("getEmailAddressForUser(\"" + username + "\") => \"" + rc + "\""); logger.debug("getEmailAddressForUser(\"" + username + "\") => \"" + rc + "\"");
return rc; return rc;
@ -690,9 +695,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
{ // look for a user name matching this user record { // look for a user name matching this user record
conn = datapool.getConnection(); conn = datapool.getConnection();
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
StringBuffer sql = new StringBuffer("SELECT c.email AS email, u.passreminder AS passreminder " StringBuffer sql = new StringBuffer("SELECT c.email, u.passreminder FROM users u, contacts c WHERE "
+ "FROM users u, contacts c WHERE u.contactid = c.contactid " + "u.contactid = c.contactid AND u.username = '");
+ "AND u.username = '");
sql.append(SQLUtil.encodeString(username)).append("';"); sql.append(SQLUtil.encodeString(username)).append("';");
ResultSet rs = stmt.executeQuery(sql.toString()); ResultSet rs = stmt.executeQuery(sql.toString());
if (!(rs.next())) if (!(rs.next()))
@ -703,7 +707,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end if } // end if
String email_addr = rs.getString("email"); String email_addr = rs.getString(1);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("sendPasswordReminder(\"" + username + "\") going out to \"" + email_addr + "\""); logger.debug("sendPasswordReminder(\"" + username + "\") going out to \"" + email_addr + "\"");
@ -717,7 +721,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end if } // end if
message = StringUtil.replaceAllInstances(message,"$USERNAME",username); message = StringUtil.replaceAllInstances(message,"$USERNAME",username);
message = StringUtil.replaceAllInstances(message,"$REMINDER",rs.getString("passreminder")); message = StringUtil.replaceAllInstances(message,"$REMINDER",rs.getString(2));
// Create the emailer and send the message. // Create the emailer and send the message.
SimpleEmailer emailer = createEmailer(); SimpleEmailer emailer = createEmailer();
@ -796,7 +800,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
new_uid = rs.getInt(1); new_uid = rs.getInt(1);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("...created user \"" + username + "\" with UID " + String.valueOf(new_uid)); logger.debug("...created user \"" + username + "\" with UID " + new_uid);
// add a UserPrefs record for this user, too // add a UserPrefs record for this user, too
sql.setLength(0); sql.setLength(0);
@ -974,9 +978,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
public List searchForUsers(int field, int mode, String term, int offset, int count) throws DataException public List searchForUsers(int field, int mode, String term, int offset, int count) throws DataException
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("User search: field = " + String.valueOf(field) + ", mode = " + String.valueOf(mode) logger.debug("User search: field = " + field + ", mode = " + mode + ", term '" + term + "', offset = "
+ ", term '" + term + "', offset = " + String.valueOf(offset) + ", count = " + offset + ", count = " + count);
+ String.valueOf(count));
Vector rc = new Vector(); // return from this function Vector rc = new Vector(); // return from this function
Connection conn = null; // pooled database connection Connection conn = null; // pooled database connection
@ -985,11 +988,9 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
{ // get a database connection { // get a database connection
conn = datapool.getConnection(); conn = datapool.getConnection();
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
StringBuffer sql = new StringBuffer("SELECT u.uid AS uid, u.username AS username, u.description " StringBuffer sql = new StringBuffer("SELECT u.uid, u.username, u.description, c.given_name, "
+ "AS description, c.given_name AS given_name, c.family_name AS " + "c.family_name, c.locality, c.region, c.country FROM users u, "
+ "family_name, c.locality AS locality, c.region AS region, " + "contacts c WHERE u.contactid = c.contactid AND ");
+ "c.country AS country FROM users u, contacts c WHERE "
+ "u.contactid = c.contactid AND ");
switch (field) switch (field)
{ // determine which field to search on { // determine which field to search on
@ -1044,10 +1045,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
while (rs.next()) while (rs.next())
{ // add all the found users to the list { // add all the found users to the list
UserFoundImpl ufi = new UserFoundImpl(rs.getInt("uid"),rs.getString("username"), UserFoundImpl ufi = new UserFoundImpl(rs.getInt(1),rs.getString(2),rs.getString(3),rs.getString(4),
rs.getString("description"),rs.getString("given_name"), rs.getString(5),rs.getString(6),rs.getString(7),rs.getString(8));
rs.getString("family_name"),rs.getString("locality"),
rs.getString("region"),rs.getString("country"));
UserFound tmp = (UserFound)ufi; UserFound tmp = (UserFound)ufi;
rc.add(tmp); rc.add(tmp);
@ -1074,8 +1073,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
public int getSearchUserCount(int field, int mode, String term) throws DataException public int getSearchUserCount(int field, int mode, String term) throws DataException
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("User search: field = " + String.valueOf(field) + ", mode = " + String.valueOf(mode) logger.debug("User search: field = " + field + ", mode = " + mode + ", term '" + term + "'");
+ ", term '" + term + "'");
Connection conn = null; // pooled database connection Connection conn = null; // pooled database connection
@ -1083,8 +1081,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
{ // get a database connection { // get a database connection
conn = datapool.getConnection(); conn = datapool.getConnection();
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
StringBuffer sql = new StringBuffer("SELECT COUNT(*) AS total FROM users u, contacts c WHERE " StringBuffer sql = new StringBuffer("SELECT COUNT(*) FROM users u, contacts c WHERE u.contactid = "
+ "u.contactid = c.contactid AND "); + "c.contactid AND ");
switch (field) switch (field)
{ // determine which field to search on { // determine which field to search on
@ -1140,7 +1138,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
if (!(rs.next())) if (!(rs.next()))
throw new InternalStateError("getSearchUserCount search failure (MUST have 1 row!)"); throw new InternalStateError("getSearchUserCount search failure (MUST have 1 row!)");
return rs.getInt("total"); return rs.getInt(1);
} // end try } // end try
catch (SQLException e) catch (SQLException e)
@ -1160,7 +1158,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
public int getStdNumSearchResults() public int getStdNumSearchResults()
{ {
return 20; // TODO: make this a config file option return gp_ints[IP_MAXSEARCHRETURN];
} // end getStdNumSearchResults } // end getStdNumSearchResults
@ -1245,6 +1243,18 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getNumOldPostsBeforeNew } // end getNumOldPostsBeforeNew
public int getMaxNumConferenceMembersDisplay()
{
return gp_ints[IP_MAXCONFMEMBERDISPLAY];
} // end getMaxNumConferenceMembersDisplay
public int getMaxNumSIGMembersDisplay()
{
return gp_ints[IP_MAXSIGMEMBERDISPLAY];
} // end getMaxNumSIGMembersDisplay
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
* Implementations from interface EngineBackend * Implementations from interface EngineBackend
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
@ -1357,11 +1367,11 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getLanguageNameForCode } // end getLanguageNameForCode
public SIGData getSIGDataObject(int sigid) throws DataException public synchronized SIGData getSIGDataObject(int sigid) throws DataException
{ {
checkInitialized(); checkInitialized();
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("getSIGDataObject(" + String.valueOf(sigid) + ")..."); logger.debug("getSIGDataObject(" + sigid + ")...");
Integer the_sigid = new Integer(sigid); Integer the_sigid = new Integer(sigid);
SIGData sd = (SIGData)(sig_objects.get(the_sigid)); SIGData sd = (SIGData)(sig_objects.get(the_sigid));
@ -1385,6 +1395,25 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getSIGDataObject } // end getSIGDataObject
public synchronized void detachSIGDataObject(int sigid)
{
checkInitialized();
if (logger.isDebugEnabled())
logger.debug("detachSIGDataObject(" + sigid + ")...");
Integer the_sigid = new Integer(sigid);
SIGData sd = (SIGData)(sig_objects.get(the_sigid));
if (sd!=null)
{ // pull the reference out of our hashtable
sig_objects.remove(the_sigid);
sd.rd_release();
if (logger.isDebugEnabled())
logger.debug("...reference detached");
} // end if
} // end detachSIGDataObject
public BitSet getLockedFeaturesMask() public BitSet getLockedFeaturesMask()
{ {
checkInitialized(); checkInitialized();
@ -1420,7 +1449,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end if and for } // end if and for
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("getSIGFeatureSet() loaded " + String.valueOf(rc.size()) + " elements"); logger.debug("getSIGFeatureSet() loaded " + rc.size() + " elements");
return new ReadOnlyVector(rc); // wrap the vector for return return new ReadOnlyVector(rc); // wrap the vector for return
@ -1431,14 +1460,14 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
checkInitialized(); checkInitialized();
if ((code<0) || (code>=features.length)) if ((code<0) || (code>=features.length))
{ // the index is out of bounds! { // the index is out of bounds!
logger.error("getAppletForFeature(" + String.valueOf(code) + ") => out of range"); logger.error("getAppletForFeature(" + code + ") => out of range");
throw new IndexOutOfBoundsException("invalid feature code"); throw new IndexOutOfBoundsException("invalid feature code");
} // end if } // end if
String rc = features[code].getApplet(); String rc = features[code].getApplet();
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("getAppletForFeature(" + String.valueOf(code) + ") => \"" + rc + "\""); logger.debug("getAppletForFeature(" + code + ") => \"" + rc + "\"");
return rc; return rc;
} // end getAppletForFeature } // end getAppletForFeature
@ -1463,15 +1492,15 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getDefaultFeaturesMask } // end getDefaultFeaturesMask
public void registerNewSIG(SIGData sig) public synchronized void registerNewSIG(SIGData sig)
{ {
checkInitialized(); checkInitialized();
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("registerNewSIG(" + String.valueOf(sig.getID()) + ")..."); logger.debug("registerNewSIG(" + sig.getID() + ")...");
Integer the_sigid = new Integer(sig.getID()); Integer the_sigid = new Integer(sig.getID());
if (sig_objects.get(the_sigid)!=null) if (sig_objects.get(the_sigid)!=null)
throw new InternalStateError("SIGID " + the_sigid.toString() + " already exists...but it CAN'T HAVE!"); throw new InternalStateError("SIGID " + the_sigid + " already exists...but it CAN'T HAVE!");
// throw an extra reference on it and dump it in the object cache // throw an extra reference on it and dump it in the object cache
sig.rd_addRef(); sig.rd_addRef();
@ -1501,11 +1530,11 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end canAccessFeature } // end canAccessFeature
public ConferenceData getConferenceDataObject(int confid) throws DataException public synchronized ConferenceData getConferenceDataObject(int confid) throws DataException
{ {
checkInitialized(); checkInitialized();
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("getConferenceDataObject(" + String.valueOf(confid) + ")..."); logger.debug("getConferenceDataObject(" + confid + ")...");
Integer the_confid = new Integer(confid); Integer the_confid = new Integer(confid);
ConferenceData cd = (ConferenceData)(conf_objects.get(the_confid)); ConferenceData cd = (ConferenceData)(conf_objects.get(the_confid));
@ -1529,6 +1558,25 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end getConferenceDataObject } // end getConferenceDataObject
public synchronized void detachConferenceDataObject(int confid)
{
checkInitialized();
if (logger.isDebugEnabled())
logger.debug("detachConferenceDataObject(" + confid + ")...");
Integer the_confid = new Integer(confid);
ConferenceData cd = (ConferenceData)(conf_objects.get(the_confid));
if (cd!=null)
{ // remove it from our hashtable
conf_objects.remove(the_confid);
cd.rd_release();
if (logger.isDebugEnabled())
logger.debug("...detached reference");
} // end if
} // end detachConferenceDataObject
public void saveAuditRecord(AuditRecord ar) public void saveAuditRecord(AuditRecord ar)
{ {
checkInitialized(); checkInitialized();
@ -1557,15 +1605,15 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend
} // end saveAuditRecord } // end saveAuditRecord
public void registerNewConference(ConferenceData conf) public synchronized void registerNewConference(ConferenceData conf)
{ {
checkInitialized(); checkInitialized();
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("registerNewConference(" + String.valueOf(conf.getID()) + ")..."); logger.debug("registerNewConference(" + conf.getID() + ")...");
Integer the_confid = new Integer(conf.getID()); Integer the_confid = new Integer(conf.getID());
if (conf_objects.get(the_confid)!=null) if (conf_objects.get(the_confid)!=null)
throw new InternalStateError("ConfID " + the_confid.toString() + " already exists...but it CAN'T HAVE!"); throw new InternalStateError("ConfID " + the_confid + " already exists...but it CAN'T HAVE!");
// throw an extra reference on it and dump it in the object cache // throw an extra reference on it and dump it in the object cache
conf.rd_addRef(); conf.rd_addRef();

View File

@ -59,5 +59,6 @@ public interface Audit
public static final int SCRIBBLE_MESSAGE = 312; public static final int SCRIBBLE_MESSAGE = 312;
public static final int NUKE_MESSAGE = 313; public static final int NUKE_MESSAGE = 313;
public static final int UPLOAD_ATTACHMENT = 314; public static final int UPLOAD_ATTACHMENT = 314;
public static final int DELETE_CONF = 315;
} // end interface Audit } // end interface Audit

View File

@ -63,6 +63,7 @@ public class Role implements Comparable, SecLevels
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
*/ */
private static Role not_in_list = null;
private static Role no_access = null; private static Role no_access = null;
private static Role unrestricted_user = null; private static Role unrestricted_user = null;
private static Vector global_low = null; private static Vector global_low = null;
@ -99,6 +100,9 @@ public class Role implements Comparable, SecLevels
private static void initAllSets() private static void initAllSets()
{ {
if (not_in_list==null)
not_in_list = new Role(0,"(not in list)");
if (no_access==null) if (no_access==null)
no_access = new Role(NO_ACCESS,"No Access"); no_access = new Role(NO_ACCESS,"No Access");
@ -343,4 +347,18 @@ public class Role implements Comparable, SecLevels
} // end getConferenceDeleteList } // end getConferenceDeleteList
public static List getConferenceMemberLevelChoices()
{
initAllSets();
Vector rc = new Vector();
rc.add(not_in_list);
rc.addAll(global_low);
rc.addAll(sig_low);
rc.addAll(conf_low);
rc.add(unrestricted_user);
rc.add(conf_high.lastElement());
return new ReadOnlyVector(rc);
} // end getConferenceMemberLevelChoices
} // end class Role } // end class Role

View File

@ -18,6 +18,7 @@
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.*;
@ -33,6 +34,9 @@ public class ConfOperations extends VeniceServlet
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
*/ */
private static final String DELETE_CONFIRM_ATTR = "servlets.ConfOperations.delete.confirm";
private static final String DELETE_CONFIRM_PARAM = "confirm";
private static Category logger = Category.getInstance(ConfOperations.class.getName()); private static Category logger = Category.getInstance(ConfOperations.class.getName());
/*-------------------------------------------------------------------------------- /*--------------------------------------------------------------------------------
@ -174,6 +178,11 @@ public class ConfOperations extends VeniceServlet
conf.fixSeen(); conf.fixSeen();
} // end try } // end try
catch (AccessError ae)
{ // some sort of access error - display an error dialog
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
catch (DataException de) catch (DataException de)
{ // some sort of error in the database { // some sort of error in the database
return new ErrorBox("Database Error","Database error catching up conference: " + de.getMessage(), return new ErrorBox("Database Error","Database error catching up conference: " + de.getMessage(),
@ -282,9 +291,84 @@ public class ConfOperations extends VeniceServlet
on_error); on_error);
} // end catch } // end catch
catch (AccessError ae)
{ // some sort of access error - display an error dialog
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
} // end if ("RP" and "RR" commands) } // end if ("RP" and "RR" commands)
if (cmd.equals("M"))
{ // "M" - Manage Conference Membership (requires conference parameter)
ConferenceContext conf = getConferenceParameter(request,sig,true,on_error);
on_error = "confops?sig=" + sig.getSIGID() + "&conf=" + conf.getConfID() + "&cmd=Q";
try
{ // display the conference member list!
ConferenceMembership m = new ConferenceMembership(engine,sig,conf);
m.doConferenceMemberList();
setMyLocation(request,"confops?sig=" + sig.getSIGID() + "&conf=" + conf.getConfID() + "&cmd=M");
return m;
} // end try
catch (DataException de)
{ // something wrong in the database
return new ErrorBox("Database Error","Database error listing conference members: " + de.getMessage(),
on_error);
} // end catch
catch (AccessError ae)
{ // some lack of access is causing problems
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
} // end if ("M" command)
if (cmd.equals("DEL"))
{ // "DEL" = "Delete Conference (requires conference parameter)
ConferenceContext conf = getConferenceParameter(request,sig,true,on_error);
on_error = "confops?sig=" + sig.getSIGID() + "&conf=" + conf.getConfID() + "&cmd=Q";
if (!(conf.canDeleteConference()))
return new ErrorBox("Access Error","You do not have permission to delete this conference.",on_error);
if (ConfirmBox.isConfirmed(request,DELETE_CONFIRM_ATTR,DELETE_CONFIRM_PARAM))
{ // we are confirmed - delete the conference!
try
{ // tell it to go away
conf.delete();
} // end try
catch (DataException de)
{ // something wrong in the database
return new ErrorBox("Database Error","Database error deleting conference: " + de.getMessage(),
on_error);
} // end catch
catch (AccessError ae)
{ // some lack of access is causing problems
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
// that's it - trap back to the main conference list
throw new RedirectResult("confops?sig=" + sig.getSIGID());
} // end if
else
{ // generate a confirmation box and wait for confirmation
String message = "You are about to permanently delete the \"" + conf.getName() + "\" conference! "
+ "Are you sure you want to do this?";
return new ConfirmBox(request,DELETE_CONFIRM_ATTR,DELETE_CONFIRM_PARAM,"Delete Conference",message,
"confops?sig=" + sig.getSIGID() + "&conf=" + conf.getConfID() + "&cmd=DEL",
on_error);
} // end else
} // end if ("DEL" command)
// Any unrecognized command shows us the conference list. // Any unrecognized command shows us the conference list.
on_error = "sigprofile?sig=" + sig.getSIGID(); on_error = "sigprofile?sig=" + sig.getSIGID();
try try
@ -572,6 +656,124 @@ public class ConfOperations extends VeniceServlet
} // end if ("A" command) } // end if ("A" command)
if (cmd.equals("M"))
{ // "M" - Manage Conference Membership (requires conference parameter)
ConferenceContext conf = getConferenceParameter(request,sig,true,on_error);
on_error = "confops?sig=" + sig.getSIGID() + "&conf=" + conf.getConfID() + "&cmd=M";
if (isImageButtonClicked(request,"update"))
{ // the "update" command that changes all the security levels
HashMap org_vals = new HashMap();
HashMap new_vals = new HashMap();
try
{ // retrieve all parameters and filter them for the levels
Enumeration p_names = request.getParameterNames();
while (p_names.hasMoreElements())
{ // examine each parameter name in turn
String p_name = (String)(p_names.nextElement());
if (p_name.startsWith("zxcur_"))
{ // this is a current value (from a hidden field)
int uid = Integer.parseInt(p_name.substring(6));
int level = Integer.parseInt(request.getParameter(p_name));
org_vals.put(new Integer(uid),new Integer(level));
} // end if
else if (p_name.startsWith("zxnew_"))
{ // this is a new value (from a dropdown list box)
int uid = Integer.parseInt(p_name.substring(6));
int level = Integer.parseInt(request.getParameter(p_name));
new_vals.put(new Integer(uid),new Integer(level));
} // end else if
} // end while
if (org_vals.size()!=new_vals.size())
return new ErrorBox(null,"Invalid parameters.",on_error);
} // end try
catch (NumberFormatException nfe)
{ // error converting the parameters
return new ErrorBox(null,"Invalid parameter conversion.",on_error);
} // end catch
try
{ // loop through the hashmaps and set the value
Iterator it = org_vals.keySet().iterator();
while (it.hasNext())
{ // extract the UID, old level, and new level
Integer uid = (Integer)(it.next());
Integer org_level = (Integer)(org_vals.get(uid));
Integer new_level = (Integer)(new_vals.get(uid));
if (new_level==null) // whoops
return new ErrorBox(null,"Invalid new level parameter.",on_error);
int new_level_x = new_level.intValue();
if (new_level_x==0)
new_level_x = -1;
// call down to set the membership level
if (org_level.intValue()!=new_level_x)
conf.setMembership(uid.intValue(),new_level_x);
} // end while
} // end try
catch (AccessError ae)
{ // some sort of access error - display an error dialog
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
catch (DataException de)
{ // database error creating the conference
return new ErrorBox("Database Error","Database error setting memberships: " + de.getMessage(),
on_error);
} // end catch
// trap back to the conference membership display
throw new RedirectResult(on_error);
} // end if ("update" clicked)
if ( isImageButtonClicked(request,"search") || isImageButtonClicked(request,"previous")
|| isImageButtonClicked(request,"next"))
{ // create the new dialog box
ConferenceMembership m = new ConferenceMembership(engine,sig,conf);
try
{ // perform the search!
m.doSearch(request);
} // end try
catch (ValidationException ve)
{ // validation error - throw it back to the user
return new ErrorBox(null,ve.getMessage() + " Please try again.",on_error);
} // end catch
catch (AccessError ae)
{ // some sort of access error - display an error dialog
return new ErrorBox("Access Error",ae.getMessage(),on_error);
} // end catch
catch (DataException de)
{ // database error creating the conference
return new ErrorBox("Database Error","Database error updating conference: " + de.getMessage(),
on_error);
} // end catch
setMyLocation(request,on_error);
return m;
} // end if (search function clicked)
// we don't know what button was pressed
logger.error("no known button click on ConfOperations.doPost, cmd=M");
return new ErrorBox("Internal Error","Unknown command button pressed",on_error);
} // end if ("M" command)
// unrecognized command! // unrecognized command!
logger.error("invalid command to ConfOperations.doPost: " + cmd); logger.error("invalid command to ConfOperations.doPost: " + cmd);
return new ErrorBox("Internal Error","Invalid command to ConfOperations.doPost",on_error); return new ErrorBox("Internal Error","Invalid command to ConfOperations.doPost",on_error);

View File

@ -47,7 +47,8 @@ public class ConferenceActivity implements JSPRender
*-------------------------------------------------------------------------------- *--------------------------------------------------------------------------------
*/ */
public ConferenceActivity(SIGContext sig, ConferenceContext conf, boolean posters) throws DataException public ConferenceActivity(SIGContext sig, ConferenceContext conf, boolean posters)
throws DataException, AccessError
{ {
this.sig = sig; this.sig = sig;
this.conf = conf; this.conf = conf;

View File

@ -0,0 +1,337 @@
/*
* 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 javax.servlet.*;
import javax.servlet.http.*;
import com.silverwrist.venice.ValidationException;
import com.silverwrist.venice.security.Role;
import com.silverwrist.venice.core.*;
public class ConferenceMembership implements JSPRender, SearchMode
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
// Attribute name for request attribute
protected static final String ATTR_NAME = "com.silverwrist.venice.content.ConferenceMembership";
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private VeniceEngine engine; // reference to the engine
private SIGContext sig; // the SIG we're in
private ConferenceContext conf; // the conference being listed
private List display_list = null; // list of members to display
private boolean conf_members = false; // is this a list of conference members?
private int field = -1; // search field
private int mode = -1; // search mode
private String term = null; // search term
private int offset = 0; // search result offset
private int find_count = -1; // search results count
private List role_choices; // the list of security roles
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
public ConferenceMembership(VeniceEngine engine, SIGContext sig, ConferenceContext conf)
{
this.engine = engine;
this.sig = sig;
this.conf = conf;
this.role_choices = Role.getConferenceMemberLevelChoices();
} // end constructor
/*--------------------------------------------------------------------------------
* Internal functions
*--------------------------------------------------------------------------------
*/
private static int getParamInt(ServletRequest request, String name, int default_val)
{
String str = request.getParameter(name);
if (str==null)
return -1;
try
{ // parse the integer value
return Integer.parseInt(str);
} // end try
catch (NumberFormatException nfe)
{ // in case of conversion error, return default
return default_val;
} // end catch
} // end getParamInt
private static boolean isImageButtonClicked(ServletRequest request, String name)
{
String val = request.getParameter(name + ".x");
return (val!=null);
} // end isImageButtonClicked
/*--------------------------------------------------------------------------------
* External static functions
*--------------------------------------------------------------------------------
*/
public static ConferenceMembership retrieve(ServletRequest request)
{
return (ConferenceMembership)(request.getAttribute(ATTR_NAME));
} // end retrieve
/*--------------------------------------------------------------------------------
* Implementations from interface VeniceContent
*--------------------------------------------------------------------------------
*/
public String getPageTitle(RenderData rdat)
{
return "Membership in Conference " + conf.getName();
} // end getPageTitle
/*--------------------------------------------------------------------------------
* Implementations from interface JSPRender
*--------------------------------------------------------------------------------
*/
public void store(ServletRequest request)
{
request.setAttribute(ATTR_NAME,this);
} // end store
public String getTargetJSPName()
{
return "conf_member.jsp";
} // end getTargetJSPName
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public void doConferenceMemberList() throws DataException, AccessError
{
this.display_list = conf.getMemberList();
this.conf_members = true;
this.term = "";
} // end doConferenceMemberList
public void doSearch(ServletRequest request) throws ValidationException, DataException, AccessError
{
// Validate the search field parameter.
field = getParamInt(request,"field",FIELD_USER_NAME);
if ( (field!=FIELD_USER_NAME) && (field!=FIELD_USER_DESCRIPTION) && (field!=FIELD_USER_GIVEN_NAME)
&& (field!=FIELD_USER_FAMILY_NAME))
throw new ValidationException("The field search parameter is not valid.");
// Validate the search mode parameter.
mode = getParamInt(request,"mode",SEARCH_PREFIX);
if ((mode!=SEARCH_PREFIX) && (mode!=SEARCH_SUBSTRING) && (mode!=SEARCH_REGEXP))
throw new ValidationException("The search mode parameter is not valid.");
// Retrieve the search term parameter.
term = request.getParameter("term");
if (term==null)
term = "";
// Retrieve the offset and find count parameters.
offset = getParamInt(request,"ofs",0);
find_count = getParamInt(request,"fcount",-1);
// Adjust the search return offset based on the command button click.
int count = getNumResultsDisplayed();
if (isImageButtonClicked(request,"search"))
offset = 0;
else if (isImageButtonClicked(request,"previous"))
{ // adjust the offset in the reverse direction
offset -= count;
if (offset<0)
offset = 0;
} // end else if
else if (isImageButtonClicked(request,"next"))
offset += count; // go forwards instead
else
throw new ValidationException("Unable to determine what action triggered the form.");
// Perform the search!
List intermediate = sig.searchForMembers(field,mode,term,offset,count);
if (find_count<0)
find_count = sig.getSearchMemberCount(field,mode,term);
// Create the real display list by getting the conference security levels.
Iterator it = intermediate.iterator();
Vector rc = new Vector(count+1);
while (it.hasNext())
{ // loop around and find the member level of every one
UserFound uf = (UserFound)(it.next());
int new_level = conf.getMemberLevel(uf.getUID());
if (new_level==-1)
new_level = 0;
rc.add(uf.createNewLevel(new_level));
} // end while
display_list = rc; // save display list for display
} // end doSearch
public int getSIGID()
{
return sig.getSIGID();
} // end getSIGID
public int getConfID()
{
return conf.getConfID();
} // end getConfID
public String getSIGName()
{
return sig.getName();
} // end getSIGName
public String getConfName()
{
return conf.getName();
} // end getConfName
public String getLocator()
{
return "sig=" + sig.getSIGID() + "&conf=" + conf.getConfID();
} // end getLocator
public boolean displayList()
{
if ((display_list==null) || (display_list.size()==0))
return false;
if (conf_members && (display_list.size()>engine.getMaxNumConferenceMembersDisplay()))
return false;
return true;
} // end displayList
public boolean conferenceMemberList()
{
return conf_members;
} // end conferenceMemberList
public int getSearchField()
{
return field;
} // end getSearchField
public int getSearchMode()
{
return mode;
} // end getSearchMode
public boolean searchFieldIs(int value)
{
return (field==value);
} // end searchFieldIs
public boolean searchModeIs(int value)
{
return (mode==value);
} // end searchModeIs
public String getSearchTerm()
{
return term;
} // end getSearchTerm
public int getFindCount()
{
return find_count;
} // end getFindCount
public int getOffset()
{
return offset;
} // end getOffset
public int getSize()
{
return display_list.size();
} // end getSize
public int getNumResultsDisplayed()
{
return engine.getStdNumSearchResults();
} // end getNumResultsDisplayed
public UserFound getItem(int ndx)
{
return (UserFound)(display_list.get(ndx));
} // end getItem
public void outputDropDown(Writer out, int uid, int cur_level) throws IOException
{
out.write("<INPUT TYPE=HIDDEN NAME=\"zxcur_" + uid + "\" VALUE=\"" + cur_level + "\">\n");
out.write("<SELECT NAME=\"zxnew_" + uid + "\" SIZE=1>\n");
Iterator it = role_choices.iterator();
while (it.hasNext())
{ // output the <OPTION> lines for the dropdown
Role r = (Role)(it.next());
out.write("<OPTION VALUE=\"" + r.getLevel() + "\"");
if (r.getLevel()==cur_level)
out.write(" SELECTED");
out.write(">" + r.getName() + "</OPTION>\n");
} // end while
out.write("</SELECT>\n");
} // end outputDropDown
} // end class ConferenceMembership

View File

@ -66,7 +66,7 @@ public class ConfirmBox implements ContentRender
this.conf_num = rng.nextInt(0x1000000); this.conf_num = rng.nextInt(0x1000000);
this.title = title; this.title = title;
this.message = message; this.message = message;
this.confirm_url = confirm_url + "&" + param_name + "=" + String.valueOf(this.conf_num); this.confirm_url = confirm_url + "&" + param_name + "=" + this.conf_num;
this.deny_url = deny_url; this.deny_url = deny_url;
// Stash this object in the HTTP session. // Stash this object in the HTTP session.

154
web/format/conf_member.jsp Normal file
View File

@ -0,0 +1,154 @@
<%--
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):
--%>
<%@ page import = "java.util.*" %>
<%@ page import = "com.silverwrist.util.StringUtil" %>
<%@ page import = "com.silverwrist.venice.core.*" %>
<%@ page import = "com.silverwrist.venice.servlets.Variables" %>
<%@ page import = "com.silverwrist.venice.servlets.format.*" %>
<%
ConferenceMembership data = ConferenceMembership.retrieve(request);
Variables.failIfNull(data);
RenderData rdat = RenderConfig.createRenderData(application,request,response);
%>
<% rdat.writeContentHeader(out,"Set Conference Membership:",data.getConfName()); %>
<%= rdat.getStdFontTag(null,2) %>
<A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=Q") %>">Return to
Manage Conference Menu</A>
</FONT><P>
<%= rdat.getStdFontTag(null,3) %><B>Find users in SIG "<%= data.getSIGName() %>":</B></FONT><P>
<FORM METHOD="POST" ACTION="<%= rdat.getEncodedServletPath("confops") %>">
<INPUT TYPE="HIDDEN" NAME="sig" VALUE="<%= data.getSIGID() %>">
<INPUT TYPE="HIDDEN" NAME="conf" VALUE="<%= data.getConfID() %>">
<INPUT TYPE="HIDDEN" NAME="cmd" VALUE="M">
<INPUT TYPE="HIDDEN" NAME="ofs" VALUE="0">
<%= rdat.getStdFontTag(null,2) %>
Display all SIG members whose&nbsp;&nbsp;
<SELECT NAME="field" SIZE=1>
<OPTION VALUE="<%= SearchMode.FIELD_USER_NAME %>"
<% if (data.searchFieldIs(SearchMode.FIELD_USER_NAME)) { %>SELECTED<% } %> >user name</OPTION>
<OPTION VALUE="<%= SearchMode.FIELD_USER_DESCRIPTION %>"
<% if (data.searchFieldIs(SearchMode.FIELD_USER_DESCRIPTION)) { %>SELECTED<% } %> >description</OPTION>
<OPTION VALUE="<%= SearchMode.FIELD_USER_GIVEN_NAME %>"
<% if (data.searchFieldIs(SearchMode.FIELD_USER_GIVEN_NAME)) { %>SELECTED<% } %> >first name</OPTION>
<OPTION VALUE="<%= SearchMode.FIELD_USER_FAMILY_NAME %>"
<% if (data.searchFieldIs(SearchMode.FIELD_USER_FAMILY_NAME)) { %>SELECTED<% } %> >last name</OPTION>
</SELECT><BR>
<SELECT NAME="mode" SIZE=1>
<OPTION VALUE="<%= SearchMode.SEARCH_PREFIX %>"
<% if (data.searchModeIs(SearchMode.SEARCH_PREFIX)) { %>SELECTED<% } %> >starts with the string</OPTION>
<OPTION VALUE="<%= SearchMode.SEARCH_SUBSTRING %>"
<% if (data.searchModeIs(SearchMode.SEARCH_SUBSTRING)) { %>SELECTED<% } %> >contains the string</OPTION>
<OPTION VALUE="<%= SearchMode.SEARCH_REGEXP %>"
<% if (data.searchModeIs(SearchMode.SEARCH_REGEXP)) { %>SELECTED<% } %> >matches the regular
expression</OPTION>
</SELECT>
<INPUT TYPE=TEXT NAME="term" SIZE=32 MAXLENGTH=255 VALUE="<%= data.getSearchTerm() %>"><BR>
<INPUT TYPE=IMAGE NAME="search" SRC="<%= rdat.getFullImagePath("bn_search.gif") %>"
ALT="Search" WIDTH=80 HEIGHT=24 BORDER=0><BR>
</FONT>
</FORM>
<% if (data.displayList()) { %>
<% int dcount = data.getSize(); %>
<HR>
<% if (data.conferenceMemberList()) { %>
<%-- The conference list header --%>
<%= rdat.getStdFontTag(null,3) %><B>
Members of Conference "<%= StringUtil.encodeHTML(data.getConfName()) %>":
</B></FONT><BR>
<% } else { %>
<%
// Determine the number of results to display and whether to display a "next" button
boolean go_next = false;
if (dcount>data.getNumResultsDisplayed())
{ // there's a "next"
dcount = data.getNumResultsDisplayed();
go_next = true;
} // end if
%>
<TABLE WIDTH="100%" BORDER=0 ALIGN=CENTER><TR VALIGN=MIDDLE>
<TD WIDTH="50%" ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>
<%-- The search results header --%>
<FONT SIZE=+1><B>Search Results:</B></FONT>
<% if (data.getFindCount()>0) { %>
(Displaying <%= data.getOffset() + 1 %>-<%= data.getOffset() + dcount %> of
<%= data.getFindCount() %>)
<% } else { %>(None)<% } %>
</FONT></TD>
<TD WIDTH="50%" ALIGN=RIGHT>
<% if (go_next || (data.getOffset()>0)) { %>
<%-- The navigational form that allows us to page through the results --%>
<% if (rdat.useHTMLComments()) { %><!-- Navigational Form --><% } %>
<FORM METHOD="POST" ACTION="<%= rdat.getEncodedServletPath("confops") %>">
<INPUT TYPE=HIDDEN NAME="sig" VALUE="<%= data.getSIGID() %>">
<INPUT TYPE=HIDDEN NAME="conf" VALUE="<%= data.getConfID() %>">
<INPUT TYPE=HIDDEN NAME="cmd" VALUE="M">
<INPUT TYPE=HIDDEN NAME="ofs" VALUE="<%= data.getOffset() %>">
<INPUT TYPE=HIDDEN NAME="field" VALUE="<%= data.getSearchField() %>">
<INPUT TYPE=HIDDEN NAME="mode" VALUE="<%= data.getSearchMode() %>">
<INPUT TYPE=HIDDEN NAME="term" VALUE="<%= data.getSearchTerm() %>">
<INPUT TYPE=HIDDEN NAME="fcount" VALUE="<%= data.getFindCount() %>">
<% if (data.getOffset()>0) { %>
<INPUT TYPE=IMAGE NAME="previous" SRC="<%= rdat.getFullImagePath("bn_ar_previous.gif") %>"
ALT="Previous" WIDTH=80 HEIGHT=24 BORDER=0>
<% } else { %>
<IMG SRC="<%= rdat.getFullImagePath("bn_transparent.gif") %>" WIDTH=80 HEIGHT=24 BORDER=0>
<% } // end if %>
&nbsp;
<% if (go_next) { %>
<INPUT TYPE=IMAGE NAME="next" SRC="<%= rdat.getFullImagePath("bn_ar_next.gif") %>"
ALT="Next" WIDTH=80 HEIGHT=24 BORDER=0>
<% } else { %>
<IMG SRC="<%= rdat.getFullImagePath("bn_transparent.gif") %>" WIDTH=80 HEIGHT=24 BORDER=0>
<% } // end if %>
</FORM>
<% } else { %>&nbsp;<% } %>
</TD>
</TR></TABLE><BR>
<% } // end if %>
<%-- Display the results of the search --%>
<FORM METHOD="POST" ACTION="<%= rdat.getEncodedServletPath("confops") %>">
<INPUT TYPE=HIDDEN NAME="sig" VALUE="<%= data.getSIGID() %>">
<INPUT TYPE=HIDDEN NAME="conf" VALUE="<%= data.getConfID() %>">
<INPUT TYPE=HIDDEN NAME="cmd" VALUE="M">
<TABLE BORDER=0 ALIGN=LEFT CELLPADDING=0 CELLSPACING=4>
<% for (int i=0; i<dcount; i++) { %>
<% UserFound uf = data.getItem(i); %>
<TR VALIGN=MIDDLE>
<TD ALIGN=CENTER WIDTH=14>
<IMG SRC="<%= rdat.getFullImagePath("purple-ball.gif") %>" ALT="*" WIDTH=14 HEIGHT=14 BORDER=0>
</TD>
<TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>
<A HREF="<%= rdat.getEncodedServletPath("user/" + uf.getName()) %>"><%= uf.getName() %></A>
</FONT></TD>
<TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>
<% data.outputDropDown(out,uf.getUID(),uf.getLevel()); %>
</FONT></TD>
</TR>
<% } // end for %>
</TABLE><BR CLEAR=LEFT>
<INPUT TYPE=IMAGE SRC="<%= rdat.getFullImagePath("bn_update.gif") %>" NAME="update" ALT="Update"
WIDTH=80 HEIGHT=24 BORDER=0>
</FORM><BR>
<% } // end if %>
<% rdat.writeFooter(out); %>

View File

@ -59,12 +59,14 @@
Conference Information</A><P> Conference Information</A><P>
<A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=A") %>">Manage <A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=A") %>">Manage
Conference Aliases</A><P> Conference Aliases</A><P>
<A HREF="TODO">Manage Conference Members</A><P> <A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=M") %>">Manage
Conference Members</A><P>
<A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=RP") %>">Conference <A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=RP") %>">Conference
Posters Report</A><P> Posters Report</A><P>
<A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=RR") %>">Conference <A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=RR") %>">Conference
Readers/Lurkers Report</A><P> Readers/Lurkers Report</A><P>
<A HREF="TODO">Delete Conference</A><P> <A HREF="<%= rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=DEL") %>">Delete
Conference</A><P>
</B></FONT> </B></FONT>
<% } // end if (displaying admin section) %> <% } // end if (displaying admin section) %>