diff --git a/setup/database.sql b/setup/database.sql index 49c65be..0aeca4a 100644 --- a/setup/database.sql +++ b/setup/database.sql @@ -44,6 +44,13 @@ CREATE TABLE globals ( sig_create_lvl INT NOT NULL ); +# The global properties table. The "ndx" parameter is used to indicate what +# element is being loaded, and then the "data" element is parsed. +CREATE TABLE propglobal ( + ndx INT NOT NULL PRIMARY KEY, + data VARCHAR(255) +); + # The audit records table. Most "major" events add a record to this table. CREATE TABLE audit ( record BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, @@ -93,6 +100,15 @@ CREATE TABLE userprefs ( localeid VARCHAR(64) DEFAULT 'en_US' ); +# The per-user properties table. The "ndx" parameter is used to indicate what +# element is being loaded, and then the "data" element is parsed. +CREATE TABLE propuser ( + uid INT NOT NULL, + ndx INT NOT NULL, + data VARCHAR(255), + PRIMARY KEY (uid, ndx) +); + # Indicates what the top-level "sidebox" configuration is for any given user. CREATE TABLE sideboxes ( uid INT NOT NULL, @@ -238,6 +254,15 @@ CREATE TABLE sigban ( PRIMARY KEY (sigid, uid) ); +# The community properties table. The "index" parameter is used to indicate what +# element is being loaded, and then the "data" element is parsed. +CREATE TABLE propcomm ( + cid INT NOT NULL, + ndx INT NOT NULL, + data VARCHAR(255), + PRIMARY KEY (cid, ndx) +); + # The table describing conferences. Like original CW, confs may be linked to more # than one SIG. CREATE TABLE confs ( @@ -306,6 +331,15 @@ CREATE TABLE confhotlist ( INDEX inorder (uid, sequence) ); +# The conference properties table. The "index" parameter is used to indicate what +# element is being loaded, and then the "data" element is parsed. +CREATE TABLE propconf ( + confid INT NOT NULL, + ndx INT NOT NULL, + data VARCHAR(255), + PRIMARY KEY (confid, ndx) +); + # The table describing topics within a conference. CREATE TABLE topics ( topicid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, @@ -1372,12 +1406,17 @@ INSERT INTO globals (posts_per_page, old_posts_at_top, max_search_page, max_sig_ fp_posts, num_audit_page, sig_create_lvl) VALUES (20, 2, 20, 50, 50, 10, 100, 1000); +# Initialize the global properies table. +INSERT INTO propglobal (ndx, data) + VALUES (0, ''); + # Add the 'Anonymous Honyak' user to the users table. # (Do 'SELECT * FROM users WHERE is_anon = 1' to retrieve the AC user details.) # (UID = 1, CONTACTID = 1) INSERT INTO users (uid, username, passhash, contactid, is_anon, verify_email, base_lvl, created) VALUES (1, 'Anonymous_Honyak', '', 1, 1, 1, 100, '2000-12-01 00:00:00'); INSERT INTO userprefs (uid) VALUES (1); +INSERT INTO propuser (uid, ndx, data) VALUES (1, 0, ''); INSERT INTO contacts (contactid, given_name, family_name, locality, region, pcode, country, email, owner_uid) VALUES (1, 'Anonymous', 'User', 'Anywhere', '', '', 'US', 'nobody@example.com', 1); @@ -1393,6 +1432,7 @@ INSERT INTO confhotlist (uid, sequence, sigid, confid) INSERT INTO users (uid, username, passhash, contactid, verify_email, base_lvl, created) VALUES (2, 'Administrator', '', 2, 1, 64999, '2000-12-01 00:00:00'); INSERT INTO userprefs (uid) VALUES (2); +INSERT INTO propuser (uid, ndx, data) VALUES (2, 0, ''); INSERT INTO contacts (contactid, given_name, family_name, locality, region, pcode, country, email, owner_uid) VALUES (2, 'System', 'Administrator', 'Anywhere', '', '', 'US', 'root@your.box.com', 2); @@ -1412,6 +1452,7 @@ INSERT INTO sigs (sigid, createdate, read_lvl, write_lvl, create_lvl, delete_lvl 'Admin'); INSERT INTO contacts (contactid, locality, country, owner_uid, owner_sigid) VALUES (3, 'Anywhere', 'US', 2, 1); +INSERT INTO propcomm (cid, ndx, data) VALUES (1, 0, ''); # Insert the desired features for the 'Administration' SIG. INSERT INTO sigftrs (sigid, ftr_code) @@ -1430,6 +1471,7 @@ INSERT INTO confs (confid, createdate, read_lvl, post_lvl, create_lvl, hide_lvl, 'Administrative Notes', 'Used to store notes and discussions between the site administrators.'); INSERT INTO sigtoconf (sigid, confid, sequence) VALUES (1, 1, 10); INSERT INTO confalias (confid, alias) VALUES (1, 'Admin_Notes'); +INSERT INTO propconf (confid, ndx, data) VALUES (1, 0, ''); # Make the Administrator the host-of-record of the "Administrative Notes" conference. INSERT INTO confmember (confid, uid, granted_lvl) VALUES (1, 2, 52500); @@ -1444,6 +1486,7 @@ INSERT INTO sigs (sigid, createdate, read_lvl, write_lvl, create_lvl, delete_lvl 'Like the man said, do unto others as you would have them do unto you.', 'Piazza'); INSERT INTO contacts (contactid, locality, country, owner_uid, owner_sigid) VALUES (4, 'Anywhere', 'US', 2, 2); +INSERT INTO propcomm (cid, ndx, data) VALUES (2, 0, ''); # Insert the desired features for La Piazza. INSERT INTO sigftrs (sigid, ftr_code) @@ -1467,6 +1510,7 @@ INSERT INTO confs (confid, createdate, read_lvl, post_lvl, create_lvl, hide_lvl, 'Your place for general discussion about the system and general topics.'); INSERT INTO sigtoconf (sigid, confid, sequence) VALUES (2, 2, 10); INSERT INTO confalias (confid, alias) VALUES (2, 'General'); +INSERT INTO propconf (confid, ndx, data) VALUES (2, 0, ''); # Make the Administrator the host-of-record of the "General Discussion" conference. INSERT INTO confmember (confid, uid, granted_lvl) VALUES (2, 2, 52500); @@ -1479,6 +1523,7 @@ INSERT INTO confs (confid, createdate, read_lvl, post_lvl, create_lvl, hide_lvl, 'Use this conference to test the conferencing system.'); INSERT INTO sigtoconf (sigid, confid, sequence) VALUES (2, 3, 20); INSERT INTO confalias (confid, alias) VALUES (3, 'Test'); +INSERT INTO propconf (confid, ndx, data) VALUES (3, 0, ''); # Make the Administrator the host-of-record of the "Test Postings" conference. INSERT INTO confmember (confid, uid, granted_lvl) VALUES (3, 2, 52500); @@ -1492,6 +1537,7 @@ INSERT INTO confmember (confid, uid, granted_lvl) VALUES (3, 2, 52500); INSERT INTO users (uid, username, passhash, contactid, verify_email, base_lvl, created) VALUES (3, 'TestUser', '6BC1E91CF2917BE1AA0D0D1007C28437D3D3AEDF', 5, 1, 1000, '2000-12-01 00:00:00'); INSERT INTO userprefs (uid) VALUES (3); +INSERT INTO propuser (uid, ndx, data) VALUES (3, 0, ''); INSERT INTO contacts (contactid, given_name, family_name, locality, region, pcode, country, email, owner_uid) VALUES (5, 'Test', 'User', 'Denver', 'CO', '80231', 'US', 'testuser@example.com', 3); INSERT INTO sideboxes (uid, boxid, sequence, param) @@ -1510,6 +1556,7 @@ INSERT INTO sigs (sigid, createdate, read_lvl, write_lvl, create_lvl, delete_lvl 'You must have a silly walk.', 'sillywalk'); INSERT INTO contacts (contactid, locality, country, owner_uid, owner_sigid) VALUES (6, 'Anywhere', 'US', 2, 3); +INSERT INTO propcomm (cid, ndx, data) VALUES (3, 0, ''); INSERT INTO sigftrs (sigid, ftr_code) VALUES (3, 0), (3, 1), (3, 3); INSERT INTO sigmember (sigid, uid, granted_lvl, locked) @@ -1524,6 +1571,7 @@ INSERT INTO sigs (sigid, createdate, read_lvl, write_lvl, create_lvl, delete_lvl 'Evil Geniuses Only!', 'fnord', 'illuminati'); INSERT INTO contacts (contactid, locality, country, owner_uid, owner_sigid) VALUES (7, 'Anywhere', 'US', 2, 4); +INSERT INTO propcomm (cid, ndx, data) VALUES (4, 0, ''); INSERT INTO sigftrs (sigid, ftr_code) VALUES (4, 0), (4, 1), (4, 3); INSERT INTO sigmember (sigid, uid, granted_lvl, locked) diff --git a/src/com/silverwrist/util/OptionSet.java b/src/com/silverwrist/util/OptionSet.java index dd5c093..bf43b73 100644 --- a/src/com/silverwrist/util/OptionSet.java +++ b/src/com/silverwrist/util/OptionSet.java @@ -109,6 +109,19 @@ public class OptionSet extends BitSet *-------------------------------------------------------------------------------- */ + public boolean assign(int ndx, boolean val) + { + if (ndx>=ALPHA.length()) + throw new IndexOutOfBoundsException(); + boolean old = super.get(ndx); + if (val) + super.set(ndx); + else + super.clear(ndx); + return (old!=val); + + } // end assign + public void assign(char[] options) { int i; @@ -127,7 +140,8 @@ public class OptionSet extends BitSet public void assign(String options) { - assign(options.toCharArray()); + if (options!=null) + assign(options.toCharArray()); } // end assign diff --git a/src/com/silverwrist/venice/core/AdminOperations.java b/src/com/silverwrist/venice/core/AdminOperations.java index 89038a1..51ebf91 100644 --- a/src/com/silverwrist/venice/core/AdminOperations.java +++ b/src/com/silverwrist/venice/core/AdminOperations.java @@ -31,4 +31,8 @@ public interface AdminOperations public abstract AdminUserContext getUserContext(String username) throws DataException; + public abstract GlobalProperties getProperties(); + + public abstract void setProperties(GlobalProperties props) throws DataException; + } // end interface AdminOperations diff --git a/src/com/silverwrist/venice/core/CommunityContext.java b/src/com/silverwrist/venice/core/CommunityContext.java index 3351250..8ff8c14 100644 --- a/src/com/silverwrist/venice/core/CommunityContext.java +++ b/src/com/silverwrist/venice/core/CommunityContext.java @@ -171,4 +171,8 @@ public interface CommunityContext extends SearchMode public abstract int getAuditRecordCount() throws AccessError, DataException; + public abstract CommunityProperties getProperties() throws DataException, AccessError; + + public abstract void setProperties(CommunityProperties props) throws DataException, AccessError; + } // end interface CommunityContext diff --git a/src/com/silverwrist/venice/core/CommunityProperties.java b/src/com/silverwrist/venice/core/CommunityProperties.java new file mode 100644 index 0000000..480110b --- /dev/null +++ b/src/com/silverwrist/venice/core/CommunityProperties.java @@ -0,0 +1,57 @@ +/* + * 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 . + * + * 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 , + * 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; + +public final class CommunityProperties +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private boolean display_post_pictures; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public CommunityProperties() + { + display_post_pictures = false; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Public getters/setters + *-------------------------------------------------------------------------------- + */ + + public final boolean getDisplayPostPictures() + { + return display_post_pictures; + + } // end getDisplayPostPictures + + public final void setDisplayPostPictures(boolean b) + { + display_post_pictures = b; + + } // end setDisplayPostPictures + +} // end class CommunityProperties diff --git a/src/com/silverwrist/venice/core/ConferenceContext.java b/src/com/silverwrist/venice/core/ConferenceContext.java index f49550e..30a7feb 100644 --- a/src/com/silverwrist/venice/core/ConferenceContext.java +++ b/src/com/silverwrist/venice/core/ConferenceContext.java @@ -153,4 +153,10 @@ public interface ConferenceContext public abstract void setHotlistSequence(int seq) throws DataException; + public abstract boolean displayPostPictures(); + + public abstract ConferenceProperties getProperties() throws DataException, AccessError; + + public abstract void setProperties(ConferenceProperties props) throws DataException, AccessError; + } // end interface ConferenceContext diff --git a/src/com/silverwrist/venice/core/ConferenceProperties.java b/src/com/silverwrist/venice/core/ConferenceProperties.java new file mode 100644 index 0000000..10f3673 --- /dev/null +++ b/src/com/silverwrist/venice/core/ConferenceProperties.java @@ -0,0 +1,57 @@ +/* + * 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 . + * + * 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 , + * 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; + +public final class ConferenceProperties +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private boolean display_post_pictures; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public ConferenceProperties() + { + display_post_pictures = false; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Public getters/setters + *-------------------------------------------------------------------------------- + */ + + public final boolean getDisplayPostPictures() + { + return display_post_pictures; + + } // end getDisplayPostPictures + + public final void setDisplayPostPictures(boolean b) + { + display_post_pictures = b; + + } // end setDisplayPostPictures + +} // end class ConferenceProperties diff --git a/src/com/silverwrist/venice/core/GlobalProperties.java b/src/com/silverwrist/venice/core/GlobalProperties.java new file mode 100644 index 0000000..fe0db42 --- /dev/null +++ b/src/com/silverwrist/venice/core/GlobalProperties.java @@ -0,0 +1,169 @@ +/* + * 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 . + * + * 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 , + * 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; + +public final class GlobalProperties +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private int posts_per_page; + private int old_posts_at_top; + private int search_items_per_page; + private int community_members_per_page; + private int conference_members_per_page; + private int posts_on_front_page; + private int audit_records_per_page; + private int community_create_level; + private boolean display_post_pictures; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public GlobalProperties() + { + posts_per_page = 20; + old_posts_at_top = 2; + search_items_per_page = 20; + community_members_per_page = 50; + conference_members_per_page = 50; + posts_on_front_page = 10; + audit_records_per_page = 100; + community_create_level = com.silverwrist.venice.security.SecLevels.GLOBAL_NORMAL; + display_post_pictures = false; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Public getters/setters + *-------------------------------------------------------------------------------- + */ + + public final int getPostsPerPage() + { + return posts_per_page; + + } // end getPostsPerPage + + public final void setPostsPerPage(int v) + { + posts_per_page = v; + + } // end setPostsPerPage + + public final int getOldPostsAtTop() + { + return old_posts_at_top; + + } // end getOldPostsAtTop + + public final void setOldPostsAtTop(int v) + { + old_posts_at_top = v; + + } // end setOldPostsAtTop + + public final int getSearchItemsPerPage() + { + return search_items_per_page; + + } // end getSearchItemsPerPage + + public final void setSearchItemsPerPage(int v) + { + search_items_per_page = v; + + } // end setSearchItemsPerPage + + public final int getCommunityMembersPerPage() + { + return community_members_per_page; + + } // end getCommunityMembersPerPage + + public final void setCommunityMembersPerPage(int v) + { + community_members_per_page = v; + + } // end setCommunityMembersPerPage + + public final int getConferenceMembersPerPage() + { + return conference_members_per_page; + + } // end getConferenceMembersPerPage + + public final void setConferenceMembersPerPage(int v) + { + conference_members_per_page = v; + + } // end setConferenceMembersPerPage + + public final int getPostsOnFrontPage() + { + return posts_on_front_page; + + } // end getPostsOnFontPage + + public final void setPostsOnFrontPage(int v) + { + posts_on_front_page = v; + + } // end setPostsOnFrontPage + + public final int getAuditRecordsPerPage() + { + return audit_records_per_page; + + } // end getAuditRecordsPerPage + + public final void setAuditRecordsPerPage(int v) + { + audit_records_per_page = v; + + } // end setAuditRecordsPerPage + + public final int getCommunityCreateLevel() + { + return community_create_level; + + } // end getCommunityCreateLevel + + public final void setCommunityCreateLevel(int v) + { + community_create_level = v; + + } // end setCommunityCreateLevel + + public final boolean getDisplayPostPictures() + { + return display_post_pictures; + + } // end getDisplayPostPictures + + public final void setDisplayPostPictures(boolean b) + { + display_post_pictures = b; + + } // end setDisplayPostPictures + +} // end class GlobalProperties diff --git a/src/com/silverwrist/venice/core/UserContext.java b/src/com/silverwrist/venice/core/UserContext.java index 250dc2a..8c56ca5 100644 --- a/src/com/silverwrist/venice/core/UserContext.java +++ b/src/com/silverwrist/venice/core/UserContext.java @@ -112,4 +112,10 @@ public interface UserContext extends SearchMode public abstract Advertisement selectAd(); + public abstract boolean displayPostPictures() throws DataException; + + public abstract UserProperties getProperties() throws DataException; + + public abstract void setProperties(UserProperties props) throws DataException; + } // end interface UserContext diff --git a/src/com/silverwrist/venice/core/UserProperties.java b/src/com/silverwrist/venice/core/UserProperties.java new file mode 100644 index 0000000..21cd1f1 --- /dev/null +++ b/src/com/silverwrist/venice/core/UserProperties.java @@ -0,0 +1,57 @@ +/* + * 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 . + * + * 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 , + * 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; + +public final class UserProperties +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private boolean display_post_pictures; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public UserProperties() + { + display_post_pictures = false; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Public getters/setters + *-------------------------------------------------------------------------------- + */ + + public final boolean getDisplayPostPictures() + { + return display_post_pictures; + + } // end getDisplayPostPictures + + public final void setDisplayPostPictures(boolean b) + { + display_post_pictures = b; + + } // end setDisplayPostPictures + +} // end class UserProperties diff --git a/src/com/silverwrist/venice/core/impl/AdminOperationsImpl.java b/src/com/silverwrist/venice/core/impl/AdminOperationsImpl.java index 02a6368..c96143f 100644 --- a/src/com/silverwrist/venice/core/impl/AdminOperationsImpl.java +++ b/src/com/silverwrist/venice/core/impl/AdminOperationsImpl.java @@ -135,4 +135,16 @@ class AdminOperationsImpl implements AdminOperations } // end getUserContext + public GlobalProperties getProperties() + { + return engine.getProperties(); + + } // end getProperties + + public void setProperties(GlobalProperties props) throws DataException + { + engine.setProperties(props); + + } // end setProperties + } // end class AdminOperationsImpl diff --git a/src/com/silverwrist/venice/core/impl/BackgroundCommunityPurge.java b/src/com/silverwrist/venice/core/impl/BackgroundCommunityPurge.java index 4bc7c4c..ae8e981 100644 --- a/src/com/silverwrist/venice/core/impl/BackgroundCommunityPurge.java +++ b/src/com/silverwrist/venice/core/impl/BackgroundCommunityPurge.java @@ -88,6 +88,7 @@ class BackgroundCommunityPurge implements Runnable stmt.executeUpdate("DELETE FROM contacts WHERE owner_sigid = " + cid + ";"); stmt.executeUpdate("DELETE FROM sigftrs WHERE sigid = " + cid + ";"); stmt.executeUpdate("DELETE FROM sigban WHERE sigid = " + cid + ";"); + stmt.executeUpdate("DELETE FROM propcomm WHERE cid = " + cid + ";"); // look up all conference IDs in this community int[] conf_ids = new int[num_confs]; @@ -132,6 +133,7 @@ class BackgroundCommunityPurge implements Runnable // tables first stmt.executeUpdate("DELETE FROM confs WHERE confid = " + key + ";"); stmt.executeUpdate("DELETE FROM confalias WHERE confid = " + key + ";"); + stmt.executeUpdate("DELETE FROM propconf WHERE confid = " + key + ";"); // determine the number of topics in this conference, and the maximum topic ID, and use // that information to queue up the conference deletion diff --git a/src/com/silverwrist/venice/core/impl/BackgroundConferencePurge.java b/src/com/silverwrist/venice/core/impl/BackgroundConferencePurge.java index 3450d2e..bdb0410 100644 --- a/src/com/silverwrist/venice/core/impl/BackgroundConferencePurge.java +++ b/src/com/silverwrist/venice/core/impl/BackgroundConferencePurge.java @@ -81,7 +81,7 @@ class BackgroundConferencePurge implements Runnable 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 + ";"); + stmt.executeUpdate("DELETE FROM propconf WHERE confid = " + confid + ";"); // look up all the topic IDs that are present in this conference int[] topicids = new int[num_topics]; diff --git a/src/com/silverwrist/venice/core/impl/CommunityBackend.java b/src/com/silverwrist/venice/core/impl/CommunityBackend.java index da45b8d..d53761c 100644 --- a/src/com/silverwrist/venice/core/impl/CommunityBackend.java +++ b/src/com/silverwrist/venice/core/impl/CommunityBackend.java @@ -40,4 +40,6 @@ public interface CommunityBackend extends UserBackend public abstract boolean userCanDeleteSubobjects(); + public abstract CommunityDataBackend getDataBackend() throws DataException; + } // end interface CommunityBackend diff --git a/src/com/silverwrist/venice/core/impl/CommunityCoreData.java b/src/com/silverwrist/venice/core/impl/CommunityCoreData.java index a13c6e8..847b7b5 100644 --- a/src/com/silverwrist/venice/core/impl/CommunityCoreData.java +++ b/src/com/silverwrist/venice/core/impl/CommunityCoreData.java @@ -20,6 +20,7 @@ package com.silverwrist.venice.core.impl; import java.sql.*; import java.util.*; import org.apache.log4j.*; +import com.silverwrist.util.OptionSet; import com.silverwrist.util.StringUtil; import com.silverwrist.util.rcache.*; import com.silverwrist.venice.db.*; @@ -64,6 +65,11 @@ class CommunityCoreData implements CommunityData, CommunityDataBackend *-------------------------------------------------------------------------------- */ + // Property indices + private static final int PROP_FLAGS = 0; // flags + + private static final BitSet ALL_PROPS; // BitSet representing all properties + private static Category logger = Category.getInstance(CommunityCoreData.class); /*-------------------------------------------------------------------------------- @@ -101,6 +107,7 @@ class CommunityCoreData implements CommunityData, CommunityDataBackend private ReferenceCache conf_refcache = new ReferenceCache(); private ConferenceCommunityContextImplCreator conf_creator = new ConferenceCommunityContextImplCreator(); private boolean deleted = false; // has this community been deleted? + private OptionSet flags; // property flags /*-------------------------------------------------------------------------------- * Constructor @@ -131,6 +138,24 @@ class CommunityCoreData implements CommunityData, CommunityDataBackend loadData(rs); // load the community data + sql.setLength(0); + sql.append("SELECT ndx, data FROM propcomm WHERE cid = ").append(cid).append(';'); + rs = stmt.executeQuery(sql.toString()); + while (rs.next()) + { // load all properties + switch (rs.getInt(1)) + { // look for the various property indices + case PROP_FLAGS: + flags = new OptionSet(rs.getString(2)); + break; + + default: + break; + + } // end switch + + } // end while + // get the community feature set sql.setLength(0); sql.append("SELECT ftr_code FROM sigftrs WHERE sigid = ").append(cid).append(';'); @@ -188,6 +213,9 @@ class CommunityCoreData implements CommunityData, CommunityDataBackend this.alias = alias; this.public_comm = StringUtil.isStringEmpty(joinkey); this.features = (BitSet)(features.clone()); + this.flags = new OptionSet(); + if (engine.getParamBoolean(EngineBackend.BP_POSTPICTURES)) + flags.set(BP_POSTPICTURES); } // end constructor @@ -266,6 +294,81 @@ class CommunityCoreData implements CommunityData, CommunityDataBackend } // end touchUpdate + private void newProperties(Connection conn) throws SQLException + { + // generate start of SQL statement + Statement stmt = conn.createStatement(); + StringBuffer sql = new StringBuffer("INSERT INTO propcomm (cid, ndx, data) VALUES "); + + // append Property 0: flags + sql.append('(').append(cid).append(", ").append(PROP_FLAGS).append(", '"); + sql.append(flags.asString()).append("')"); + + // finish up + sql.append(';'); + stmt.executeUpdate(sql.toString()); + + } // end newProperties + + private synchronized void updateProperties(BitSet delta) throws DataException + { + Connection conn = null; + try + { // get a connection and create a statement + conn = datapool.getConnection(); + Statement stmt = conn.createStatement(); + StringBuffer sql = new StringBuffer(); + + if (delta.get(PROP_FLAGS)) + { // store the flags + sql.append("UPDATE propcomm SET data = '").append(flags.asString()).append("' WHERE cid = "); + sql.append(cid).append(" AND ndx = ").append(PROP_FLAGS).append(';'); + stmt.executeUpdate(sql.toString()); + sql.setLength(0); + + } // end if + + } // end try + catch (SQLException e) + { // database error - this is a DataException + logger.error("DB error storing community properties: " + e.getMessage(),e); + throw new DataException("unable to save community properties: " + e.getMessage(),e); + + } // end catch + finally + { // make sure the connection is released before we go + if (conn!=null) + datapool.releaseConnection(conn); + + } // end finally + + } // end updateProperties + + private synchronized void updateProperties() throws DataException + { + updateProperties(ALL_PROPS); + + } // end updateProperties + + private final CommunityProperties createProperties() + { + CommunityProperties rc = new CommunityProperties(); + rc.setDisplayPostPictures(flags.get(BP_POSTPICTURES)); + return rc; + + } // end createProperties + + private final synchronized BitSet storeProperties(CommunityProperties props) + { + BitSet rc = new BitSet(); + + if (flags.assign(BP_POSTPICTURES,props.getDisplayPostPictures())) + rc.set(PROP_FLAGS); + + return rc; + + } // end storeProperties + /*-------------------------------------------------------------------------------- * Implementations from interface ReferencedData *-------------------------------------------------------------------------------- @@ -1886,6 +1989,35 @@ class CommunityCoreData implements CommunityData, CommunityDataBackend } // end sweepCache + public CommunityProperties getProperties() + { + return createProperties(); + + } // end getProperties + + public void setProperties(CommunityProperties props) throws DataException + { + CommunityProperties orig = createProperties(); + BitSet delta = storeProperties(props); + if (delta.length()==0) + return; + + boolean succeeded = false; + try + { // update the properties in the database + updateProperties(delta); + succeeded = true; + + } // end try + finally + { // make sure the connection is released before we go + if (!succeeded) + storeProperties(orig); + + } // end finally + + } // end setProperties + /*-------------------------------------------------------------------------------- * Implementations from interface CommunityDataBackend *-------------------------------------------------------------------------------- @@ -1897,6 +2029,12 @@ class CommunityCoreData implements CommunityData, CommunityDataBackend } // end realCommunityID + public boolean getParamBoolean(int selector) + { + return flags.get(selector); + + } // end getParamBoolean + /*-------------------------------------------------------------------------------- * External static operations (usable only from within package) *-------------------------------------------------------------------------------- @@ -1912,12 +2050,13 @@ class CommunityCoreData implements CommunityData, CommunityDataBackend int new_cid; // ID of the new community java.util.Date creation; // creation date! AuditRecord ar = null; // the audit record + CommunityCoreData comm; // the new community that gets returned try { // get a database connection and create the appropriate SELECT statement conn = datapool.getConnection(); Statement stmt = conn.createStatement(); - stmt.executeUpdate("LOCK TABLES sigs WRITE, sigftrs WRITE, sigmember WRITE;"); + stmt.executeUpdate("LOCK TABLES sigs WRITE, sigftrs WRITE, propcomm WRITE, sigmember WRITE;"); try { // first, we need to check if the community alias already exists @@ -1997,6 +2136,12 @@ class CommunityCoreData implements CommunityData, CommunityDataBackend logger.debug("SQL: " + sql.toString()); stmt.executeUpdate(sql.toString()); + // Create the CommunityCoreData object representing this community and register it with the engine's + // community data object cache. + comm = new CommunityCoreData(engine,datapool,new_cid,creation,name,alias,host_uid,language,synopsis, + rules,joinkey,hide_dir,hide_search,def_features); + comm.newProperties(conn); + } // end try finally { // unlock the tables before we bail out @@ -2005,10 +2150,12 @@ class CommunityCoreData implements CommunityData, CommunityDataBackend } // end finally + engine.registerNewCommunity(comm); + // create an audit record indicating we were successful ar = new AuditRecord(AuditRecord.CREATE_COMMUNITY,host_uid,user.userRemoteAddress(),new_cid, "name=" + name,"alias=" + alias); - + } // end try catch (SQLException e) { // database error - this is a DataException @@ -2035,14 +2182,21 @@ class CommunityCoreData implements CommunityData, CommunityDataBackend } // end finally - // Create the CommunityCoreData object representing this community and register it with the engine's - // community data object cache. - CommunityCoreData comm = new CommunityCoreData(engine,datapool,new_cid,creation,name,alias,host_uid, - language,synopsis,rules,joinkey,hide_dir,hide_search, - def_features); - engine.registerNewCommunity(comm); return comm; } // end createCommunity + /*-------------------------------------------------------------------------------- + * Static initializer + *-------------------------------------------------------------------------------- + */ + + static + { // initialize the "all properties" bit set + BitSet tmp = new BitSet(); + tmp.set(PROP_FLAGS); + ALL_PROPS = tmp; + + } // end static initializer + } // end class CommunityCoreData diff --git a/src/com/silverwrist/venice/core/impl/CommunityData.java b/src/com/silverwrist/venice/core/impl/CommunityData.java index 67ee296..33b4237 100644 --- a/src/com/silverwrist/venice/core/impl/CommunityData.java +++ b/src/com/silverwrist/venice/core/impl/CommunityData.java @@ -22,6 +22,7 @@ import java.util.Date; import java.util.List; import com.silverwrist.util.rcache.ReferencedData; import com.silverwrist.venice.core.AccessError; +import com.silverwrist.venice.core.CommunityProperties; import com.silverwrist.venice.core.ContactInfo; import com.silverwrist.venice.core.DataException; @@ -154,4 +155,8 @@ public interface CommunityData extends ReferencedData public abstract void sweepCache(); + public abstract CommunityProperties getProperties(); + + public abstract void setProperties(CommunityProperties props) throws DataException; + } // end interface CommunityData diff --git a/src/com/silverwrist/venice/core/impl/CommunityDataBackend.java b/src/com/silverwrist/venice/core/impl/CommunityDataBackend.java index 7114444..3a85aba 100644 --- a/src/com/silverwrist/venice/core/impl/CommunityDataBackend.java +++ b/src/com/silverwrist/venice/core/impl/CommunityDataBackend.java @@ -19,6 +19,11 @@ package com.silverwrist.venice.core.impl; public interface CommunityDataBackend { + // Boolean parameter indexes + public static final int BP_POSTPICTURES = 0; + public abstract int realCommunityID(); + public abstract boolean getParamBoolean(int selector); + } // end interface CommunityDataBackend diff --git a/src/com/silverwrist/venice/core/impl/CommunityUserContextImpl.java b/src/com/silverwrist/venice/core/impl/CommunityUserContextImpl.java index d47b6dc..9f8e502 100644 --- a/src/com/silverwrist/venice/core/impl/CommunityUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/CommunityUserContextImpl.java @@ -1361,6 +1361,36 @@ class CommunityUserContextImpl implements CommunityContext, CommunityBackend } // end getAuditRecordCount + public CommunityProperties getProperties() throws DataException, AccessError + { + getData().testMembership(level,is_member); + if (!(getData().canModifyCommunityProfile(level))) + { // this user can't modify the community feature set + logger.error("user not permitted to modify the community's information"); + throw new AccessError("You are not permitted to modify the community's information."); + + } // end if + + // call down to do it + return getData().getProperties(); + + } // end getProperties + + public void setProperties(CommunityProperties props) throws DataException, AccessError + { + getData().testMembership(level,is_member); + if (!(getData().canModifyCommunityProfile(level))) + { // this user can't modify the community feature set + logger.error("user not permitted to modify the community's information"); + throw new AccessError("You are not permitted to modify the community's information."); + + } // end if + + // call down to do it + getData().setProperties(props); + + } // end setProperties + /*-------------------------------------------------------------------------------- * Implementations from interface UserBackend *-------------------------------------------------------------------------------- @@ -1485,6 +1515,12 @@ class CommunityUserContextImpl implements CommunityContext, CommunityBackend } // end userCanDeleteSubobjects + public CommunityDataBackend getDataBackend() throws DataException + { + return (CommunityDataBackend)(getData()); + + } // end getDataBackend + /*-------------------------------------------------------------------------------- * Static operations for use within the implementation package *-------------------------------------------------------------------------------- diff --git a/src/com/silverwrist/venice/core/impl/ConferenceCommunityContext.java b/src/com/silverwrist/venice/core/impl/ConferenceCommunityContext.java index 1e6945e..4de21b9 100644 --- a/src/com/silverwrist/venice/core/impl/ConferenceCommunityContext.java +++ b/src/com/silverwrist/venice/core/impl/ConferenceCommunityContext.java @@ -21,6 +21,7 @@ import java.sql.Connection; import java.util.Date; import java.util.List; import com.silverwrist.util.rcache.ReferencedData; +import com.silverwrist.venice.core.ConferenceProperties; import com.silverwrist.venice.core.DataException; public interface ConferenceCommunityContext extends ReferencedData @@ -109,4 +110,10 @@ public interface ConferenceCommunityContext extends ReferencedData public abstract void delete(UserBackend user) throws DataException; + public abstract boolean displayPostPictures(); + + public abstract ConferenceProperties getProperties() throws DataException; + + public abstract void setProperties(ConferenceProperties props) throws DataException; + } // end interface ConferenceCommunityContext diff --git a/src/com/silverwrist/venice/core/impl/ConferenceCommunityContextImpl.java b/src/com/silverwrist/venice/core/impl/ConferenceCommunityContextImpl.java index 3778e59..056207c 100644 --- a/src/com/silverwrist/venice/core/impl/ConferenceCommunityContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/ConferenceCommunityContextImpl.java @@ -833,4 +833,26 @@ class ConferenceCommunityContextImpl implements ConferenceCommunityContext } // end delete + public boolean displayPostPictures() + { + ConferenceData c = getConferenceDataNE(); + if (c!=null) + return c.displayPostPictures(); + else + return false; + + } // end displayPostPictures + + public ConferenceProperties getProperties() throws DataException + { + return getConferenceData().getProperties(); + + } // end getProperties + + public void setProperties(ConferenceProperties props) throws DataException + { + getConferenceData().setProperties(props); + + } // end setProperties + } // end class ConferenceCommunityContextImpl diff --git a/src/com/silverwrist/venice/core/impl/ConferenceCoreData.java b/src/com/silverwrist/venice/core/impl/ConferenceCoreData.java index 556be0e..5885182 100644 --- a/src/com/silverwrist/venice/core/impl/ConferenceCoreData.java +++ b/src/com/silverwrist/venice/core/impl/ConferenceCoreData.java @@ -20,6 +20,7 @@ package com.silverwrist.venice.core.impl; import java.sql.*; import java.util.*; import org.apache.log4j.*; +import com.silverwrist.util.OptionSet; import com.silverwrist.venice.db.*; import com.silverwrist.venice.security.AuditRecord; import com.silverwrist.venice.security.DefaultLevels; @@ -32,6 +33,14 @@ class ConferenceCoreData implements ConferenceData *-------------------------------------------------------------------------------- */ + // Property indexes + private static final int PROP_FLAGS = 0; // flags + + private static final BitSet ALL_PROPS; // BitSet representing all properties + + // Boolean property selectors + private static final int BP_POSTPICTURES = 0; + private static Category logger = Category.getInstance(ConferenceCoreData.class); /*-------------------------------------------------------------------------------- @@ -58,6 +67,7 @@ class ConferenceCoreData implements ConferenceData private String cached_alias = null; // the cached alias (for getAnAlias) private boolean creating_topic = false; // is somebody creating a topic? private boolean deleted = false; // has this conference been deleted? + private OptionSet flags; // option flags /*-------------------------------------------------------------------------------- * Constructors @@ -87,6 +97,8 @@ class ConferenceCoreData implements ConferenceData throw new DataException("Conference #" + confid + " does not exist in the database."); loadData(rs); // load the conference data + flags = new OptionSet(); + loadProperties(conn); } // end try catch (SQLException e) @@ -104,8 +116,8 @@ class ConferenceCoreData implements ConferenceData } // end constructor - protected ConferenceCoreData(EngineBackend engine, DataPool datapool, int confid, java.util.Date created, - boolean pvt, String name, String descr) + protected ConferenceCoreData(EngineBackend engine, CommunityDataBackend comm, DataPool datapool, int confid, + java.util.Date created, boolean pvt, String name, String descr) { if (logger.isDebugEnabled()) logger.debug("new ConferenceCoreData for NEW conference " + confid); @@ -124,6 +136,9 @@ class ConferenceCoreData implements ConferenceData this.top_topic = 0; this.name = name; this.description = descr; + this.flags = new OptionSet(); + if (comm.getParamBoolean(CommunityDataBackend.BP_POSTPICTURES)) + flags.set(BP_POSTPICTURES); } // end constructor @@ -151,6 +166,29 @@ class ConferenceCoreData implements ConferenceData } // end loadData + private synchronized void loadProperties(Connection conn) throws SQLException + { + Statement stmt = conn.createStatement(); + StringBuffer sql = new StringBuffer("SELECT ndx, data FROM propconf WHERE confid = "); + sql.append(confid).append(';'); + ResultSet rs = stmt.executeQuery(sql.toString()); + while (rs.next()) + { // load the property records one at a time + switch (rs.getInt(1)) + { // figure out which properties to load + case PROP_FLAGS: + flags.assign(rs.getString(2)); + break; + + default: + break; + + } // end switch + + } // end while + + } // end loadProperties + private synchronized void touchUpdate(Connection conn) throws SQLException { Statement stmt = conn.createStatement(); @@ -162,6 +200,80 @@ class ConferenceCoreData implements ConferenceData } // end touchUpdate + private void newProperties(Connection conn) throws SQLException + { + Statement stmt = conn.createStatement(); + StringBuffer sql = new StringBuffer("INSERT INTO propconf (confid, ndx, data) VALUES "); + + // Append Property 0 - the "flags" property. + sql.append('(').append(confid).append(", ").append(PROP_FLAGS).append(", '"); + sql.append(flags.asString()).append("')"); + + // Finish up. + sql.append(';'); + stmt.executeUpdate(sql.toString()); + + } // end newProperties + + private synchronized void updateProperties(BitSet delta) throws DataException + { + Connection conn = null; + try + { // get a connection and create a statement + conn = datapool.getConnection(); + Statement stmt = conn.createStatement(); + StringBuffer sql = new StringBuffer(); + + if (delta.get(PROP_FLAGS)) + { // store the flags + sql.append("UPDATE propconf SET data = '").append(flags.asString()).append("' WHERE confid = "); + sql.append(confid).append(" AND ndx = ").append(PROP_FLAGS).append(';'); + stmt.executeUpdate(sql.toString()); + sql.setLength(0); + + } // end if + + } // end try + catch (SQLException e) + { // database error - this is a DataException + logger.error("DB error storing conference properties: " + e.getMessage(),e); + throw new DataException("unable to save conference properties: " + e.getMessage(),e); + + } // end catch + finally + { // make sure the connection is released before we go + if (conn!=null) + datapool.releaseConnection(conn); + + } // end finally + + } // end updateProperties + + private synchronized void updateProperties() throws DataException + { + updateProperties(ALL_PROPS); + + } // end updateProperties + + private final ConferenceProperties createProperties() + { + ConferenceProperties rc = new ConferenceProperties(); + rc.setDisplayPostPictures(flags.get(BP_POSTPICTURES)); + return rc; + + } // end createProperties + + private final synchronized BitSet storeProperties(ConferenceProperties props) + { + BitSet rc = new BitSet(); + + if (flags.assign(BP_POSTPICTURES,props.getDisplayPostPictures())) + rc.set(PROP_FLAGS); + + return rc; + + } // end storeProperties + /*-------------------------------------------------------------------------------- * Implementations from interface ReferencedData *-------------------------------------------------------------------------------- @@ -1254,6 +1366,41 @@ class ConferenceCoreData implements ConferenceData } // end delete + public boolean displayPostPictures() + { + return flags.get(BP_POSTPICTURES); + + } // end displayPostPictures + + public ConferenceProperties getProperties() + { + return createProperties(); + + } // end getProperties + + public synchronized void setProperties(ConferenceProperties props) throws DataException + { + ConferenceProperties orig = createProperties(); + BitSet delta = storeProperties(props); + if (delta.length()==0) + return; + + boolean succeeded = false; + try + { // update the properties in the database + updateProperties(delta); + succeeded = true; + + } // end try + finally + { // make sure the connection is released before we go + if (!succeeded) + storeProperties(orig); + + } // end finally + + } // end setProperties + /*-------------------------------------------------------------------------------- * External static operations (usable only from within package) *-------------------------------------------------------------------------------- @@ -1263,11 +1410,13 @@ class ConferenceCoreData implements ConferenceData String name, String alias, String description, boolean pvt, boolean hide_list, int host_uid) throws DataException { + CommunityDataBackend data_backend = comm.getDataBackend(); Connection conn = null; // database connection AuditRecord ar = null; // audit record int new_confid; // new conference ID short new_sequence; // new sequence number java.util.Date created; // date/time conference created + ConferenceCoreData conf; // returned conference core data if (logger.isDebugEnabled()) logger.debug("createConference entry"); @@ -1276,7 +1425,8 @@ class ConferenceCoreData implements ConferenceData { // start by locking all the tables we need conn = datapool.getConnection(); Statement stmt = conn.createStatement(); - stmt.executeUpdate("LOCK TABLES confs WRITE, sigtoconf WRITE, confalias WRITE, confmember WRITE;"); + stmt.executeUpdate("LOCK TABLES confs WRITE, sigtoconf WRITE, confalias WRITE, confmember WRITE, " + + "propconf WRITE;"); try { // first check on the alias availability @@ -1347,6 +1497,11 @@ class ConferenceCoreData implements ConferenceData logger.debug("SQL: " + sql.toString()); stmt.executeUpdate(sql.toString()); + // Create a new ConferenceCoreData object representing this conference and register it with the + // engine's conference data object cache. + conf = new ConferenceCoreData(engine,data_backend,datapool,new_confid,created,pvt,name,description); + conf.newProperties(conn); + } // end try finally { // unlock the tables before we go @@ -1355,6 +1510,8 @@ class ConferenceCoreData implements ConferenceData } // end finally + engine.registerNewConference(conf); + // create an audit record indicating we were successful ar = new AuditRecord(AuditRecord.CREATE_CONF,comm.realUID(),comm.userRemoteAddress(), comm.realCommunityID(),"confid=" + new_confid,"name=" + name,"alias=" + alias); @@ -1385,12 +1542,21 @@ class ConferenceCoreData implements ConferenceData } // end finally - // Create a new ConferenceCoreData object representing this conference and register it with the - // engine's conference data object cache. - ConferenceCoreData conf = new ConferenceCoreData(engine,datapool,new_confid,created,pvt,name,description); - engine.registerNewConference(conf); return new ReturnConfSeq(conf,new_sequence); } // end createConference + /*-------------------------------------------------------------------------------- + * Static initializer + *-------------------------------------------------------------------------------- + */ + + static + { // initialize the "all properties" bit set + BitSet tmp = new BitSet(); + tmp.set(PROP_FLAGS); + ALL_PROPS = tmp; + + } // end static initializer + } // end class ConferenceCoreData diff --git a/src/com/silverwrist/venice/core/impl/ConferenceData.java b/src/com/silverwrist/venice/core/impl/ConferenceData.java index 8a8d625..fac9132 100644 --- a/src/com/silverwrist/venice/core/impl/ConferenceData.java +++ b/src/com/silverwrist/venice/core/impl/ConferenceData.java @@ -21,6 +21,7 @@ import java.sql.Connection; import java.util.Date; import java.util.List; import com.silverwrist.util.rcache.ReferencedData; +import com.silverwrist.venice.core.ConferenceProperties; import com.silverwrist.venice.core.DataException; public interface ConferenceData extends ReferencedData @@ -103,4 +104,10 @@ public interface ConferenceData extends ReferencedData public abstract void delete(UserBackend user, int the_cid) throws DataException; + public abstract boolean displayPostPictures(); + + public abstract ConferenceProperties getProperties(); + + public abstract void setProperties(ConferenceProperties props) throws DataException; + } // end interface ConferenceData diff --git a/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java b/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java index ddf42c5..3cafeeb 100644 --- a/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/ConferenceUserContextImpl.java @@ -1442,6 +1442,43 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend } // end setHotlistSequence + public boolean displayPostPictures() + { + ConferenceCommunityContext c = getConferenceDataNE(); + if (c==null) + return false; + return c.displayPostPictures(); + + } // end displayPostPictures + + public ConferenceProperties getProperties() throws DataException, AccessError + { + if (!(getConferenceData().canChangeConference(level))) + { // this user can't modify the conference properties + logger.error("user not permitted to change properties"); + throw new AccessError("You are not permitted to change the properties of this conference."); + + } // end if + + // call down to get the properties + return getConferenceData().getProperties(); + + } // end getProperties + + public void setProperties(ConferenceProperties props) throws DataException, AccessError + { + if (!(getConferenceData().canChangeConference(level))) + { // this user can't modify the conference properties + logger.error("user not permitted to change properties"); + throw new AccessError("You are not permitted to change the properties of this conference."); + + } // end if + + // call down to set the properties + getConferenceData().setProperties(props); + + } // end setProperties + /*-------------------------------------------------------------------------------- * Implementations from interface UserBackend *-------------------------------------------------------------------------------- @@ -1560,6 +1597,12 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend } // end userCanDeleteSubobjects + public CommunityDataBackend getDataBackend() throws DataException + { + return comm.getDataBackend(); + + } // end getDataBackend + /*-------------------------------------------------------------------------------- * Implementations from interface ConferenceBackend *-------------------------------------------------------------------------------- diff --git a/src/com/silverwrist/venice/core/impl/EngineBackend.java b/src/com/silverwrist/venice/core/impl/EngineBackend.java index d08ba55..37724f3 100644 --- a/src/com/silverwrist/venice/core/impl/EngineBackend.java +++ b/src/com/silverwrist/venice/core/impl/EngineBackend.java @@ -22,15 +22,18 @@ import java.util.List; import com.silverwrist.venice.security.AuditRecord; import com.silverwrist.venice.htmlcheck.HTMLChecker; import com.silverwrist.venice.core.DataException; +import com.silverwrist.venice.core.GlobalProperties; import com.silverwrist.venice.core.SideBoxDescriptor; public interface EngineBackend { + // HTML checker types public static final int HTMLC_POST_BODY = 0; public static final int HTMLC_POST_PSEUD = 1; public static final int HTMLC_PREVIEW_BODY = 2; public static final int HTMLC_ESCAPE_BODY_PSEUD = 3; + // Integer parameter indexes public static final int IP_POSTSPERPAGE = 0; public static final int IP_POSTSATTOP = 1; public static final int IP_MAXSEARCHRETURN = 2; @@ -41,6 +44,9 @@ public interface EngineBackend public static final int IP_CREATECOMMUNITYLVL = 7; public static final int IPC_NUM_PARAMS = 8; + // Boolean parameter indexes + public static final int BP_POSTPICTURES = 0; + public abstract SimpleEmailer createEmailer(); public abstract String getStockMessage(String key); @@ -83,6 +89,8 @@ public interface EngineBackend public abstract int getParamInt(int selector); + public abstract boolean getParamBoolean(int selector); + public abstract void forceParamReload() throws DataException; public abstract SideBoxDescriptor getMasterSideBoxDescriptor(int id); @@ -99,4 +107,8 @@ public interface EngineBackend public abstract boolean isNoCompressMimeType(String type); + public abstract GlobalProperties getProperties(); + + public abstract void setProperties(GlobalProperties props) throws DataException; + } // end interface EngineBackend diff --git a/src/com/silverwrist/venice/core/impl/UserContextImpl.java b/src/com/silverwrist/venice/core/impl/UserContextImpl.java index d33fd51..3225030 100644 --- a/src/com/silverwrist/venice/core/impl/UserContextImpl.java +++ b/src/com/silverwrist/venice/core/impl/UserContextImpl.java @@ -21,6 +21,7 @@ import java.util.*; import java.sql.*; import org.apache.log4j.*; import com.silverwrist.util.LocaleFactory; +import com.silverwrist.util.OptionSet; import com.silverwrist.util.StringUtil; import com.silverwrist.util.rcache.ReferencedData; import com.silverwrist.venice.*; @@ -38,6 +39,14 @@ class UserContextImpl implements UserContext, UserBackend *-------------------------------------------------------------------------------- */ + // Property set indexes + private static final int PROP_FLAGS = 0; // flags + + private static final BitSet ALL_PROPS; // BitSet representing all properties + + // Boolean flag indexes + private static final int BF_POSTPICTURES = 0; + private static Category logger = Category.getInstance(UserContextImpl.class); private static final String AUTH_TOKEN_PREFIX = "VQAT:"; @@ -67,6 +76,7 @@ class UserContextImpl implements UserContext, UserBackend private Locale my_locale = null; // my default locale (cached) private TimeZone my_tz = null; // my default timezone (cached) private HashMap mru_cache = new HashMap(); // MRU cache for ReferencedData objects + private OptionSet flags = null; // option flags /*-------------------------------------------------------------------------------- * Constructor @@ -147,22 +157,6 @@ class UserContextImpl implements UserContext, UserBackend } // end loadUserData - private void loadPrefs(Connection conn) throws SQLException, DataException - { - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT * FROM userprefs WHERE uid = " + uid + ";"); - - if (!(rs.next())) - throw new DataException("cannot find preferences for user"); - - if (my_tz==null) - my_tz = TimeZone.getTimeZone(rs.getString("tzid")); - - if (my_locale==null) - my_locale = LocaleFactory.createLocale(rs.getString("localeid")); - - } // end loadPrefs - private void loadPrefs() throws DataException { Connection conn = null; @@ -170,7 +164,34 @@ class UserContextImpl implements UserContext, UserBackend try { // call through to lower level function conn = datapool.getConnection(); - loadPrefs(conn); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT * FROM userprefs WHERE uid = " + uid + ";"); + + if (!(rs.next())) + throw new DataException("cannot find preferences for user"); + + if (my_tz==null) + my_tz = TimeZone.getTimeZone(rs.getString("tzid")); + + if (my_locale==null) + my_locale = LocaleFactory.createLocale(rs.getString("localeid")); + + // Load the user properties as well. + rs = stmt.executeQuery("SELECT ndx, data FROM propuser WHERE uid = " + uid + ";"); + while (rs.next()) + { // load the properties... + switch (rs.getInt(1)) + { // based on the property, do what is needed + case PROP_FLAGS: + flags = new OptionSet(rs.getString(2)); + break; + + default: + break; + + } // end switch + + } // end while } // end try catch (SQLException e) @@ -282,6 +303,65 @@ class UserContextImpl implements UserContext, UserBackend } // end autoJoinCommunities + private void updateProperties(BitSet delta) throws DataException + { + Connection conn = null; + try + { // get a connection and create a statement + conn = datapool.getConnection(); + Statement stmt = conn.createStatement(); + StringBuffer sql = new StringBuffer(); + + if (delta.get(PROP_FLAGS)) + { // store the flags + sql.append("UPDATE propuser SET data = '").append(flags.asString()).append("' WHERE uid = "); + sql.append(uid).append(" AND ndx = ").append(PROP_FLAGS).append(';'); + stmt.executeUpdate(sql.toString()); + sql.setLength(0); + + } // end if + + } // end try + catch (SQLException e) + { // database error - this is a DataException + logger.error("DB error storing community properties: " + e.getMessage(),e); + throw new DataException("unable to save community properties: " + e.getMessage(),e); + + } // end catch + finally + { // make sure the connection is released before we go + if (conn!=null) + datapool.releaseConnection(conn); + + } // end finally + + } // end updateProperties + + private void updateProperties() throws DataException + { + updateProperties(ALL_PROPS); + + } // end updateProperties + + private final UserProperties createProperties() + { + UserProperties rc = new UserProperties(); + rc.setDisplayPostPictures(flags.get(BF_POSTPICTURES)); + return rc; + + } // end createProperties + + private final BitSet storeProperties(UserProperties props) + { + BitSet rc = new BitSet(); + + if (flags.assign(BF_POSTPICTURES,props.getDisplayPostPictures())) + rc.set(PROP_FLAGS); + + return rc; + + } // end storeProperties + /*-------------------------------------------------------------------------------- * Implementations from interface UserContext *-------------------------------------------------------------------------------- @@ -1421,6 +1501,48 @@ class UserContextImpl implements UserContext, UserBackend } // end selectAd + public boolean displayPostPictures() throws DataException + { + if (flags==null) + loadPrefs(); + + return flags.get(BF_POSTPICTURES); + + } // end if + + public UserProperties getProperties() throws DataException + { + if (flags==null) + loadPrefs(); + return createProperties(); + + } // end getProperties + + public void setProperties(UserProperties props) throws DataException + { + if (flags==null) + loadPrefs(); + UserProperties orig = createProperties(); + BitSet delta = storeProperties(props); + if (delta.length()==0) + return; + + boolean succeeded = false; + try + { // update the properties in the database + updateProperties(delta); + succeeded = true; + + } // end try + finally + { // make sure the connection is released before we go + if (!succeeded) + storeProperties(orig); + + } // end finally + + } // end setProperties + /*-------------------------------------------------------------------------------- * Implementations from interface UserBackend *-------------------------------------------------------------------------------- @@ -1578,4 +1700,17 @@ class UserContextImpl implements UserContext, UserBackend } // end autoJoinCommunities + /*-------------------------------------------------------------------------------- + * Static initializer + *-------------------------------------------------------------------------------- + */ + + static + { // initialize the "all properties" bit set + BitSet tmp = new BitSet(); + tmp.set(PROP_FLAGS); + ALL_PROPS = tmp; + + } // end static initializer + } // end class UserContextImpl diff --git a/src/com/silverwrist/venice/core/impl/VeniceEngineImpl.java b/src/com/silverwrist/venice/core/impl/VeniceEngineImpl.java index 1eafdf2..6c639c6 100644 --- a/src/com/silverwrist/venice/core/impl/VeniceEngineImpl.java +++ b/src/com/silverwrist/venice/core/impl/VeniceEngineImpl.java @@ -22,6 +22,7 @@ import java.sql.*; import java.util.*; import org.apache.log4j.*; import org.w3c.dom.*; +import com.silverwrist.util.OptionSet; import com.silverwrist.util.StringUtil; import com.silverwrist.util.DOMElementHelper; import com.silverwrist.util.rcache.*; @@ -472,6 +473,14 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend *-------------------------------------------------------------------------------- */ + // Property indices + private static final int PROP_FLAGS = 0; // flags + + private static final int _PPROP_IP_BASE = 256; // base for "pseudo property" indexes + + private static final BitSet IP_PROPS; // BitSet representing the "integer parameter" properties + private static final BitSet ALL_PROPS; // BitSet representing all properties + private static Category logger = Category.getInstance(VeniceEngineImpl.class); private static final String AUTH_ALPHABET = @@ -506,6 +515,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend private boolean cache_fp_posts_busy = false; // busy flag for above vector private HashSet no_compress_types = new HashSet(); // the file types that can't be compressed private HashMap password_changes = new HashMap(); // current password change requests + private OptionSet global_flags = new OptionSet(); // global option flags /*-------------------------------------------------------------------------------- * Constructor @@ -534,10 +544,27 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend private void loadDefaults(Statement stmt) throws SQLException, DataException { - final String query = + final String query1 = "SELECT ndx, data FROM propglobal;"; + ResultSet rs = stmt.executeQuery(query1); + while (rs.next()) + { // load the property values based on indexes + switch (rs.getInt(1)) + { + case PROP_FLAGS: + global_flags.assign(rs.getString(2)); + break; + + default: + break; // don't understand property index - ignored + + } // end switch + + } // end while + + final String query2 = "SELECT posts_per_page, old_posts_at_top, max_search_page, max_sig_mbr_page, max_conf_mbr_page, " + "fp_posts, num_audit_page, sig_create_lvl FROM globals;"; - ResultSet rs = stmt.executeQuery(query); + rs = stmt.executeQuery(query2); if (!(rs.next())) throw new DataException("Globals table does not appear to be loaded!"); @@ -553,6 +580,155 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end loadDefaults + private synchronized void updateDefaults(BitSet delta) throws DataException + { + Connection conn = null; + try + { // get a database connection + conn = datapool.getConnection(); + Statement stmt = conn.createStatement(); + StringBuffer sql = new StringBuffer(); + + if (delta.get(PROP_FLAGS)) + { // update the global flags + sql.append("UPDATE propglobal SET data = '").append(global_flags.asString()).append("' WHERE ndx = "); + sql.append(PROP_FLAGS).append(";"); + stmt.executeUpdate(sql.toString()); + sql.setLength(0); + + } // end if + + BitSet tmp = (BitSet)(delta.clone()); + tmp.and(IP_PROPS); + if (tmp.length()>0) + { // need to update the globals table + sql.append("UPDATE globals SET"); + if (delta.get(_PPROP_IP_BASE + IP_POSTSPERPAGE)) + sql.append(" posts_per_page = ").append(gp_ints[IP_POSTSPERPAGE]).append(','); + if (delta.get(_PPROP_IP_BASE + IP_POSTSATTOP)) + sql.append(" old_posts_at_top = ").append(gp_ints[IP_POSTSATTOP]).append(','); + if (delta.get(_PPROP_IP_BASE + IP_MAXSEARCHRETURN)) + sql.append(" max_search_page = ").append(gp_ints[IP_MAXSEARCHRETURN]).append(','); + if (delta.get(_PPROP_IP_BASE + IP_MAXCOMMUNITYMEMBERDISPLAY)) + sql.append(" max_sig_mbr_page = ").append(gp_ints[IP_MAXCOMMUNITYMEMBERDISPLAY]).append(','); + if (delta.get(_PPROP_IP_BASE + IP_MAXCONFMEMBERDISPLAY)) + sql.append(" max_conf_mbr_page = ").append(gp_ints[IP_MAXCONFMEMBERDISPLAY]).append(','); + if (delta.get(_PPROP_IP_BASE + IP_NUMFRONTPAGEPOSTS)) + sql.append(" fp_posts = ").append(gp_ints[IP_NUMFRONTPAGEPOSTS]).append(','); + if (delta.get(_PPROP_IP_BASE + IP_NUMAUDITRECSPERPAGE)) + sql.append(" num_audit_page = ").append(gp_ints[IP_NUMAUDITRECSPERPAGE]).append(','); + if (delta.get(_PPROP_IP_BASE + IP_CREATECOMMUNITYLVL)) + sql.append(" sig_create_lvl = ").append(gp_ints[IP_CREATECOMMUNITYLVL]).append(','); + sql.setLength(sql.length()-1); // trim off the last comma + sql.append(';'); + stmt.executeUpdate(sql.toString()); + sql.setLength(0); + + } // end if + + } // end try + catch (SQLException e) + { // convert exceptions to DataException + logger.fatal("Database error storing defaults: " + e.getMessage(),e); + throw new DataException("error saving new defaults: " + e.getMessage(),e); + + } // end catch + finally + { // make sure we release the connection before we go + if (conn!=null) + datapool.releaseConnection(conn); + + } // end finally + + } // end updateDefaults + + private synchronized void updateDefaults() throws DataException + { + updateDefaults(ALL_PROPS); + + } // end updateDefaults + + private final GlobalProperties createProperties() + { + GlobalProperties rc = new GlobalProperties(); + rc.setPostsPerPage(gp_ints[IP_POSTSPERPAGE]); + rc.setOldPostsAtTop(gp_ints[IP_POSTSATTOP]); + rc.setSearchItemsPerPage(gp_ints[IP_MAXSEARCHRETURN]); + rc.setCommunityMembersPerPage(gp_ints[IP_MAXCOMMUNITYMEMBERDISPLAY]); + rc.setConferenceMembersPerPage(gp_ints[IP_MAXCONFMEMBERDISPLAY]); + rc.setPostsOnFrontPage(gp_ints[IP_NUMFRONTPAGEPOSTS]); + rc.setAuditRecordsPerPage(gp_ints[IP_NUMAUDITRECSPERPAGE]); + rc.setCommunityCreateLevel(gp_ints[IP_CREATECOMMUNITYLVL]); + rc.setDisplayPostPictures(global_flags.get(BP_POSTPICTURES)); + return rc; + + } // end createProperties + + private final BitSet storeProperties(GlobalProperties props) + { + BitSet rc = new BitSet(); + if (global_flags.assign(BP_POSTPICTURES,props.getDisplayPostPictures())) + rc.set(PROP_FLAGS); + if (gp_ints[IP_POSTSPERPAGE]!=props.getPostsPerPage()) + { // record variable change + gp_ints[IP_POSTSPERPAGE] = props.getPostsPerPage(); + rc.set(_PPROP_IP_BASE + IP_POSTSPERPAGE); + + } // end if + + if (gp_ints[IP_POSTSATTOP]!=props.getOldPostsAtTop()) + { // record variable change + gp_ints[IP_POSTSATTOP] = props.getOldPostsAtTop(); + rc.set(_PPROP_IP_BASE + IP_POSTSATTOP); + + } // end if + + if (gp_ints[IP_MAXSEARCHRETURN]!=props.getSearchItemsPerPage()) + { // record variable change + gp_ints[IP_MAXSEARCHRETURN] = props.getSearchItemsPerPage(); + rc.set(_PPROP_IP_BASE + IP_MAXSEARCHRETURN); + + } // end if + + if (gp_ints[IP_MAXCOMMUNITYMEMBERDISPLAY]!=props.getCommunityMembersPerPage()) + { // record variable change + gp_ints[IP_MAXCOMMUNITYMEMBERDISPLAY] = props.getCommunityMembersPerPage(); + rc.set(_PPROP_IP_BASE + IP_MAXCOMMUNITYMEMBERDISPLAY); + + } // end if + + if (gp_ints[IP_MAXCONFMEMBERDISPLAY]!=props.getConferenceMembersPerPage()) + { // record variable change + gp_ints[IP_MAXCONFMEMBERDISPLAY] = props.getConferenceMembersPerPage(); + rc.set(_PPROP_IP_BASE + IP_MAXCONFMEMBERDISPLAY); + + } // end if + + if (gp_ints[IP_NUMFRONTPAGEPOSTS]!=props.getPostsOnFrontPage()) + { // record variable change + gp_ints[IP_NUMFRONTPAGEPOSTS] = props.getPostsOnFrontPage(); + rc.set(_PPROP_IP_BASE + IP_NUMFRONTPAGEPOSTS); + + } // end if + + if (gp_ints[IP_NUMAUDITRECSPERPAGE]!=props.getAuditRecordsPerPage()) + { // record variable change + gp_ints[IP_NUMAUDITRECSPERPAGE] = props.getAuditRecordsPerPage(); + rc.set(_PPROP_IP_BASE + IP_NUMAUDITRECSPERPAGE); + + } // end if + + if (gp_ints[IP_CREATECOMMUNITYLVL]!=props.getCommunityCreateLevel()) + { // record variable change + gp_ints[IP_CREATECOMMUNITYLVL] = props.getCommunityCreateLevel(); + rc.set(_PPROP_IP_BASE + IP_CREATECOMMUNITYLVL); + + } // end if + + return rc; + + } // end storeProperties + /*-------------------------------------------------------------------------------- * Implementations from interface VeniceEngine *-------------------------------------------------------------------------------- @@ -1252,8 +1428,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend { // look to see if the user name is already present conn = datapool.getConnection(); Statement stmt = conn.createStatement(); - stmt.executeUpdate("LOCK TABLES users WRITE, userprefs WRITE, sigmember WRITE, sideboxes WRITE, " - + "confhotlist WRITE;"); + stmt.executeUpdate("LOCK TABLES users WRITE, userprefs WRITE, propuser WRITE, sigmember WRITE, " + + "sideboxes WRITE, confhotlist WRITE;"); try { // make sure the user name isn't there already ResultSet rs = stmt.executeQuery("SELECT uid FROM users WHERE username = '" + encode_username + "';"); @@ -1296,6 +1472,31 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend if (logger.isDebugEnabled()) logger.debug("...created userprefs"); + // add a properties configuration for this user + rs = stmt.executeQuery("SELECT propuser.ndx, propuser.data FROM propuser, users WHERE " + + "propuser.uid = users.uid AND users.is_anon = 1;"); + sql.setLength(0); + while (rs.next()) + { // set up to insert into the propuser table + if (sql.length()==0) + sql.append("INSERT INTO propuser (uid, ndx, data) VALUES "); + else + sql.append(", "); + sql.append("(").append(new_uid).append(", ").append(rs.getInt(1)).append(", '"); + sql.append(SQLUtil.encodeString(rs.getString(2))).append("')"); + + } // end while + + if (sql.length()>0) + { // execute the big update + sql.append(';'); + stmt.executeUpdate(sql.toString()); + + } // end if + + if (logger.isDebugEnabled()) + logger.debug("...created user properties"); + // get the sidebox configuration for this user rs = stmt.executeQuery("SELECT sideboxes.boxid, sideboxes.sequence FROM sideboxes, " + "users WHERE sideboxes.uid = users.uid AND users.is_anon = 1;"); @@ -2164,6 +2365,12 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end getParamInt + public boolean getParamBoolean(int selector) + { + return global_flags.get(selector); + + } // end getParamBoolean + public void forceParamReload() throws DataException { Connection conn = null; // data pooled connection @@ -2275,4 +2482,59 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end isNoCompressMimeType + public GlobalProperties getProperties() + { + return createProperties(); + + } // end getProperties + + public void setProperties(GlobalProperties props) throws DataException + { + GlobalProperties orig = createProperties(); + BitSet delta = storeProperties(props); + if (delta.length()==0) + return; + + boolean succeeded = false; + try + { // write the changes out to the database + updateDefaults(delta); + succeeded = true; + + } // end try + finally + { // restore old properties on failure + if (!succeeded) + storeProperties(orig); + + } // end finally + + } // end setProperties + + /*-------------------------------------------------------------------------------- + * Static initializer + *-------------------------------------------------------------------------------- + */ + + static + { // Initialize the "integer parameter properties" BitSet. + BitSet tmp = new BitSet(); + tmp.set(_PPROP_IP_BASE + IP_POSTSPERPAGE); + tmp.set(_PPROP_IP_BASE + IP_POSTSATTOP); + tmp.set(_PPROP_IP_BASE + IP_MAXSEARCHRETURN); + tmp.set(_PPROP_IP_BASE + IP_MAXCOMMUNITYMEMBERDISPLAY); + tmp.set(_PPROP_IP_BASE + IP_MAXCONFMEMBERDISPLAY); + tmp.set(_PPROP_IP_BASE + IP_NUMFRONTPAGEPOSTS); + tmp.set(_PPROP_IP_BASE + IP_NUMAUDITRECSPERPAGE); + tmp.set(_PPROP_IP_BASE + IP_CREATECOMMUNITYLVL); + IP_PROPS = tmp; + + // Initialize the "all properties" BitSet. + tmp = new BitSet(); + tmp.set(PROP_FLAGS); + tmp.or(IP_PROPS); + ALL_PROPS = tmp; + + } // end static initializer + } // end class VeniceEngineImpl diff --git a/src/com/silverwrist/venice/security/Role.java b/src/com/silverwrist/venice/security/Role.java index 4630f7b..de5447d 100644 --- a/src/com/silverwrist/venice/security/Role.java +++ b/src/com/silverwrist/venice/security/Role.java @@ -52,6 +52,7 @@ public class Role implements Comparable, SecLevels private static List confhidelist_rc = null; private static List confdeletelist_rc = null; private static List conf_member_levels = null; + private static List new_comm_list_rc = null; /*-------------------------------------------------------------------------------- * Attributes @@ -153,6 +154,7 @@ public class Role implements Comparable, SecLevels rc.add(unrestricted_user); rc.addAll(global_high); rc.remove(rc.size()-1); + rc.trimToSize(); base_levels = Collections.unmodifiableList(rc); } // end if @@ -168,6 +170,7 @@ public class Role implements Comparable, SecLevels ArrayList rc = new ArrayList(); rc.addAll(global_low); rc.add(unrestricted_user); + rc.trimToSize(); base_levels_2 = Collections.unmodifiableList(rc); } // end if @@ -192,6 +195,7 @@ public class Role implements Comparable, SecLevels rc.add(unrestricted_user); rc.addAll(comm_high); rc.add(global_high.get(0)); + rc.trimToSize(); commreadlist_rc = Collections.unmodifiableList(rc); } // end if @@ -207,6 +211,7 @@ public class Role implements Comparable, SecLevels ArrayList rc = new ArrayList(); rc.addAll(comm_high); rc.addAll(global_high); + rc.trimToSize(); commwritelist_rc = Collections.unmodifiableList(rc); } // end if @@ -225,6 +230,7 @@ public class Role implements Comparable, SecLevels rc.add(unrestricted_user); rc.addAll(comm_high); rc.add(global_high.get(0)); + rc.trimToSize(); commcreatelist_rc = Collections.unmodifiableList(rc); } // end if @@ -241,6 +247,7 @@ public class Role implements Comparable, SecLevels rc.addAll(comm_high); rc.addAll(global_high); rc.add(no_access); + rc.trimToSize(); commdeletelist_rc = Collections.unmodifiableList(rc); } // end if @@ -268,6 +275,7 @@ public class Role implements Comparable, SecLevels rc.add(unrestricted_user); rc.addAll(comm_high); rc.remove(rc.size()-1); + rc.trimToSize(); comm_member_levels = Collections.unmodifiableList(rc); } // end if @@ -291,6 +299,7 @@ public class Role implements Comparable, SecLevels rc.addAll(comm_low); rc.addAll(conf_low); rc.add(unrestricted_user); + rc.trimToSize(); confreadlist_rc = Collections.unmodifiableList(rc); } // end if @@ -309,6 +318,7 @@ public class Role implements Comparable, SecLevels rc.addAll(conf_low); rc.add(unrestricted_user); rc.addAll(conf_high); + rc.trimToSize(); confpostlist_rc = Collections.unmodifiableList(rc); } // end if @@ -331,6 +341,7 @@ public class Role implements Comparable, SecLevels rc.addAll(conf_high); rc.addAll(comm_high); rc.add(global_high.get(0)); + rc.trimToSize(); confhidelist_rc = Collections.unmodifiableList(rc); } // end if @@ -359,6 +370,7 @@ public class Role implements Comparable, SecLevels rc.addAll(comm_high); rc.addAll(global_high); rc.add(no_access); + rc.trimToSize(); confdeletelist_rc = Collections.unmodifiableList(rc); } // end if @@ -378,6 +390,7 @@ public class Role implements Comparable, SecLevels rc.addAll(conf_low); rc.add(unrestricted_user); rc.add(conf_high.get(conf_high.size()-1)); + rc.trimToSize(); conf_member_levels = Collections.unmodifiableList(rc); } // end if @@ -386,13 +399,30 @@ public class Role implements Comparable, SecLevels } // end getConferenceMemberLevelChoices + public static List getNewCommunityLevelChoices() + { + if (new_comm_list_rc==null) + { // precalculate the list + ArrayList rc = new ArrayList(); + rc.add(global_low.get(global_low.size()-1)); + rc.add(unrestricted_user); + rc.addAll(global_high); + rc.trimToSize(); + new_comm_list_rc = Collections.unmodifiableList(rc); + + } // end if + + return new_comm_list_rc; + + } // end getNewCommunityLevelChoices + /*-------------------------------------------------------------------------------- * Static initializer *-------------------------------------------------------------------------------- */ static - { + { // begin initializing the "all roles" map all_roles = new HashMap(); not_in_list = new Role(0,"(not in list)"); all_roles.put(new Integer(0),not_in_list); diff --git a/src/com/silverwrist/venice/servlets/ConfDisplay.java b/src/com/silverwrist/venice/servlets/ConfDisplay.java index 4a107b9..a9f8d8f 100644 --- a/src/com/silverwrist/venice/servlets/ConfDisplay.java +++ b/src/com/silverwrist/venice/servlets/ConfDisplay.java @@ -369,8 +369,8 @@ public class ConfDisplay extends VeniceServlet // Create the post display. try { // create the display - return new TopicPosts(request,engine,comm,conf,topic,piv.getFirst(),piv.getLast(),read_new,show_adv, - no_bozos); + return new TopicPosts(request,engine,user,comm,conf,topic,piv.getFirst(),piv.getLast(),read_new, + show_adv,no_bozos); } // end try catch (DataException de) @@ -430,7 +430,8 @@ public class ConfDisplay extends VeniceServlet PostInterval piv = getInterval(engine,request,topic,on_error); // create the topic posts view - return new TopicPosts(request,engine,comm,conf,topic,piv.getFirst(),piv.getLast(),true,false,false); + return new TopicPosts(request,engine,user,comm,conf,topic,piv.getFirst(),piv.getLast(),true, + false,false); } // end try catch (DataException de) diff --git a/src/com/silverwrist/venice/servlets/SystemAdmin.java b/src/com/silverwrist/venice/servlets/SystemAdmin.java index 235edfa..71fa9fb 100644 --- a/src/com/silverwrist/venice/servlets/SystemAdmin.java +++ b/src/com/silverwrist/venice/servlets/SystemAdmin.java @@ -75,6 +75,23 @@ public class SystemAdmin extends VeniceServlet } // end makeAdminModifyUserDialog + private EditGlobalPropertiesDialog makeGlobalPropertiesDialog() throws ServletException + { + final String desired_name = "EditGlobalPropertiesDialog"; + DialogCache cache = DialogCache.getDialogCache(getServletContext()); + + if (!(cache.isCached(desired_name))) + { // create a template and save it off + EditGlobalPropertiesDialog template = new EditGlobalPropertiesDialog(); + cache.saveTemplate(template); + + } // end if + + // return a new copy + return (EditGlobalPropertiesDialog)(cache.getNewDialog(desired_name)); + + } // end makeGlobalPropertiesDialog + /*-------------------------------------------------------------------------------- * Overrides from class HttpServlet *-------------------------------------------------------------------------------- @@ -193,6 +210,25 @@ public class SystemAdmin extends VeniceServlet } // end if ("UM" command) + if (cmd.equals("G")) + { // "G" = Edit Global Properties + try + { // get the global properties + AdminOperations adm = user.getAdminInterface(); + EditGlobalPropertiesDialog dlg = makeGlobalPropertiesDialog(); + dlg.setupDialog(adm); + setMyLocation(request,"sysadmin?cmd=G"); + return dlg; + + } // end try + catch (AccessError ae) + { // an access error generally means we're not an administrator + return new ErrorBox("Access Error","You do not have permission to administer the system.",null); + + } // end catch + + } // end if + // TODO: other command handling if (!(user.hasAdminAccess())) @@ -274,7 +310,7 @@ public class SystemAdmin extends VeniceServlet } // end if else { // the button must be wrong! - logger.error("no known button click on Account.doPost, cmd=P"); + logger.error("no known button click on SystemAdmin.doPost, cmd=UF"); return new ErrorBox("Internal Error","Unknown command button pressed","sysadmin?cmd=UF"); } // end else @@ -299,6 +335,57 @@ public class SystemAdmin extends VeniceServlet } // end if ("UM" command) + if (cmd.equals("G")) + { // "G" - Edit Global Properties + try + { // get the dialog box + EditGlobalPropertiesDialog dlg = makeGlobalPropertiesDialog(); + + if (dlg.isButtonClicked(request,"cancel")) + throw new RedirectResult("sysadmin"); // we decided not to bother - go back + + if (dlg.isButtonClicked(request,"update")) + { // update the system properties + AdminOperations adm = user.getAdminInterface(); + dlg.loadValues(request); + + try + { // execute the dialog! + dlg.doDialog(adm); + throw new RedirectResult("sysadmin"); + + } // end try + catch (ValidationException ve) + { // validation error - retry the dialog + dlg.setErrorMessage(ve.getMessage() + " Please try again."); + setMyLocation(request,"sysadmin?cmd=G"); + return dlg; + + } // end catch + + } // end if + else + { // the button must be wrong! + logger.error("no known button click on SystemAdmin.doPost, cmd=G"); + return new ErrorBox("Internal Error","Unknown command button pressed","sysadmin?cmd=UF"); + + } // end else + + } // end try + catch (AccessError ae) + { // an access error generally means we're not an administrator + return new ErrorBox("Access Error","You do not have permission to administer the system.",null); + + } // end catch + catch (DataException de) + { // error pulling the audit records + return new ErrorBox("Database Error","Unable to update global properties: " + de.getMessage(), + "sysadmin"); + + } // end catch + + } // end if ("G" command) + // TODO: other command handling if (!(user.hasAdminAccess())) diff --git a/src/com/silverwrist/venice/servlets/format/CDBaseFormField.java b/src/com/silverwrist/venice/servlets/format/CDBaseFormField.java index 7e3e238..c51061f 100644 --- a/src/com/silverwrist/venice/servlets/format/CDBaseFormField.java +++ b/src/com/silverwrist/venice/servlets/format/CDBaseFormField.java @@ -7,7 +7,7 @@ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * - * The Original Code is the Venice Web Community System. + * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are @@ -24,6 +24,11 @@ import com.silverwrist.venice.ValidationException; public abstract class CDBaseFormField implements CDFormField, ColorSelectors { + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + private String name; private String caption; private String caption2; @@ -31,6 +36,11 @@ public abstract class CDBaseFormField implements CDFormField, ColorSelectors private String value = null; private boolean enabled; + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + protected CDBaseFormField(String name, String caption, String caption2, boolean required) { this.name = name; @@ -52,12 +62,10 @@ public abstract class CDBaseFormField implements CDFormField, ColorSelectors } // end constructor - protected abstract void renderActualField(Writer out, RenderData rdat) - throws IOException; - - protected void validateContents(String value) throws ValidationException - { // this is a do-nothing value - } // end validateContents + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ protected final String getCaption() { @@ -65,6 +73,28 @@ public abstract class CDBaseFormField implements CDFormField, ColorSelectors } // end getCaption + /*-------------------------------------------------------------------------------- + * Abstract functions which MUST be overriden + *-------------------------------------------------------------------------------- + */ + + protected abstract void renderActualField(Writer out, RenderData rdat) + throws IOException; + + /*-------------------------------------------------------------------------------- + * Overridable operations + *-------------------------------------------------------------------------------- + */ + + protected void validateContents(String value) throws ValidationException + { // this is a do-nothing value + } // end validateContents + + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentRender + *-------------------------------------------------------------------------------- + */ + public void renderHere(Writer out, RenderData rdat) throws IOException { out.write("\n\n"); @@ -81,6 +111,11 @@ public abstract class CDBaseFormFieldReverse implements CDFormField, ColorSelect } // end renderHere + /*-------------------------------------------------------------------------------- + * Implementations from interface CDFormField + *-------------------------------------------------------------------------------- + */ + public String getName() { return name; @@ -99,6 +134,18 @@ public abstract class CDBaseFormFieldReverse implements CDFormField, ColorSelect } // end setValue + public Object getObjValue() + { + return value; + + } // end getObjValue + + public void setObjValue(Object obj) + { + this.value = obj.toString(); + + } // end setObjValue + public boolean isRequired() { return required; diff --git a/src/com/silverwrist/venice/servlets/format/CDCheckBoxFormField.java b/src/com/silverwrist/venice/servlets/format/CDCheckBoxFormField.java index 310f8e6..d675168 100644 --- a/src/com/silverwrist/venice/servlets/format/CDCheckBoxFormField.java +++ b/src/com/silverwrist/venice/servlets/format/CDCheckBoxFormField.java @@ -7,7 +7,7 @@ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * - * The Original Code is the Venice Web Community System. + * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are @@ -24,8 +24,25 @@ import com.silverwrist.venice.ValidationException; public class CDCheckBoxFormField extends CDBaseFormFieldReverse { + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final String YES = "Y"; + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + private String on_value; + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + public CDCheckBoxFormField(String name, String caption, String caption2, String on_value) { super(name,caption,caption2,false); @@ -33,6 +50,13 @@ public class CDCheckBoxFormField extends CDBaseFormFieldReverse } // end constructor + public CDCheckBoxFormField(String name, String caption, String caption2) + { + super(name,caption,caption2,false); + this.on_value = YES; + + } // end constructor + protected CDCheckBoxFormField(CDCheckBoxFormField other) { super(other); @@ -40,6 +64,11 @@ public class CDCheckBoxFormField extends CDBaseFormFieldReverse } // end constructor + /*-------------------------------------------------------------------------------- + * Overrides from class CDBaseFormFieldReverse + *-------------------------------------------------------------------------------- + */ + protected void renderActualField(Writer out, RenderData rdat) throws IOException { out.write(", * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are @@ -25,10 +25,20 @@ import com.silverwrist.venice.ValidationException; public class CDFormCategoryHeader implements CDFormField, ColorSelectors { + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + private String caption; private String rtext; private boolean enabled; + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + public CDFormCategoryHeader(String caption) { this.caption = caption; @@ -53,6 +63,11 @@ public class CDFormCategoryHeader implements CDFormField, ColorSelectors } // end constructor + /*-------------------------------------------------------------------------------- + * Implementations from interface ComponentRender + *-------------------------------------------------------------------------------- + */ + public void renderHere(Writer out, RenderData rdat) throws IOException { out.write(", * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are @@ -27,6 +27,10 @@ public interface CDFormField extends ComponentRender public abstract void setValue(String value); + public abstract Object getObjValue(); + + public abstract void setObjValue(Object obj); + public abstract boolean isRequired(); public abstract void validate() throws ValidationException; diff --git a/src/com/silverwrist/venice/servlets/format/CDIntegerFormField.java b/src/com/silverwrist/venice/servlets/format/CDIntegerFormField.java new file mode 100644 index 0000000..5e54ad3 --- /dev/null +++ b/src/com/silverwrist/venice/servlets/format/CDIntegerFormField.java @@ -0,0 +1,142 @@ +/* + * 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 . + * + * 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 , + * 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 com.silverwrist.venice.ValidationException; + +public class CDIntegerFormField extends CDTextFormField +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final double LN10 = Math.log(10.0); + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private int min_value; + private int max_value; + + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + public CDIntegerFormField(String name, String caption, String caption2, int min, int max) + { + super(name,caption,caption2,true,numDigits(min,max),numDigits(min,max)); + this.min_value = min; + this.max_value = max; + + } // end constructor + + protected CDIntegerFormField(CDIntegerFormField other) + { + super(other); + this.min_value = other.min_value; + this.max_value = other.max_value; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private static int numDigits(int v) + { + if (v==0) + return 1; + else if (v>0) + return 1 + (int)(Math.floor(Math.log((double)v) / LN10)); + else + return 2 + (int)(Math.floor(Math.log((double)(-v)) / LN10)); + + } // end numDigits + + private static int numDigits(int min, int max) + { + return Math.max(Math.max(numDigits(min),numDigits(max)),2); + + } // end numDigits + + /*-------------------------------------------------------------------------------- + * Overrides from class CDTextFormField + *-------------------------------------------------------------------------------- + */ + + protected void renderActualField(Writer out, RenderData rdat) throws IOException + { + super.renderActualField(out,rdat); + out.write(" (" + min_value + " - " + max_value + ")"); + + } // end renderActualField + + protected void validateContents(String value) throws ValidationException + { + try + { // convert to an integer and check against range + int x = Integer.parseInt(value); + if ((min_value>Integer.MIN_VALUE) && (xmax_value)) + throw new ValidationException("The value of the '" + getCaption() + + "' field must be less than or equal to " + max_value + "."); + + } // end try + catch (NumberFormatException nfe) + { // integer conversion failed + throw new ValidationException("Invalid non-numeric character in the '" + getCaption() + "' field."); + + } // end catch + + } // end validateContents + + /*-------------------------------------------------------------------------------- + * Implementations from interface CDFormField + *-------------------------------------------------------------------------------- + */ + + public Object getObjValue() + { + try + { // build an Integer and return it + return new Integer(getValue()); + + } // end try + catch (NumberFormatException nfe) + { // shouldn't happen + return null; + + } // end catch + + } // end getObjValue + + public CDFormField duplicate() + { + return new CDIntegerFormField(this); + + } // end clone + +} // end class CDIntegerFormField diff --git a/src/com/silverwrist/venice/servlets/format/CDRoleListFormField.java b/src/com/silverwrist/venice/servlets/format/CDRoleListFormField.java index 9e4f0c8..bb18404 100644 --- a/src/com/silverwrist/venice/servlets/format/CDRoleListFormField.java +++ b/src/com/silverwrist/venice/servlets/format/CDRoleListFormField.java @@ -7,7 +7,7 @@ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * - * The Original Code is the Venice Web Community System. + * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are @@ -25,6 +25,11 @@ import com.silverwrist.venice.security.Role; public class CDRoleListFormField extends CDPickListFormField { + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + public CDRoleListFormField(String name, String caption, String caption2, boolean required, List role_list) { @@ -38,6 +43,11 @@ public class CDRoleListFormField extends CDPickListFormField } // end constructor + /*-------------------------------------------------------------------------------- + * Overrides from class CDPickListFormField + *-------------------------------------------------------------------------------- + */ + protected void renderChoice(Writer out, RenderData rdat, Object obj, String my_value) throws IOException { Role r = (Role)obj; @@ -48,6 +58,26 @@ public class CDRoleListFormField extends CDPickListFormField } // end renderChoice + /*-------------------------------------------------------------------------------- + * Implementations from class CDFormField + *-------------------------------------------------------------------------------- + */ + + public Object getObjValue() + { + try + { // return value as Integer, for now + return new Integer(super.getValue()); + + } // end try + catch (NumberFormatException nfe) + { + return null; + + } // end catch + + } // end getObjValue + public CDFormField duplicate() { return new CDRoleListFormField(this); @@ -55,3 +85,4 @@ public class CDRoleListFormField extends CDPickListFormField } // end clone } // end class CDRoleListFormField + diff --git a/src/com/silverwrist/venice/servlets/format/CDTextFormField.java b/src/com/silverwrist/venice/servlets/format/CDTextFormField.java index 55305c8..04dddcd 100644 --- a/src/com/silverwrist/venice/servlets/format/CDTextFormField.java +++ b/src/com/silverwrist/venice/servlets/format/CDTextFormField.java @@ -23,9 +23,19 @@ import com.silverwrist.venice.ValidationException; public class CDTextFormField extends CDBaseFormField { + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + private int size; private int maxlength; + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + public CDTextFormField(String name, String caption, String caption2, boolean required, int size, int maxlength) { @@ -43,6 +53,11 @@ public class CDTextFormField extends CDBaseFormField } // end constructor + /*-------------------------------------------------------------------------------- + * Overrides from class CDBaseFormField + *-------------------------------------------------------------------------------- + */ + protected void renderActualField(Writer out, RenderData rdat) throws IOException { out.write(". + * + * 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 , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.servlets.format; + +import java.io.*; +import java.util.*; +import com.silverwrist.util.StringUtil; +import com.silverwrist.venice.ValidationException; +import com.silverwrist.venice.security.Role; +import com.silverwrist.venice.core.*; + +public class EditGlobalPropertiesDialog extends ContentDialog +{ + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + public EditGlobalPropertiesDialog() + { + super("Edit Global Properties",null,"globpropform","sysadmin"); + setHiddenField("cmd","G"); + + addFormField(new CDFormCategoryHeader("System Properties")); + addFormField(new CDIntegerFormField("search_items","Number of search items to display per page", + null,5,100)); + addFormField(new CDIntegerFormField("fp_posts","Number of published posts to display on front page", + null,1,50)); + addFormField(new CDIntegerFormField("audit_recs","Number of audit records to display per page", + null,10,500)); + addFormField(new CDRoleListFormField("create_lvl","Security level required to create a new community", + null,true,Role.getNewCommunityLevelChoices())); + + addFormField(new CDFormCategoryHeader("Community Properties")); + addFormField(new CDIntegerFormField("comm_mbrs","Number of community members to display per page", + null,10,100)); + + addFormField(new CDFormCategoryHeader("Conferencing Properties")); + addFormField(new CDIntegerFormField("posts_page","Maximum number of posts to display per page", + null,5,100)); + addFormField(new CDIntegerFormField("old_posts","Number of \"old\" posts to display at top of page", + null,1,5)); + addFormField(new CDIntegerFormField("conf_mbrs","Number of conference members to display per page", + null,10,100)); + addFormField(new CDCheckBoxFormField("pic_in_post","Display user pictures next to posts in conferences", + "(by default; user can override)")); + + addCommandButton(new CDImageButton("update","bn_update.gif","Update",80,24)); + addCommandButton(new CDImageButton("cancel","bn_cancel.gif","Cancel",80,24)); + + } // end constructor + + protected EditGlobalPropertiesDialog(EditGlobalPropertiesDialog other) + { + super(other); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + public void setupDialog(AdminOperations adm) + { + GlobalProperties props = adm.getProperties(); + setFieldObjValue("search_items",new Integer(props.getSearchItemsPerPage())); + setFieldObjValue("fp_posts",new Integer(props.getPostsOnFrontPage())); + setFieldObjValue("audit_recs",new Integer(props.getAuditRecordsPerPage())); + setFieldObjValue("create_lvl",new Integer(props.getCommunityCreateLevel())); + setFieldObjValue("comm_mbrs",new Integer(props.getCommunityMembersPerPage())); + setFieldObjValue("posts_page",new Integer(props.getPostsPerPage())); + setFieldObjValue("old_posts",new Integer(props.getOldPostsAtTop())); + setFieldObjValue("conf_mbrs",new Integer(props.getConferenceMembersPerPage())); + setFieldObjValue("pic_in_post",new Boolean(props.getDisplayPostPictures())); + + } // end setupDialog + + public void doDialog(AdminOperations adm) throws ValidationException, DataException + { + validate(); // validate the dialog + + // Reset the global properties. + GlobalProperties props = adm.getProperties(); + Integer iv = (Integer)(getFieldObjValue("search_items")); + props.setSearchItemsPerPage(iv.intValue()); + iv = (Integer)(getFieldObjValue("fp_posts")); + props.setPostsOnFrontPage(iv.intValue()); + iv = (Integer)(getFieldObjValue("audit_recs")); + props.setAuditRecordsPerPage(iv.intValue()); + iv = (Integer)(getFieldObjValue("create_lvl")); + props.setCommunityCreateLevel(iv.intValue()); + iv = (Integer)(getFieldObjValue("comm_mbrs")); + props.setCommunityMembersPerPage(iv.intValue()); + iv = (Integer)(getFieldObjValue("posts_page")); + props.setPostsPerPage(iv.intValue()); + iv = (Integer)(getFieldObjValue("old_posts")); + props.setOldPostsAtTop(iv.intValue()); + iv = (Integer)(getFieldObjValue("conf_mbrs")); + props.setConferenceMembersPerPage(iv.intValue()); + Boolean bv = (Boolean)(getFieldObjValue("pic_in_post")); + props.setDisplayPostPictures(bv.booleanValue()); + adm.setProperties(props); + + } // end doDialog + + public Object clone() + { + return new EditGlobalPropertiesDialog(this); + + } // end clone + +} // end class EditGlobalPropertiesDialog diff --git a/src/com/silverwrist/venice/servlets/format/EditProfileDialog.java b/src/com/silverwrist/venice/servlets/format/EditProfileDialog.java index 60d2563..ed18ec9 100644 --- a/src/com/silverwrist/venice/servlets/format/EditProfileDialog.java +++ b/src/com/silverwrist/venice/servlets/format/EditProfileDialog.java @@ -81,6 +81,13 @@ public class EditProfileDialog extends ContentDialog } // end class CDUserPhotoControl + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final String YES = "Y"; + /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- @@ -113,7 +120,7 @@ public class EditProfileDialog extends ContentDialog addFormField(new CDTextFormField("company","Company",null,false,32,255)); addFormField(new CDTextFormField("addr1","Address",null,false,32,255)); addFormField(new CDTextFormField("addr2","Address","(line 2)",false,32,255)); - addFormField(new CDCheckBoxFormField("pvt_addr","Hide address in profile",null,"Y")); + addFormField(new CDCheckBoxFormField("pvt_addr","Hide address in profile",null,YES)); addFormField(new CDTextFormField("loc","City",null,true,32,64)); addFormField(new CDTextFormField("reg","State/Province",null,true,32,64)); addFormField(new CDTextFormField("pcode","Zip/Postal Code",null,true,32,64)); @@ -121,18 +128,20 @@ public class EditProfileDialog extends ContentDialog addFormField(new CDFormCategoryHeader("Phone Numbers")); addFormField(new CDTextFormField("phone","Telephone",null,false,32,32)); addFormField(new CDTextFormField("mobile","Mobile/cellphone",null,false,32,32)); - addFormField(new CDCheckBoxFormField("pvt_phone","Hide phone/mobile numbers in profile",null,"Y")); + addFormField(new CDCheckBoxFormField("pvt_phone","Hide phone/mobile numbers in profile",null,YES)); addFormField(new CDTextFormField("fax","Fax",null,false,32,32)); - addFormField(new CDCheckBoxFormField("pvt_fax","Hide fax number in profile",null,"Y")); + addFormField(new CDCheckBoxFormField("pvt_fax","Hide fax number in profile",null,YES)); addFormField(new CDFormCategoryHeader("Internet")); addFormField(new CDEmailAddressFormField("email","E-mail address",null,true,32,255)); - addFormField(new CDCheckBoxFormField("pvt_email","Hide e-mail address in profile",null,"Y")); + addFormField(new CDCheckBoxFormField("pvt_email","Hide e-mail address in profile",null,YES)); addFormField(new CDTextFormField("url","Home page","(URL)",false,32,255)); addFormField(new CDFormCategoryHeader("Personal")); addFormField(new CDTextFormField("descr","Personal description",null,false,32,255)); photo_control = new CDUserPhotoControl("photo","User Photo","userphoto"); addFormField(photo_control); addFormField(new CDFormCategoryHeader("User Preferences")); + addFormField(new CDCheckBoxFormField("pic_in_post","Display user photos next to conference posts", + "(where applicable)",YES)); addFormField(new CDLocaleListFormField("locale","Default locale","(for formatting dates/times)",true)); addFormField(new CDTimeZoneListFormField("tz","Default time zone",null,true)); addCommandButton(new CDImageButton("update","bn_update.gif","Update",80,24)); @@ -198,6 +207,7 @@ public class EditProfileDialog extends ContentDialog { setTarget(target); ContactInfo ci = uc.getContactInfo(); // get the main contact info + UserProperties props = uc.getProperties(); // get the properties setFieldValue("prefix",ci.getNamePrefix()); setFieldValue("first",ci.getGivenName()); @@ -210,7 +220,7 @@ public class EditProfileDialog extends ContentDialog setFieldValue("addr1",ci.getAddressLine1()); setFieldValue("addr2",ci.getAddressLine2()); if (ci.getPrivateAddress()) - setFieldValue("pvt_addr","Y"); + setFieldValue("pvt_addr",YES); setFieldValue("loc",ci.getLocality()); setFieldValue("reg",ci.getRegion()); setFieldValue("pcode",ci.getPostalCode()); @@ -218,17 +228,19 @@ public class EditProfileDialog extends ContentDialog setFieldValue("phone",ci.getPhone()); setFieldValue("mobile",ci.getMobile()); if (ci.getPrivatePhone()) - setFieldValue("pvt_phone","Y"); + setFieldValue("pvt_phone",YES); setFieldValue("fax",ci.getFax()); if (ci.getPrivateFax()) - setFieldValue("pvt_fax","Y"); + setFieldValue("pvt_fax",YES); setFieldValue("email",ci.getEmail()); if (ci.getPrivateEmail()) - setFieldValue("pvt_email","Y"); + setFieldValue("pvt_email",YES); setFieldValue("url",ci.getURL()); setFieldValue("descr",uc.getDescription()); setFieldValue("photo",ci.getPhotoURL()); photo_control.setLinkURL("userphoto?tgt=" + URLEncoder.encode(target)); + if (props.getDisplayPostPictures()) + setFieldValue("pic_in_post",YES); setFieldValue("locale",uc.getLocale().toString()); setFieldValue("tz",uc.getTimeZone().getID()); @@ -238,8 +250,8 @@ public class EditProfileDialog extends ContentDialog { validate(); // validate the dialog - final String yes = "Y"; // the "yes" string ContactInfo ci = uc.getContactInfo(); // get the main contact info + UserProperties props = uc.getProperties(); // Reset all the contact info fields. ci.setNamePrefix(getFieldValue("prefix")); @@ -254,23 +266,27 @@ public class EditProfileDialog extends ContentDialog ci.setCompany(getFieldValue("company")); ci.setAddressLine1(getFieldValue("addr1")); ci.setAddressLine2(getFieldValue("addr2")); - ci.setPrivateAddress(yes.equals(getFieldValue("pvt_addr"))); + ci.setPrivateAddress(YES.equals(getFieldValue("pvt_addr"))); ci.setLocality(getFieldValue("loc")); ci.setRegion(getFieldValue("reg")); ci.setPostalCode(getFieldValue("pcode")); ci.setCountry(getFieldValue("country")); ci.setPhone(getFieldValue("phone")); ci.setMobile(getFieldValue("mobile")); - ci.setPrivatePhone(yes.equals(getFieldValue("pvt_phone"))); + ci.setPrivatePhone(YES.equals(getFieldValue("pvt_phone"))); ci.setFax(getFieldValue("fax")); - ci.setPrivateFax(yes.equals(getFieldValue("pvt_fax"))); + ci.setPrivateFax(YES.equals(getFieldValue("pvt_fax"))); ci.setEmail(getFieldValue("email")); - ci.setPrivateEmail(yes.equals(getFieldValue("pvt_email"))); + ci.setPrivateEmail(YES.equals(getFieldValue("pvt_email"))); ci.setURL(getFieldValue("url")); // Store the completed contact info. boolean retval = uc.putContactInfo(ci); + // Save off the properties. + props.setDisplayPostPictures(YES.equals(getFieldValue("pic_in_post"))); + uc.setProperties(props); + // Save off the user's description and preferences. uc.setDescription(getFieldValue("descr")); uc.setLocale(LocaleFactory.createLocale(getFieldValue("locale"))); diff --git a/src/com/silverwrist/venice/servlets/format/SystemAdminTop.java b/src/com/silverwrist/venice/servlets/format/SystemAdminTop.java index ac0f577..b09fe3c 100644 --- a/src/com/silverwrist/venice/servlets/format/SystemAdminTop.java +++ b/src/com/silverwrist/venice/servlets/format/SystemAdminTop.java @@ -31,7 +31,7 @@ public class SystemAdminTop extends ContentMenuPanel public SystemAdminTop() { super("System Administration",null); - addChoice("Set Global Parameters","TODO"); + addChoice("Edit Global Properties","sysadmin?cmd=G"); addChoice("View/Edit Banned Users","TODO"); addChoice("User Account Management","sysadmin?cmd=UF"); addChoice("System Audit Logs","sysadmin?cmd=A"); diff --git a/src/com/silverwrist/venice/servlets/format/TopicPosts.java b/src/com/silverwrist/venice/servlets/format/TopicPosts.java index f484c06..5d2f9c6 100644 --- a/src/com/silverwrist/venice/servlets/format/TopicPosts.java +++ b/src/com/silverwrist/venice/servlets/format/TopicPosts.java @@ -17,6 +17,7 @@ */ package com.silverwrist.venice.servlets.format; +import java.awt.Dimension; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; @@ -56,13 +57,15 @@ public class TopicPosts implements JSPRender private String topic_qid; private String cache_locator = null; private HashSet bozo_uids = new HashSet(); + private Dimension photo_size = null; + private HashMap uid_photos = null; /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ - public TopicPosts(HttpServletRequest request, VeniceEngine engine, CommunityContext comm, + public TopicPosts(HttpServletRequest request, VeniceEngine engine, UserContext user, CommunityContext comm, ConferenceContext conf, TopicContext topic, int first, int last, boolean read_new, boolean show_advanced, boolean no_bozos) throws DataException, AccessError { @@ -93,16 +96,38 @@ public class TopicPosts implements JSPRender // build up the list of users IN THIS VIEW that are bozo-filtered HashSet saw_users = new HashSet(); + if (conf.displayPostPictures() && user.displayPostPictures()) + { // build up the mapping of UIDs to photo URLs + photo_size = engine.getUserPhotoSize(); + uid_photos = new HashMap(); + + } // end if + Iterator it = messages.iterator(); while (it.hasNext()) { // get the user IDs of all messages on this page TopicMessageContext msg = (TopicMessageContext)(it.next()); Integer the_uid = new Integer(msg.getCreatorUID()); + boolean get_photo; if (!(saw_users.contains(the_uid))) { // only check user IDs once per display operation saw_users.add(the_uid); + get_photo = true; if (topic.isBozo(the_uid.intValue())) + { // shall we get the user photo? bozo_uids.add(the_uid); + get_photo = no_bozos; + + } // end if + + if (conf.displayPostPictures() && user.displayPostPictures() && get_photo) + { // look up the user photo URL + UserProfile prof = user.getProfile(the_uid.intValue()); + String url = prof.getPhotoURL(); + if (url!=null) + uid_photos.put(the_uid,url); + + } // end else if } // end if @@ -470,4 +495,24 @@ public class TopicPosts implements JSPRender } // end showFilterButton + public String getUserPhotoTag(int uid, RenderData rdat) + { + if (photo_size==null) + return ""; // user photos not enabled + StringBuffer buf = new StringBuffer("\"\""); + return buf.toString(); + + } // end getUserPhotoTag + + public boolean displayPostPictures() + { + return (photo_size!=null); + + } // end displayPostPictures + } // end class TopicPosts diff --git a/web/format/posts.jsp b/web/format/posts.jsp index 21c7bb3..b76719b 100644 --- a/web/format/posts.jsp +++ b/web/format/posts.jsp @@ -166,6 +166,9 @@
<% } // end if (showing advanced controls) %> <%= rdat.getStdFontTag(ColorSelectors.CONTENT_FOREGROUND,2) %> + <% if (!(data.bozoFilterUser(msg.getCreatorUID()))) { %> + <%= data.getUserPhotoTag(msg.getCreatorUID(),rdat) %> + <% } // end if %> "><%= msg.getPostNumber() %> of <%= data.getTotalMessages() - 1 %> @@ -200,7 +203,8 @@ (Scribbled by <%= data.getMessageBodyText(msg) %> on <%= rdat.formatDateForDisplay(msg.getScribbleDate()) %>) -

+ + <% if (data.displayPostPictures()) { %>
<% } %>

<% } else if (data.bozoFilterUser(msg.getCreatorUID())) { %> ">(Hidden Message: <%= msg.getNumLines() %> <% if (msg.getNumLines()==1) { %>Line<% } else { %>Lines<% } %>) -

+ + <% if (data.displayPostPictures()) { %>
<% } %>

<% } else { %>

<%= rdat.rewritePostData(data.getMessageBodyText(msg)) %>
+ <% if (data.displayPostPictures()) { %>
<% } %> <% } // end if %> <% if (data.showAdvanced()) { %>