Index: openacs-4/packages/sloan-bboard/ChangeLog
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/ChangeLog,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/ChangeLog	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,116 @@
+2001-01-03  Anukul Kapoor  <akk@squishy>
+
+	* www/message.tcl, www/message-threaded.tcl: fixed problem where
+	"deleted" messages are displayed
+
+	* www/doc/index.html, www/doc/requirements.html: slight
+	documentation improvements
+
+	* bboard.info: changed version to 4.0.2rc
+
+	* sql/bboard-drop.sql: added support for dropping attachments and
+	email a friend droppings
+
+	* www/forum-view.adp: fixed a buggy link to "All messages"
+
+	* www/message-threaded.adp: added anchor support
+
+	* www/message-list.adp: support for showing the date in search
+	results
+
+	* www/search.adp, www/search.tcl: we know show the date on search
+	results
+
+	* www/message-new-3.tcl: add support for user editable permissions
+
+	* www/message-entry.adp: don't show attachments when replying
+
+	* www/message.adp, www/message.tcl, www/messages-by-user.tcl,
+	www/search.tcl: support for anchored reference to replies
+
+	* www/message-mail-2.tcl: fixed email a friend artifact messages
+	not to point with reply_to at parent message.  also updated to use
+	new return redirect target
+
+	* www/message-list.adp: support for last updated column
+
+	* www/master.adp: context_bar is no longer required
+
+	* www/forum-view.adp, www/forum.tcl: support for "last updated"
+	column on forum overview page as well as last_n_days of messages
+	being shown
+
+	* www/attachment-delete.tcl, www/attachment.tcl,
+	www/message-attach.tcl, www/simple-message.adp,
+	www/simple-message.tcl, www/message-attach-2.tcl,
+	www/message-attach.adp: added attachment support
+
+	* www/forum-by-category.tcl: formatting change
+
+	* tcl/bboard-procs.tcl: added attachment support and a work around
+	for an acs-messaging bug
+
+	* bboard.info: added parameters for: mailing a friend user posts
+	editable attachments enabled max attachment size display last N
+	days
+
+2000-12-04  Anukul Kapoor  <akk@arsdigita.com>
+
+	* bboard.info: updated file and version info
+
+	* sql/upgrade-4.0.1-4.0.2.sql: removed a redundant index creation
+
+2000-12-01  Anukul Kapoor  <akk@arsdigita.com>
+
+	* bboard.info: updated file and version info
+
+	* tcl/bboard-procs.tcl: Added bboard_n_spaces proc
+
+	* www/forum-delete.tcl:
+	* www/forum-delete.adp:
+	* www/forum-delete-2.tcl: Added UI for deleting a forum.
+
+	* www/index.tcl: Added querying for bboard_forum_delete permissions
+	* www/index.adp: Added links to deleting a forum
+
+2000-12-01  John Prevost  <jmp@arsdigita.com>
+
+	* www/message-delete-2.tcl: Fixed typo in contract
+
+        * sql/upgrade-4.0.1-4.0.2.sql:
+        * sql/bboard-create.sql: Added appropriate on delete cascade
+          clauses.
+
+        * www/category-delete.tcl:
+        * www/category-delete.adp:
+        * www/category-delete-2.tcl: Added UI for deleting a category.
+        
+        * www/forum-view.adp: Now expects categories rows to have a
+          delete_p column.  Provides a link to delete the category if it's
+          "t".
+        
+        * www/master.adp: Master template for bboard now calls out to the
+          default master (picking up appropriate colors and style from the
+          core-ui.)
+
+2000-11-30  John Prevost  <jmp@arsdigita.com>
+
+        * www/message-mail.tcl:
+        * www/message-mail.adp:
+        * www/message-mail-2.tcl: Preliminary UI for mailing a friend.
+        
+        * www/simple-message.tcl:
+        * www/simple-message.adp: Added "send to a friend" link.
+
+2000-11-27  Anukul Kapoor  <akk@arsdigita.com>
+
+        * Released 4.0.1
+
+        * sql/upgrade-4.0b-4.0.sql:
+        * sql/upgrade-4.0-4.0.1.sql: Added bboard_im_convert to the
+          upgrade script.  Incremented version number to be sure it gets
+          run.
+
+2000-11-27  Anukul Kapoor  <akk@arsdigita.com>
+
+        * Released 4.0 (initial production release)
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/bboard.info
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/Attic/bboard.info,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/bboard.info	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,193 @@
+<?xml version="1.0"?>
+<!-- Generated by the OpenACS Package Manager -->
+
+<package key="bboard" url="http://www.arsdigita.com/acs-repository/apm/packages/bboard/" type="apm_application">
+    <package-name>Bboard</package-name>
+    <pretty-plural>Bboard Forums</pretty-plural>
+    <initial-install-p>f</initial-install-p>
+    <singleton-p>f</singleton-p>
+
+    <version name="4.0.2b6" url="http://www.arsdigita.com/acs-repository/download/apm/bboard-4.0.2b6.apm">
+    <database-support>
+        <database>oracle</database>
+        <database>postgresql</database>
+    </database-support>
+        <owner url="mailto:bboard@arsdigita.com">Anukul Kapoor</owner>
+        <owner url="mailto:jmp@arsdigita.com">John Prevost</owner>
+        <summary>ACS 4 bboard package.</summary>
+        <release-date>2001-02-13</release-date>
+        <vendor url="http://www.arsdigita.com/">ArsDigita Corporation</vendor>
+        <description format="text/plain">This is the release candidate for bboard version 4.0.2.  This package provides customizable discussion forums for a community of users.</description>
+
+        <requires url="acs-kernel" version="4.0"/>
+        <requires url="acs-messaging" version="4.0.1"/>
+        <requires url="general-comments" version="4.0"/>
+
+        <files>
+            <file path="ChangeLog"/>
+            <file type="package_spec" path="bboard.info"/>
+            <file type="data_model_create" db_type="oracle" path="sql/oracle/bboard-create.sql"/>
+            <file type="data_model_drop" db_type="oracle" path="sql/oracle/bboard-drop.sql"/>
+            <file type="data_model" db_type="oracle" path="sql/oracle/bboard-packages.sql"/>
+            <file type="data_model" db_type="oracle" path="sql/oracle/bboard-views.sql"/>
+            <file type="data_model" db_type="oracle" path="sql/oracle/index_sync.sql"/>
+            <file type="data_model_upgrade" db_type="oracle" path="sql/oracle/upgrade-4.0-4.0.1.sql"/>
+            <file type="data_model_upgrade" db_type="oracle" path="sql/oracle/upgrade-4.0.1-4.0.2.sql"/>
+            <file type="data_model_upgrade" db_type="oracle" path="sql/oracle/upgrade-4.0.2b3-4.0.2b4.sql"/>
+            <file type="data_model_upgrade" db_type="oracle" path="sql/oracle/upgrade-4.0.2b5-4.0.2b6.sql"/>
+            <file type="data_model_upgrade" db_type="oracle" path="sql/oracle/upgrade-4.0.2b6-4.0.2b7.sql"/>
+            <file type="data_model_upgrade" db_type="oracle" path="sql/oracle/upgrade-4.0b-4.0.sql"/>
+            <file type="data_model_create" db_type="postgresql" path="sql/postgresql/bboard-create.sql"/>
+            <file type="data_model_drop" db_type="postgresql" path="sql/postgresql/bboard-drop.sql"/>
+            <file type="data_model" db_type="postgresql" path="sql/postgresql/bboard-packages.sql"/>
+            <file type="data_model" db_type="postgresql" path="sql/postgresql/bboard-views.sql"/>
+            <file type="tcl_init" path="tcl/bboard-init.tcl"/>
+            <file type="query_file" db_type="oracle" path="tcl/bboard-procs-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="tcl/bboard-procs-postgresql.xql"/>
+            <file type="tcl_procs" path="tcl/bboard-procs.tcl"/>
+            <file type="query_file" path="tcl/bboard-procs.xql"/>
+            <file type="content_page" path="www/attachment-delete.tcl"/>
+            <file type="content_page" path="www/attachment.tcl"/>
+            <file type="query_file" db_type="oracle" path="www/category-delete-2-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/category-delete-2-postgresql.xql"/>
+            <file type="content_page" path="www/category-delete-2.tcl"/>
+            <file type="query_file" path="www/category-delete-2.xql"/>
+            <file type="content_page" path="www/category-delete.adp"/>
+            <file type="content_page" path="www/category-delete.tcl"/>
+            <file type="query_file" path="www/category-delete.xql"/>
+            <file type="content_page" path="www/category-edit-2.tcl"/>
+            <file type="content_page" path="www/category-edit.tcl"/>
+            <file type="query_file" path="www/category-edit.xql"/>
+            <file type="content_page" path="www/category-entry.adp"/>
+            <file type="content_page" path="www/category-new-2.tcl"/>
+            <file type="content_page" path="www/category-new.tcl"/>
+            <file type="query_file" path="www/category-new.xql"/>
+            <file type="content_page" path="www/category-subscribe.tcl"/>
+            <file type="query_file" path="www/category-subscribe.xql"/>
+            <file type="content_page" path="www/category-unsubscribe.tcl"/>
+            <file type="documentation" path="www/doc/acs-messaging-and-bboard-dm.gif"/>
+            <file type="documentation" path="www/doc/design.html"/>
+            <file type="documentation" path="www/doc/index.html"/>
+            <file type="documentation" path="www/doc/requirements.html"/>
+            <file type="documentation" path="www/doc/xml/configuration.xml"/>
+            <file type="documentation" path="www/doc/xml/design.xml"/>
+            <file type="documentation" path="www/doc/xml/index.xml"/>
+            <file type="documentation" path="www/doc/xml/installation.xml"/>
+            <file type="documentation" path="www/doc/xml/intro.xml"/>
+            <file type="documentation" path="www/doc/xml/notes.xml"/>
+            <file type="documentation" path="www/doc/xml/requirements.xml"/>
+            <file type="documentation" path="www/doc/xml/support.xml"/>
+            <file type="documentation" path="www/doc/xml/top.xml"/>
+            <file type="query_file" db_type="oracle" path="www/forum-by-category-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/forum-by-category-postgresql.xql"/>
+            <file type="content_page" path="www/forum-by-category.tcl"/>
+            <file type="query_file" path="www/forum-by-category.xql"/>
+            <file type="query_file" db_type="oracle" path="www/forum-delete-2-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/forum-delete-2-postgresql.xql"/>
+            <file type="content_page" path="www/forum-delete-2.tcl"/>
+            <file type="query_file" path="www/forum-delete-2.xql"/>
+            <file type="content_page" path="www/forum-delete.adp"/>
+            <file type="content_page" path="www/forum-delete.tcl"/>
+            <file type="query_file" path="www/forum-delete.xql"/>
+            <file type="content_page" path="www/forum-edit-2.tcl"/>
+            <file type="content_page" path="www/forum-edit.tcl"/>
+            <file type="query_file" path="www/forum-edit.xql"/>
+            <file type="content_page" path="www/forum-entry.adp"/>
+            <file type="content_page" path="www/forum-move-2.tcl"/>
+            <file type="query_file" path="www/forum-move-2.xql"/>
+            <file type="content_page" path="www/forum-move.adp"/>
+            <file type="content_page" path="www/forum-move.tcl"/>
+            <file type="query_file" path="www/forum-move.xql"/>
+            <file type="content_page" path="www/forum-new-2.tcl"/>
+            <file type="content_page" path="www/forum-new.tcl"/>
+            <file type="query_file" db_type="oracle" path="www/forum-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/forum-postgresql.xql"/>
+            <file type="content_page" path="www/forum-subscribe.tcl"/>
+            <file type="content_page" path="www/forum-unsubscribe.tcl"/>
+            <file type="content_page" path="www/forum-view.adp"/>
+            <file type="content_page" path="www/forum.tcl"/>
+            <file type="query_file" path="www/forum.xql"/>
+            <file type="query_file" db_type="oracle" path="www/index-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/index-postgresql.xql"/>
+            <file type="content_page" path="www/index.adp"/>
+            <file type="content_page" path="www/index.tcl"/>
+            <file type="content_page" path="www/master.adp"/>
+            <file type="content_page" path="www/message-approve.tcl"/>
+            <file type="query_file" path="www/message-approve.xql"/>
+            <file type="content_page" path="www/message-attach-2.tcl"/>
+            <file type="content_page" path="www/message-attach.adp"/>
+            <file type="content_page" path="www/message-attach.tcl"/>
+            <file type="query_file" db_type="oracle" path="www/message-delete-2-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/message-delete-2-postgresql.xql"/>
+            <file type="content_page" path="www/message-delete-2.tcl"/>
+            <file type="content_page" path="www/message-delete.adp"/>
+            <file type="content_page" path="www/message-delete.tcl"/>
+            <file type="query_file" path="www/message-delete.xql"/>
+            <file type="content_page" path="www/message-edit-2.tcl"/>
+            <file type="query_file" path="www/message-edit-2.xql"/>
+            <file type="content_page" path="www/message-edit-3.tcl"/>
+            <file type="content_page" path="www/message-edit.tcl"/>
+            <file type="query_file" path="www/message-edit.xql"/>
+            <file type="content_page" path="www/message-entry.adp"/>
+            <file type="content_page" path="www/message-list.adp"/>
+            <file type="query_file" db_type="oracle" path="www/message-mail-2-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/message-mail-2-postgresql.xql"/>
+            <file type="content_page" path="www/message-mail-2.tcl"/>
+            <file type="query_file" path="www/message-mail-2.xql"/>
+            <file type="content_page" path="www/message-mail.adp"/>
+            <file type="content_page" path="www/message-mail.tcl"/>
+            <file type="query_file" path="www/message-mail.xql"/>
+            <file type="query_file" db_type="oracle" path="www/message-move-2-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/message-move-2-postgresql.xql"/>
+            <file type="content_page" path="www/message-move-2.tcl"/>
+            <file type="content_page" path="www/message-move.adp"/>
+            <file type="content_page" path="www/message-move.tcl"/>
+            <file type="query_file" path="www/message-move.xql"/>
+            <file type="content_page" path="www/message-new-2.tcl"/>
+            <file type="query_file" path="www/message-new-2.xql"/>
+            <file type="query_file" db_type="oracle" path="www/message-new-3-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/message-new-3-postgresql.xql"/>
+            <file type="content_page" path="www/message-new-3.tcl"/>
+            <file type="content_page" path="www/message-new.tcl"/>
+            <file type="query_file" path="www/message-new.xql"/>
+            <file type="query_file" db_type="oracle" path="www/message-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/message-postgresql.xql"/>
+            <file type="content_page" path="www/message-preview.adp"/>
+            <file type="content_page" path="www/message-reject.tcl"/>
+            <file type="content_page" path="www/message-subscribe.tcl"/>
+            <file type="query_file" db_type="oracle" path="www/message-threaded-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/message-threaded-postgresql.xql"/>
+            <file type="content_page" path="www/message-threaded.adp"/>
+            <file type="content_page" path="www/message-threaded.tcl"/>
+            <file type="query_file" path="www/message-threaded.xql"/>
+            <file type="content_page" path="www/message-unsubscribe.tcl"/>
+            <file type="content_page" path="www/message.adp"/>
+            <file type="content_page" path="www/message.tcl"/>
+            <file type="content_page" path="www/messages-by-user.adp"/>
+            <file type="content_page" path="www/messages-by-user.tcl"/>
+            <file type="query_file" path="www/messages-by-user.xql"/>
+            <file type="query_file" db_type="oracle" path="www/search-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/search-postgresql.xql"/>
+            <file type="content_page" path="www/search.adp"/>
+            <file type="content_page" path="www/search.tcl"/>
+            <file type="query_file" db_type="oracle" path="www/simple-message-oracle.xql"/>
+            <file type="query_file" db_type="postgresql" path="www/simple-message-postgresql.xql"/>
+            <file type="content_page" path="www/simple-message.adp"/>
+            <file type="content_page" path="www/simple-message.tcl"/>
+            <file type="content_page" path="www/spacer.gif"/>
+            <file type="content_page" path="www/subscriptions.adp"/>
+            <file type="content_page" path="www/subscriptions.tcl"/>
+            <file type="query_file" path="www/subscriptions.xql"/>
+            <file type="content_page" path="www/test.adp"/>
+        </files>
+        <parameters>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="ThreadingEnabledP"  default="f" description="t enables threaded display of messages."/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="MailFriendEnabledP"  default="t" description="Enables link that forwards message to another email address."/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="UserPostsEditableP"  default="t" description="Grants permission to edit posts to posting user.  Required for attachments to work."/>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="AttachmentsEnabledP"  default="t" description="This enables binary attachments.  You need to enable UserPostsEditableP for this to work."/>
+            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="MaxAttachmentSize"  default="1048576" description="The maximum size (in bytes) of an uploadable attachment."/>
+            <parameter datatype="number"  min_n_values="1"  max_n_values="1"  name="DisplayLastNDays"  default="0" description="How many prior days worth of messages to show by default.  0 means show all."/>
+        </parameters>
+
+    </version>
+</package>
Index: openacs-4/packages/sloan-bboard/sql/oracle/bboard-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/oracle/bboard-create.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/oracle/bboard-create.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,453 @@
+--
+-- packages/bboard/sql/bboard-create.sql
+--
+-- @author Anukul Kapoor <akk@arsdigita.com>
+-- @author John Prevost <jmp@arsdigita.com>
+-- @creation-date 2000-08-29
+-- @cvs-id $Id: bboard-create.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+set feedback off
+
+-- separate parts so that if one fails, the rest happens
+
+begin
+
+    -- create the privileges
+
+    acs_privilege.create_privilege('bboard_create_forum');
+    acs_privilege.create_privilege('bboard_create_category');
+    acs_privilege.create_privilege('bboard_create_message');
+    acs_privilege.create_privilege('bboard_write_forum');
+    acs_privilege.create_privilege('bboard_write_category');
+    acs_privilege.create_privilege('bboard_write_message');
+    acs_privilege.create_privilege('bboard_read_forum');
+    acs_privilege.create_privilege('bboard_read_category');
+    acs_privilege.create_privilege('bboard_read_message');
+    acs_privilege.create_privilege('bboard_delete_forum');
+    acs_privilege.create_privilege('bboard_delete_category');
+    acs_privilege.create_privilege('bboard_delete_message');
+    acs_privilege.create_privilege('bboard_moderate_forum');
+
+end;
+/
+show errors
+
+begin
+
+    -- bind privileges to global names
+
+    acs_privilege.add_child('create','bboard_create_forum');
+    acs_privilege.add_child('create','bboard_create_category');
+    acs_privilege.add_child('create','bboard_create_message');
+    acs_privilege.add_child('write','bboard_write_forum');
+    acs_privilege.add_child('write','bboard_write_category');
+    acs_privilege.add_child('write','bboard_write_message');
+    acs_privilege.add_child('read','bboard_read_forum');
+    acs_privilege.add_child('read','bboard_read_category');
+    acs_privilege.add_child('read','bboard_read_message');
+    acs_privilege.add_child('delete','bboard_delete_forum');
+    acs_privilege.add_child('delete','bboard_delete_category');
+    acs_privilege.add_child('delete','bboard_delete_message');
+    acs_privilege.add_child('admin','bboard_moderate_forum');
+end;
+/
+show errors
+
+
+declare
+    default_context acs_objects.object_id%TYPE;
+    registered_users acs_objects.object_id%TYPE;
+    the_public acs_objects.object_id%TYPE;
+begin
+
+    default_context := acs.magic_object_id('default_context');
+    registered_users := acs.magic_object_id('registered_users');
+    the_public := acs.magic_object_id('the_public');
+
+    -- give registered users the power to post by default
+
+    acs_permission.grant_permission (
+        object_id => default_context,
+        grantee_id => registered_users,
+        privilege => 'bboard_create_message'
+    );
+
+    -- give the public the power to read by default
+
+    acs_permission.grant_permission (
+        object_id => default_context,
+        grantee_id => the_public,
+        privilege => 'bboard_read_message'
+    );
+
+    acs_permission.grant_permission (
+        object_id => default_context,
+        grantee_id => the_public,
+        privilege => 'bboard_read_category'
+    );
+
+    acs_permission.grant_permission (
+        object_id => default_context,
+        grantee_id => the_public,
+        privilege => 'bboard_read_forum'
+    );
+
+    acs_object_type.create_type (
+        supertype => 'acs_object',
+        object_type => 'bboard_forum',
+        pretty_name => 'BBoard Forum',
+        pretty_plural => 'BBoard Forum',
+        table_name => 'BBOARD_FORUMS',
+        id_column => 'FORUM_ID',
+        name_method => 'BBOARD_FORUM.NAME'
+    );
+
+    acs_object_type.create_type (
+        supertype => 'acs_object',
+        object_type => 'bboard_category',
+        pretty_name => 'BBoard Category',
+        pretty_plural => 'BBoard Categories',
+        table_name => 'BBOARD_CATEGORIES',
+        id_column => 'CATEGORY_ID',
+        name_method => 'BBOARD_CATEGORY.NAME'
+    );
+
+end;
+/
+show errors
+
+
+-- bboard forums
+--
+-- these act as primary containers for messages
+-- a message's context_id will point to its forum
+
+create table bboard_forums (
+    forum_id integer
+        constraint bboard_forums_forum_id_fk
+            references acs_objects (object_id)
+        constraint bboard_forums_pk
+            primary key,    
+    short_name varchar(400)
+        constraint bboard_forums_short_name_nn
+            not null,
+    charter varchar(4000),
+    moderated_p char(1)
+        constraint bboard_forums_moderated_p_nn
+            not null
+        constraint bboard_forums_moderated_p_ck
+            check (moderated_p in ('t','f')),
+    bboard_id integer
+        constraint bboard_forums_bboard_id_nn
+            not null
+        constraint bboard_forums_bboard_id_fk
+            references apm_packages (package_id)
+                on delete cascade
+);
+
+create index bboard_forums_bboard_id_idx
+    on bboard_forums (bboard_id);
+
+create table bboard_forum_message_map (
+    forum_id integer
+        constraint bboard_fmm_forum_id_fk
+            references bboard_forums (forum_id)
+                on delete cascade,
+    message_id integer
+        constraint bboard_fmm_message_id_fk
+            references acs_messages (message_id)
+                on delete cascade,
+    status varchar(20)
+        constraint bboard_fmm_status_ck
+            check (status in ('unmoderated', 'approved', 'rejected'))
+        constraint bboard_fmm_status_nn
+            not null,
+    constraint bboard_forum_message_map_pk
+        primary key (forum_id, message_id)
+);
+
+create index bboard_fmm_message_id_idx
+    on bboard_forum_message_map (message_id);
+
+create index bboard_fmm_status_idx
+    on bboard_forum_message_map (status);
+
+-- bboard categories
+--
+-- these are for intra-forum categorization
+-- categories will be scoped to forums via their acs_object.context_id
+
+create table bboard_categories (
+    category_id integer
+        constraint bboard_c_category_id_fk
+            references acs_objects (object_id)
+        constraint bboard_c_category_id_pk
+            primary key,
+    short_name varchar(400)
+        constraint bboard_c_short_name_nn
+            not null,
+    forum_id integer
+        constraint bboard_c_forum_id_fk
+            references bboard_forums (forum_id)
+                on delete cascade
+        constraint bboard_c_forum_id_nn
+            not null,
+    description varchar(4000)
+);
+
+create index bboard_categories_forum_id_idx
+    on bboard_categories (forum_id);
+
+create table bboard_category_message_map (
+    category_id integer
+        constraint bboard_cmm_category_id_fk
+            references bboard_categories (category_id)
+                on delete cascade,
+    message_id integer
+        constraint bboard_cmm_message_id_fk
+            references acs_messages (message_id)
+                on delete cascade,
+    constraint bboard_category_message_map_pk
+        primary key (category_id, message_id)
+);
+
+create index bboard_cmm_message_id_idx
+    on bboard_category_message_map (message_id);
+
+@@ bboard-views
+
+-- Tables to track subscriptions
+
+create table bboard_forum_subscribers (
+    forum_id integer
+        constraint bboard_fs_forum_id_fk
+            references bboard_forums (forum_id)
+                on delete cascade,
+    subscriber_id integer
+        constraint bboard_fs_subscriber_id_fk
+            references parties (party_id)
+                on delete cascade,
+    constraint bboard_forum_subscribers_pk
+        primary key (forum_id, subscriber_id)
+);
+
+create index bboard_fs_subscriber_id_idx
+    on bboard_forum_subscribers (subscriber_id);
+
+create table bboard_category_subscribers (
+    category_id integer
+        constraint bboard_cs_category_id_fk
+            references bboard_categories (category_id)
+                on delete cascade,
+    subscriber_id integer
+        constraint bboard_cs_subscriber_id_fk
+            references parties (party_id)
+                on delete cascade,
+    constraint bboard_category_subscribers_pk
+        primary key (category_id, subscriber_id)
+);
+
+create index bboard_cs_subscriber_id_idx
+    on bboard_category_subscribers (subscriber_id);
+
+create table bboard_thread_subscribers (
+    thread_id integer
+        constraint bboard_ts_thread_id_fk
+            references acs_messages (message_id)
+                on delete cascade,
+    subscriber_id integer
+        constraint bboard_ts_subscriber_id_fk
+            references parties (party_id)
+                on delete cascade,
+    constraint bboard_thread_subscribers_pk
+        primary key (thread_id, subscriber_id)
+);
+
+create index bboard_ts_subscriber_id_idx
+    on bboard_thread_subscribers (subscriber_id);
+
+@@ bboard-packages
+
+insert into cr_mime_types (mime_type) 
+    values ('text/plain; format=flowed');
+
+set feedback on
+
+-- This was stolen from ACS 3.x www/doc/sql/site-wide-search.sql
+-- to provide functionality until it is refactored into the ACS core
+
+-- Query to take free text user entered query and frob it into something
+-- that will make interMedia happy. Provided by Oracle.
+
+create or replace function bboard_im_convert(
+	query in varchar2 default null
+	) return varchar2
+is
+  i   number :=0;
+  len number :=0;
+  char varchar2(1);
+  minusString varchar2(256);
+  plusString varchar2(256); 
+  mainString varchar2(256);
+  mainAboutString varchar2(500);
+  finalString varchar2(500);
+  hasMain number :=0;
+  hasPlus number :=0;
+  hasMinus number :=0;
+  token varchar2(256);
+  tokenStart number :=1;
+  tokenFinish number :=0;
+  inPhrase number :=0;
+  inPlus number :=0;
+  inWord number :=0;
+  inMinus number :=0;
+  completePhrase number :=0;
+  completeWord number :=0;
+  code number :=0;  
+begin
+  
+  len := length(query);
+
+-- we iterate over the string to find special web operators
+  for i in 1..len loop
+    char := substr(query,i,1);
+    if(char = '"') then
+      if(inPhrase = 0) then
+        inPhrase := 1;
+	tokenStart := i;
+      else
+        inPhrase := 0;
+        completePhrase := 1;
+	tokenFinish := i-1;
+      end if;
+    elsif(char = ' ') then
+      if(inPhrase = 0) then
+        completeWord := 1;
+        tokenFinish := i-1;
+      end if;
+    elsif(char = '+') then
+      inPlus := 1;
+      tokenStart := i+1;
+    elsif((char = '-') and (i = tokenStart)) then
+      inMinus :=1;
+      tokenStart := i+1;
+    end if;
+
+    if(completeWord=1) then
+      token := '{ '||substr(query,tokenStart,tokenFinish-tokenStart+1)||' }';      
+      if(inPlus=1) then
+        plusString := plusString||','||token||'*10';
+	hasPlus :=1;	
+      elsif(inMinus=1) then
+        minusString := minusString||'OR '||token||' ';
+	hasMinus :=1;
+      else
+        mainString := mainString||' NEAR '||token;
+	mainAboutString := mainAboutString||' '||token; 
+	hasMain :=1;
+      end if;
+      tokenStart  :=i+1;
+      tokenFinish :=0;
+      inPlus := 0;
+      inMinus :=0;
+    end if;
+    completePhrase := 0;
+    completeWord :=0;
+  end loop;
+
+  -- find the last token
+  token := '{ '||substr(query,tokenStart,len-tokenStart+1)||' }';
+  if(inPlus=1) then
+    plusString := plusString||','||token||'*10';
+    hasPlus :=1;	
+  elsif(inMinus=1) then
+    minusString := minusString||'OR '||token||' ';
+    hasMinus :=1;
+  else
+    mainString := mainString||' NEAR '||token;
+    mainAboutString := mainAboutString||' '||token; 
+    hasMain :=1;
+  end if;
+
+  
+  mainString := substr(mainString,6,length(mainString)-5);
+  mainAboutString := replace(mainAboutString,'{',' ');
+  mainAboutString := replace(mainAboutString,'}',' ');
+  mainAboutString := replace(mainAboutString,')',' ');	
+  mainAboutString := replace(mainAboutString,'(',' ');
+  plusString := substr(plusString,2,length(plusString)-1);
+  minusString := substr(minusString,4,length(minusString)-4);
+
+  -- we find the components present and then process them based on the specific combinations
+  code := hasMain*4+hasPlus*2+hasMinus;
+  if(code = 7) then
+    finalString := '('||plusString||','||mainString||'*2.0,about('||mainAboutString||')*0.5) NOT ('||minusString||')';
+  elsif (code = 6) then  
+    finalString := plusString||','||mainString||'*2.0'||',about('||mainAboutString||')*0.5';
+  elsif (code = 5) then  
+    finalString := '('||mainString||',about('||mainAboutString||')) NOT ('||minusString||')';
+  elsif (code = 4) then  
+    finalString := mainString;
+    finalString := replace(finalString,'*1,',NULL); 
+    finalString := '('||finalString||')*2.0,about('||mainAboutString||')';
+  elsif (code = 3) then  
+    finalString := '('||plusString||') NOT ('||minusString||')';
+  elsif (code = 2) then  
+    finalString := plusString;
+  elsif (code = 1) then  
+    -- not is a binary operator for intermedia text
+    finalString := 'totallyImpossibleString'||' NOT ('||minusString||')';
+  elsif (code = 0) then  
+    finalString := '';
+  end if;
+
+  return finalString;
+end;
+/
+
+-- NOTE: this is only temporary until we figure out how
+--       packages will register child types to an acs-message
+declare
+    v_exists	integer;
+begin
+
+    select decode(count(*),0,0,1) into v_exists 
+      from cr_type_children
+      where parent_type = 'acs_message_revision'
+      and child_type = 'content_revision';
+
+    if v_exists = 0 then
+      content_type.register_child_type (
+          parent_type => 'acs_message_revision',
+          child_type  => 'content_revision'
+      );
+    end if;
+
+    select decode(count(*),0,0,1) into v_exists 
+      from cr_type_children
+      where parent_type = 'acs_message_revision'
+      and child_type = 'content_revision';
+
+    if v_exists = 0 then
+      content_type.register_child_type (
+          parent_type => 'acs_message_revision',
+          child_type  => 'image'
+      );
+    end if;
+
+    select decode(count(*),0,0,1) into v_exists 
+      from cr_type_children
+      where parent_type = 'acs_message_revision'
+      and child_type = 'content_revision';
+
+    if v_exists = 0 then
+      content_type.register_child_type (
+          parent_type => 'acs_message_revision',
+          child_type  => 'content_extlink'
+      );
+    end if;
+
+end;
+/
+show errors
Index: openacs-4/packages/sloan-bboard/sql/oracle/bboard-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/oracle/bboard-drop.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/oracle/bboard-drop.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,122 @@
+--
+-- packages/message/sql/bboard-drop.sql
+--
+-- @author jmp@arsdigita.com
+-- @creation-date 2000-08-31
+-- @cvs-id $Id: bboard-drop.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+-- This drop script destroys all messages that belong to forums.
+-- It should handle any permission changes that have been done since
+-- install by removing any permissions having to do with the standard
+-- bboard permissions.
+
+-- We need to get rid of things that might be referring to
+-- bboard objects that would prevent removal.  This includes:
+-- email-a-friend droppings
+-- attachments (files and images)
+
+-- if something else is pointing at one of our messages, this script
+-- will fail and removing bboard will be icky.  this is sort of hairy
+-- problem with unknown potential intra-package references.
+
+-- 
+
+-- Delete all messages that belong to forums
+declare
+    cursor message_cursor is
+        select object_id as message_id
+	    from acs_objects
+	    where object_id in (select object_id
+                                  from acs_objects
+	                          where object_type = 'acs_message'
+    	                          start with context_id in (select forum_id
+                                                              from bboard_forums)
+	                          connect by prior object_id = context_id)
+            order by object_id desc;
+begin
+    for message_val in message_cursor loop
+        bboard_message.remove(message_val.message_id);
+    end loop;
+end;
+/
+show errors
+
+-- Delete all subscriptions
+delete from bboard_thread_subscribers;
+delete from bboard_category_subscribers;
+delete from bboard_forum_subscribers;
+
+-- Delete all categories
+delete from bboard_category_message_map;
+delete from bboard_categories;
+delete from acs_objects where object_type = 'bboard_category';
+
+-- Delete all forums
+delete from bboard_forum_message_map;
+delete from bboard_forums;
+delete from acs_objects where object_type = 'bboard_forum';
+
+-- Drop all schema objects
+drop package bboard_message;
+drop package bboard_category;
+drop package bboard_forum;
+drop view bboard_messages_by_category;
+drop view bboard_messages_all;
+drop table bboard_thread_subscribers;
+drop table bboard_category_subscribers;
+drop table bboard_forum_subscribers;
+drop table bboard_category_message_map;
+drop table bboard_categories;
+drop table bboard_forum_message_map;
+drop table bboard_forums;
+
+-- Drop object type metadata
+begin
+    acs_object_type.drop_type ('bboard_forum');
+    acs_object_type.drop_type ('bboard_category');
+end;
+/
+show errors
+
+-- Drop permission metadata
+delete from acs_permissions
+    where privilege in
+        ('bboard_create_forum', 'bboard_create_category',
+         'bboard_create_message', 'bboard_write_forum',
+         'bboard_write_category', 'bboard_write_message',
+         'bboard_read_forum', 'bboard_read_category',
+         'bboard_read_message', 'bboard_delete_forum',
+         'bboard_delete_category', 'bboard_delete_message',
+         'bboard_moderate_forum');
+
+delete from acs_privilege_hierarchy
+    where privilege in
+        ('bboard_create_forum', 'bboard_create_category',
+         'bboard_create_message', 'bboard_write_forum',
+         'bboard_write_category', 'bboard_write_message',
+         'bboard_read_forum', 'bboard_read_category',
+         'bboard_read_message', 'bboard_delete_forum',
+         'bboard_delete_category', 'bboard_delete_message',
+         'bboard_moderate_forum');
+
+delete from acs_privilege_hierarchy
+    where child_privilege in
+        ('bboard_create_forum', 'bboard_create_category',
+         'bboard_create_message', 'bboard_write_forum',
+         'bboard_write_category', 'bboard_write_message',
+         'bboard_read_forum', 'bboard_read_category',
+         'bboard_read_message', 'bboard_delete_forum',
+         'bboard_delete_category', 'bboard_delete_message',
+         'bboard_moderate_forum');
+
+delete from acs_privileges
+    where privilege in
+        ('bboard_create_forum', 'bboard_create_category',
+         'bboard_create_message', 'bboard_write_forum',
+         'bboard_write_category', 'bboard_write_message',
+         'bboard_read_forum', 'bboard_read_category',
+         'bboard_read_message', 'bboard_delete_forum',
+         'bboard_delete_category', 'bboard_delete_message',
+         'bboard_moderate_forum');
+
Index: openacs-4/packages/sloan-bboard/sql/oracle/bboard-packages.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/oracle/bboard-packages.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/oracle/bboard-packages.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,694 @@
+--
+-- packages/bboard/sql/bboard-packages.sql
+--
+-- @author Anukul Kapoor <akk@arsdigita.com>
+-- @author John Prevost <jmp@arsdigita.com>
+-- @creation-date 2000-11-22
+-- @cvs-id $Id: bboard-packages.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+create or replace package bboard_forum
+as
+
+    function forum_p (
+        forum_id in bboard_forums.forum_id%TYPE
+    ) return char;
+
+    function new (
+        forum_id      in bboard_forums.forum_id%TYPE    default null,
+        short_name    in bboard_forums.short_name%TYPE,
+        charter       in bboard_forums.charter%TYPE     default null,
+        moderated_p   in bboard_forums.moderated_p%TYPE default 'f',
+        bboard_id     in bboard_forums.bboard_id%TYPE,
+        context_id    in acs_objects.context_id%TYPE    default null,
+        creation_date in acs_objects.creation_date%TYPE default sysdate,
+        creation_user in acs_objects.creation_user%TYPE default null,
+        creation_ip   in acs_objects.creation_ip%TYPE   default null,
+        object_type   in acs_objects.object_type%TYPE   default 'bboard_forum'
+    ) return acs_objects.object_id%TYPE;
+
+    procedure delete (
+        forum_id in bboard_forums.forum_id%TYPE
+    );
+
+    procedure set_attrs (
+        forum_id      in bboard_forums.forum_id%TYPE,
+        short_name    in bboard_forums.short_name%TYPE default null,
+        charter       in bboard_forums.charter%TYPE     default null,
+        moderated_p   in bboard_forums.moderated_p%TYPE default null,
+        bboard_id     in acs_objects.context_id%TYPE    default null
+    );
+
+    procedure subscribe (
+        forum_id      in bboard_forum_subscribers.forum_id%TYPE,
+        subscriber_id in bboard_forum_subscribers.subscriber_id%TYPE
+    );
+
+    function forum_containing_message (
+	message_id    in acs_messages.message_id%TYPE
+    ) return bboard_forums.forum_id%TYPE;
+
+    function name (
+        forum_id      in acs_objects.object_id%TYPE
+    ) return varchar2;
+
+end bboard_forum;
+/
+show errors
+
+create or replace package bboard_category
+as
+
+    function category_p (
+        category_id in bboard_categories.category_id%TYPE
+    ) return char;
+
+    function new (
+        category_id   in bboard_categories.category_id%TYPE default null,
+        short_name    in bboard_categories.short_name%TYPE,
+        description   in bboard_categories.description%TYPE default null,
+        forum_id      in bboard_forums.forum_id%TYPE,
+	context_id    in acs_objects.context_id%TYPE        default null,
+        creation_date in acs_objects.creation_date%TYPE     default sysdate,
+        creation_user in acs_objects.creation_user%TYPE     default null,
+        creation_ip   in acs_objects.creation_ip%TYPE       default null,
+        object_type   in acs_objects.object_type%TYPE default 'bboard_category'
+    ) return acs_objects.object_id%TYPE;
+
+    procedure delete (
+        category_id in bboard_categories.category_id%TYPE
+    );
+
+    procedure set_attrs (
+        category_id   in bboard_categories.category_id%TYPE,
+        short_name    in bboard_categories.short_name%TYPE  default null,
+        description   in bboard_categories.description%TYPE default null,
+        forum_id      in integer           default null
+    );
+
+    procedure subscribe (
+        category_id   in bboard_category_subscribers.category_id%TYPE,
+        subscriber_id in bboard_category_subscribers.subscriber_id%TYPE
+    );
+
+    function name (
+        category_id      acs_objects.object_id%TYPE
+    ) return varchar2;
+
+end bboard_category;
+/
+show errors
+
+create or replace package bboard_message
+as
+
+    function new (
+        message_id    in acs_messages.message_id%TYPE   default null,
+        reply_to      in acs_messages.message_id%TYPE   default null,
+        sent_date     in acs_messages.sent_date%TYPE    default sysdate,
+        sender        in acs_messages.sender%TYPE       default null,
+        rfc822_id     in acs_messages.rfc822_id%TYPE    default null,
+        title         in cr_revisions.title%TYPE        default null,
+        mime_type     in cr_revisions.mime_type%TYPE    default 'text/plain',
+	text          in varchar2                       default null,
+	data          in cr_revisions.content%TYPE      default null,
+        context_id    in acs_objects.context_id%TYPE    default 0,
+        creation_date in acs_objects.creation_date%TYPE default sysdate,
+        creation_user in acs_objects.creation_user%TYPE default null,
+        creation_ip   in acs_objects.creation_ip%TYPE   default null,
+        object_type   in acs_objects.object_type%TYPE   default 'acs_message'
+    ) return acs_objects.object_id%TYPE;
+
+    function message_p (
+        message_id in acs_messages.message_id%TYPE
+    ) return char;
+
+    procedure set_attrs (
+        message_id in acs_messages.message_id%TYPE,
+        reply_to   in acs_messages.reply_to%TYPE  default null,
+        sent_date  in acs_messages.sent_date%TYPE default null,
+        sender     in acs_messages.sender%TYPE    default null,
+        title      in cr_revisions.title%TYPE     default null,
+        mime_type  in cr_revisions.mime_type%TYPE default null,
+        context_id in acs_objects.context_id%TYPE default null
+    );
+
+    procedure set_status (
+        message_id in bboard_forum_message_map.message_id%TYPE,
+        forum_id   in bboard_forum_message_map.forum_id%TYPE,
+        status     in bboard_forum_message_map.status%TYPE
+    );
+
+    procedure add_category (
+        message_id  in bboard_category_message_map.message_id%TYPE,
+        category_id in bboard_category_message_map.category_id%TYPE
+    );
+
+    procedure remove_category (
+        message_id  in bboard_category_message_map.message_id%TYPE,
+        category_id in bboard_category_message_map.category_id%TYPE
+    );
+
+    procedure clear_categories (
+        message_id in bboard_category_message_map.message_id%TYPE
+    );
+
+    procedure subscribe (
+        thread_id     in bboard_thread_subscribers.thread_id%TYPE,
+        subscriber_id in bboard_thread_subscribers.subscriber_id%TYPE
+    );
+
+    function name (
+        message_id      acs_objects.object_id%TYPE
+    ) return varchar2;
+
+    procedure remove_thread (
+        thread_id    in bboard_messages_all.message_id%TYPE
+    );
+
+    procedure remove (
+        message_id   in bboard_messages_all.message_id%TYPE
+    );
+
+end bboard_message;
+/
+show errors
+
+
+
+
+create or replace package body bboard_forum
+as
+
+    function forum_p (
+        forum_id in bboard_forums.forum_id%TYPE
+    ) return char
+    is
+        v_check_forum_id integer;
+    begin
+        select count(forum_id) into v_check_forum_id
+            from bboard_forums
+            where forum_id = forum_p.forum_id;
+        if v_check_forum_id = 1 then
+            return 't';
+        else
+            return 'f';
+        end if;
+    end forum_p;
+
+    function new (
+        forum_id      in bboard_forums.forum_id%TYPE    default null,
+        short_name    in bboard_forums.short_name%TYPE,
+        charter       in bboard_forums.charter%TYPE     default null,
+        moderated_p   in bboard_forums.moderated_p%TYPE default 'f',
+        bboard_id     in bboard_forums.bboard_id%TYPE,
+        context_id    in acs_objects.context_id%TYPE    default null,
+        creation_date in acs_objects.creation_date%TYPE default sysdate,
+        creation_user in acs_objects.creation_user%TYPE default null,
+        creation_ip   in acs_objects.creation_ip%TYPE   default null,
+        object_type   in acs_objects.object_type%TYPE   default 'bboard_forum'
+    ) return acs_objects.object_id%TYPE
+    is
+        v_context_id acs_objects.context_id%TYPE;
+        v_forum_id bboard_forums.forum_id%TYPE;
+    begin
+        v_context_id := nvl(context_id, bboard_id);
+        v_forum_id := acs_object.new (
+            context_id    => v_context_id,
+            object_id     => forum_id,
+            creation_date => creation_date,
+            creation_user => creation_user,
+            creation_ip   => creation_ip,
+            object_type   => object_type
+        );
+        insert into bboard_forums
+                   (forum_id, short_name, charter, moderated_p, bboard_id)
+            values (v_forum_id, short_name, charter, moderated_p, bboard_id);
+        return v_forum_id;   
+    end new;
+
+    procedure delete (
+        forum_id in bboard_forums.forum_id%TYPE
+    )
+    is
+    begin
+        delete from bboard_forums
+            where forum_id = bboard_forum.delete.forum_id;
+        acs_object.delete(forum_id);
+    end delete;
+
+    procedure set_attrs (
+        forum_id      in bboard_forums.forum_id%TYPE,
+        short_name    in bboard_forums.short_name%TYPE default null,
+        charter       in bboard_forums.charter%TYPE     default null,
+        moderated_p   in bboard_forums.moderated_p%TYPE default null,
+        bboard_id     in acs_objects.context_id%TYPE    default null
+    )
+    is
+        v_check_forum_id integer;
+    begin
+        select count(forum_id) into v_check_forum_id
+            from bboard_forums
+            where forum_id = set_attrs.forum_id;
+        -- It's not a forum.  Fail silently?
+        if v_check_forum_id <> 1 then
+            return;
+        end if;
+        if short_name is not null then
+            update bboard_forums set short_name = set_attrs.short_name
+                where forum_id = set_attrs.forum_id;
+        end if;
+            update bboard_forums set charter = set_attrs.charter
+                where forum_id = set_attrs.forum_id;
+        if moderated_p is not null then
+            update bboard_forums set moderated_p = set_attrs.moderated_p
+                where forum_id = set_attrs.forum_id;
+        end if;
+        if bboard_id is not null then
+            update bboard_forums set bboard_id = set_attrs.bboard_id
+                where forum_id = set_attrs.forum_id;
+            update acs_objects set context_id = set_attrs.bboard_id
+                where object_id = set_attrs.forum_id;
+        end if;
+    end set_attrs;
+
+    procedure subscribe (
+        forum_id      in bboard_forum_subscribers.forum_id%TYPE,
+        subscriber_id in bboard_forum_subscribers.subscriber_id%TYPE
+    )
+    is
+    begin
+        insert into bboard_forum_subscribers (forum_id, subscriber_id)
+            values (forum_id, subscriber_id);
+    end;
+
+    function forum_containing_message (
+        message_id    in acs_messages.message_id%TYPE
+    ) return bboard_forums.forum_id%TYPE
+    is
+	v_forum_id	bboard_forums.forum_id%TYPE;
+    begin
+	select max(forum_id) into v_forum_id
+	  from bboard_forum_message_map
+	  where message_id = forum_containing_message.message_id;
+	if v_forum_id is null then
+	   return 0;
+        else
+  	   return v_forum_id;
+        end if;
+    end forum_containing_message;
+
+    function name (
+        forum_id      in acs_objects.object_id%TYPE
+    ) return varchar2
+    is
+        v_forum_name   bboard_forums.short_name%TYPE;
+    begin
+        select short_name into v_forum_name
+            from bboard_forums
+	    where forum_id = name.forum_id;
+        return v_forum_name;
+    end name;
+
+end bboard_forum;
+/
+show errors
+
+create or replace package body bboard_category
+as
+
+    function category_p (
+        category_id in bboard_categories.category_id%TYPE
+    ) return char
+    is
+        v_check_category_id integer;
+    begin
+        select count(category_id) into v_check_category_id
+            from bboard_categories
+            where category_id = category_p.category_id;
+        if v_check_category_id = 1 then
+            return 't';
+        else
+            return 'f';
+        end if;
+    end category_p;
+
+    function new (
+        category_id   in bboard_categories.category_id%TYPE default null,
+        short_name    in bboard_categories.short_name%TYPE,
+        description   in bboard_categories.description%TYPE default null,
+        forum_id      in bboard_forums.forum_id%TYPE,
+	context_id    in acs_objects.context_id%TYPE  default null,
+        creation_date in acs_objects.creation_date%TYPE default sysdate,
+        creation_user in acs_objects.creation_user%TYPE default null,
+        creation_ip   in acs_objects.creation_ip%TYPE default null,
+        object_type   in acs_objects.object_type%TYPE default 'bboard_category'
+    ) return acs_objects.object_id%TYPE
+    is
+        v_category_id bboard_categories.category_id%TYPE;
+        v_context_id acs_objects.context_id%TYPE;	
+    begin
+        v_context_id := nvl(context_id, forum_id);
+        v_category_id := acs_object.new (
+            object_id => category_id,
+            context_id => v_context_id,
+            creation_date => creation_date,
+            creation_user => creation_user,
+            creation_ip => creation_ip,
+            object_type => object_type
+        );
+        insert into bboard_categories
+                (category_id, short_name, description, forum_id)
+            values (v_category_id, short_name, description, forum_id);
+        return v_category_id;    
+    end new;
+
+    procedure delete (
+        category_id in bboard_categories.category_id%TYPE
+    )
+    is
+    begin
+        delete from bboard_categories
+            where category_id = bboard_category.delete.category_id;
+        acs_object.delete(category_id);
+    end delete;
+
+    procedure set_attrs (
+        category_id   in bboard_categories.category_id%TYPE,
+        short_name    in bboard_categories.short_name%TYPE  default null,
+        description   in bboard_categories.description%TYPE default null,
+        forum_id      in integer                            default null
+    )
+    is
+        v_check_category_id integer;
+    begin
+        select count(category_id) into v_check_category_id
+            from bboard_categories
+            where category_id = set_attrs.category_id;
+        -- It's not a category.  Fail silently?
+        if v_check_category_id <> 1 then
+            return;
+        end if;
+        -- It's a category.  Go for it.
+        if short_name is not null then
+            update bboard_categories set short_name = set_attrs.short_name
+                where category_id = set_attrs.category_id;
+        end if;
+        if description is not null then
+            update bboard_categories set description = set_attrs.description
+                where category_id = set_attrs.category_id;
+        end if;
+        if forum_id is not null then
+            update bboard_categories set forum_id = set_attrs.forum_id
+                where category_id = set_attrs.category_id;
+            update acs_objects set context_id = set_attrs.forum_id
+                where object_id = set_attrs.category_id;
+        end if;
+    end set_attrs;
+
+    procedure subscribe (
+        category_id   in bboard_category_subscribers.category_id%TYPE,
+        subscriber_id in bboard_category_subscribers.subscriber_id%TYPE
+    )
+    is
+    begin
+        insert into bboard_category_subscribers (category_id, subscriber_id)
+            values (category_id, subscriber_id);
+    end;
+
+    function name (
+        category_id      in acs_objects.object_id%TYPE
+    ) return varchar2
+    is
+        v_category_name   bboard_categories.short_name%TYPE;
+    begin
+        select short_name into v_category_name
+            from bboard_categories
+	    where category_id = name.category_id;
+        return v_category_name;
+    end name;
+
+end bboard_category;
+/
+show errors
+
+
+create or replace package body bboard_message
+as
+
+    function new (
+        message_id    in acs_messages.message_id%TYPE   default null,
+        reply_to      in acs_messages.message_id%TYPE   default null,
+        sent_date     in acs_messages.sent_date%TYPE    default sysdate,
+        sender        in acs_messages.sender%TYPE       default null,
+        rfc822_id     in acs_messages.rfc822_id%TYPE    default null,
+        title         in cr_revisions.title%TYPE        default null,
+        mime_type     in cr_revisions.mime_type%TYPE    default 'text/plain',
+	text          in varchar2                       default null,
+	data          in cr_revisions.content%TYPE      default null,
+        context_id    in acs_objects.context_id%TYPE    default 0,
+        creation_date in acs_objects.creation_date%TYPE default sysdate,
+        creation_user in acs_objects.creation_user%TYPE default null,
+        creation_ip   in acs_objects.creation_ip%TYPE   default null,
+        object_type   in acs_objects.object_type%TYPE   default 'acs_message'
+    ) return acs_objects.object_id%TYPE
+    is
+        v_sent_date acs_messages.sent_date%TYPE;
+    begin
+        v_sent_date := nvl(sent_date, sysdate);
+
+        return acs_message.new (
+            message_id => message_id,
+            reply_to => reply_to,
+            sent_date => v_sent_date,
+            sender => sender,
+            title => title,
+            mime_type => mime_type,
+            text => text,
+            data => data,
+            context_id => context_id,
+            creation_date => creation_date,
+            creation_user => creation_user,
+            creation_ip => creation_ip,
+            object_type => object_type
+        );
+    end new;
+
+    function message_p (
+        message_id in acs_messages.message_id%TYPE
+    ) return char
+    is
+        v_check_message_id integer;
+    begin
+        select count(message_id) into v_check_message_id
+            from acs_messages
+            where message_id = message_p.message_id;
+        if v_check_message_id = 1 then
+            return 't';
+        else
+            return 'f';
+        end if;
+    end message_p;
+
+    procedure set_attrs (
+        message_id in acs_messages.message_id%TYPE,
+        reply_to   in acs_messages.reply_to%TYPE             default null,
+        sent_date  in acs_messages.sent_date%TYPE            default null,
+        sender     in acs_messages.sender%TYPE               default null,
+        title      in cr_revisions.title%TYPE                default null,
+        mime_type  in cr_revisions.mime_type%TYPE            default null,
+        context_id in acs_objects.context_id%TYPE            default null
+    )
+    is
+        v_check_message_id integer;
+        v_revision_id integer;
+    begin
+        if message_p(message_id) = 'f' then
+            return;
+        end if;
+
+        -- modify the parts that are in acs_messages
+
+        if reply_to is not null then
+            update acs_messages set reply_to = set_attrs.reply_to
+                where message_id = set_attrs.message_id;
+        end if;
+        if sent_date is not null then
+            update acs_messages set sent_date = set_attrs.sent_date
+                where message_id = set_attrs.message_id;
+        end if;
+        if sender is not null then
+            update acs_messages set sender = set_attrs.sender
+                where message_id = set_attrs.message_id;
+        end if;
+
+        -- modify the parts that are in cr_revisions
+        if title is not null or mime_type is not null then
+            select live_revision into v_revision_id
+                from cr_items where item_id = set_attrs.message_id
+                for update;
+            if title is not null then
+                update cr_revisions set title = set_attrs.title
+                    where revision_id = v_revision_id;
+            end if;
+            if mime_type is not null then
+                update cr_revisions set mime_type = set_attrs.mime_type
+                    where revision_id = v_revision_id;
+            end if;
+        end if;
+
+        -- modify the context_id is acs_objects
+
+        if context_id is not null then
+            update acs_objects set context_id = set_attrs.context_id
+                where object_id = set_attrs.message_id;
+        end if;
+
+    end set_attrs;
+
+    procedure set_status (
+        message_id in bboard_forum_message_map.message_id%TYPE,
+        forum_id   in bboard_forum_message_map.forum_id%TYPE,
+        status     in bboard_forum_message_map.status%TYPE
+    )
+    is
+    begin
+        if message_p(message_id) = 'f'
+                or bboard_forum.forum_p(forum_id) = 'f' then
+            return;
+        end if;
+        delete from bboard_forum_message_map
+            where message_id = set_status.message_id
+                and forum_id = set_status.forum_id;
+        if status is not null then
+            insert into bboard_forum_message_map
+                    (forum_id, message_id, status)
+                values (set_status.forum_id, set_status.message_id,
+                    set_status.status);
+        end if;
+    end set_status;
+
+    procedure add_category (
+        message_id  in bboard_category_message_map.message_id%TYPE,
+        category_id in bboard_category_message_map.category_id%TYPE
+    )
+    is
+    begin
+        insert into bboard_category_message_map (message_id, category_id)
+            values (add_category.message_id, add_category.category_id);
+    end add_category;
+
+    procedure remove_category (
+        message_id  in bboard_category_message_map.message_id%TYPE,
+        category_id in bboard_category_message_map.category_id%TYPE
+    )
+    is
+    begin
+        delete from bboard_category_message_map
+            where category_id = remove_category.category_id
+              and message_id = remove_category.message_id;
+    end remove_category;
+
+    procedure clear_categories (
+        message_id in bboard_category_message_map.message_id%TYPE
+    )
+    is
+    begin
+        delete from bboard_category_message_map
+            where message_id = clear_categories.message_id;
+    end clear_categories;
+
+    procedure subscribe (
+        thread_id     in bboard_thread_subscribers.thread_id%TYPE,
+        subscriber_id in bboard_thread_subscribers.subscriber_id%TYPE
+    )
+    is
+    begin
+        insert into bboard_thread_subscribers (thread_id, subscriber_id)
+            values (thread_id, subscriber_id);
+    end;
+
+    function name (
+        message_id      in acs_objects.object_id%TYPE
+    ) return varchar2
+    is
+        v_message_name   bboard_messages_all.title%TYPE;
+    begin
+        select title into v_message_name
+            from bboard_messages_all
+            where message_id = name.message_id;
+        return v_message_name;
+    end name;
+
+    procedure remove_thread (
+        thread_id    in bboard_messages_all.message_id%TYPE
+    )
+    is
+	cursor messages_children is
+	   select object_id as child_id, object_type
+	       from acs_objects
+               where context_id in (select message_id 
+                                       from acs_messages
+                                       connect by prior message_id = reply_to
+                                       start with message_id = thread_id);
+
+        cursor messages is
+	   select message_id
+	       from acs_messages
+	       connect by prior message_id = reply_to
+	       start with message_id = thread_id;
+
+        image_p	     number;
+    begin
+	for child_val in messages_children loop
+	    if child_val.object_type = 'acs_message' then
+	       acs_message.delete(child_val.child_id);
+	    elsif child_val.object_type = 'content_item' then
+		select count(*) into image_p
+		    from images
+                    where image_id = child_val.child_id;
+                if image_p = 1 then
+                    acs_message.delete_image(child_val.child_id);
+                else
+                    acs_message.delete_file(child_val.child_id);
+                end if;
+           end if;
+       end loop;
+
+       for message_val in messages loop
+           acs_message.delete(message_val.message_id);
+       end loop;
+
+    end remove_thread;
+
+    procedure remove (
+        message_id    in bboard_messages_all.message_id%TYPE
+    )
+    is
+	cursor messages_children is
+	   select object_id as child_id, object_type
+	       from acs_objects
+               where context_id = message_id;
+        image_p	     number;
+    begin
+	for child_val in messages_children loop
+	    if child_val.object_type = 'acs_message' then
+	       acs_message.delete(child_val.child_id);
+	    elsif child_val.object_type = 'content_item' then
+		select count(*) into image_p
+		    from images
+                    where image_id = child_val.child_id;
+                if image_p = 1 then
+                    acs_message.delete_image(child_val.child_id);
+                else
+                    acs_message.delete_file(child_val.child_id);
+                end if;
+           end if;
+       end loop;
+
+       acs_message.delete(message_id);
+    end remove;
+
+end bboard_message;
+/
+show errors
Index: openacs-4/packages/sloan-bboard/sql/oracle/bboard-views.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/oracle/bboard-views.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/oracle/bboard-views.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,34 @@
+--
+-- packages/bboard/sql/bboard-views.sql
+--
+-- @author Anukul Kapoor <akk@arsdigita.com>
+-- @author John Prevost <jmp@arsdigita.com>
+-- @creation-date 2001-02-05
+-- @cvs-id $Id: bboard-views.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+
+
+create or replace view bboard_messages_all as
+    select m.message_id, m.reply_to, m.sent_date, m.sender,
+           m.title, m.mime_type, m.content, f.forum_id, f.status,
+           (select count(1) from acs_messages m2
+               where m2.message_id in (select mf.message_id 
+                                          from bboard_forum_message_map mf
+                                          where mf.forum_id = f.forum_id)
+               start with m2.message_id = m.message_id
+               connect by m2.reply_to = prior m2.message_id) as num_replies,
+           (select max(sent_date) from acs_messages m2
+               where m2.message_id in (select mf.message_id 
+                                          from bboard_forum_message_map mf
+                                          where mf.forum_id = f.forum_id)
+               start with m2.message_id = m.message_id
+               connect by m2.reply_to = prior m2.message_id) as last_reply_date
+        from acs_messages_all m, bboard_forum_message_map f
+        where m.message_id = f.message_id;
+
+create or replace view bboard_messages_by_category as
+    select msg.*, cat.category_id
+        from bboard_messages_all msg, bboard_category_message_map cat
+        where msg.message_id = cat.message_id(+);
+
Index: openacs-4/packages/sloan-bboard/sql/oracle/index_sync.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/oracle/index_sync.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/oracle/index_sync.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,11 @@
+-- Resync the interMedia index every hour.
+
+DECLARE
+  v_job number;
+BEGIN 
+  dbms_job.submit(v_job, 
+                  'ctx_ddl.sync_index(''cr_rev_content_index'');', 
+                  interval => 'sysdate + 1/24');
+END;
+/
+show errors
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0-4.0.1.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0-4.0.1.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0-4.0.1.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,139 @@
+--
+-- packages/bboard/sql/upgrade-4.0-4.0.1.sql
+--
+-- @author Anukul Kapoor
+-- @creation-date 2000-11-27
+-- @cvs-id $Id: upgrade-4.0-4.0.1.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+-- This was stolen from ACS 3.x www/doc/sql/site-wide-search.sql
+-- to provide functionality until it is refactored into the ACS core
+
+-- Query to take free text user entered query and frob it into something
+-- that will make interMedia happy. Provided by Oracle.
+
+create or replace function bboard_im_convert(
+	query in varchar2 default null
+	) return varchar2
+is
+  i   number :=0;
+  len number :=0;
+  char varchar2(1);
+  minusString varchar2(256);
+  plusString varchar2(256); 
+  mainString varchar2(256);
+  mainAboutString varchar2(500);
+  finalString varchar2(500);
+  hasMain number :=0;
+  hasPlus number :=0;
+  hasMinus number :=0;
+  token varchar2(256);
+  tokenStart number :=1;
+  tokenFinish number :=0;
+  inPhrase number :=0;
+  inPlus number :=0;
+  inWord number :=0;
+  inMinus number :=0;
+  completePhrase number :=0;
+  completeWord number :=0;
+  code number :=0;  
+begin
+  
+  len := length(query);
+
+-- we iterate over the string to find special web operators
+  for i in 1..len loop
+    char := substr(query,i,1);
+    if(char = '"') then
+      if(inPhrase = 0) then
+        inPhrase := 1;
+	tokenStart := i;
+      else
+        inPhrase := 0;
+        completePhrase := 1;
+	tokenFinish := i-1;
+      end if;
+    elsif(char = ' ') then
+      if(inPhrase = 0) then
+        completeWord := 1;
+        tokenFinish := i-1;
+      end if;
+    elsif(char = '+') then
+      inPlus := 1;
+      tokenStart := i+1;
+    elsif((char = '-') and (i = tokenStart)) then
+      inMinus :=1;
+      tokenStart := i+1;
+    end if;
+
+    if(completeWord=1) then
+      token := '{ '||substr(query,tokenStart,tokenFinish-tokenStart+1)||' }';      
+      if(inPlus=1) then
+        plusString := plusString||','||token||'*10';
+	hasPlus :=1;	
+      elsif(inMinus=1) then
+        minusString := minusString||'OR '||token||' ';
+	hasMinus :=1;
+      else
+        mainString := mainString||' NEAR '||token;
+	mainAboutString := mainAboutString||' '||token; 
+	hasMain :=1;
+      end if;
+      tokenStart  :=i+1;
+      tokenFinish :=0;
+      inPlus := 0;
+      inMinus :=0;
+    end if;
+    completePhrase := 0;
+    completeWord :=0;
+  end loop;
+
+  -- find the last token
+  token := '{ '||substr(query,tokenStart,len-tokenStart+1)||' }';
+  if(inPlus=1) then
+    plusString := plusString||','||token||'*10';
+    hasPlus :=1;	
+  elsif(inMinus=1) then
+    minusString := minusString||'OR '||token||' ';
+    hasMinus :=1;
+  else
+    mainString := mainString||' NEAR '||token;
+    mainAboutString := mainAboutString||' '||token; 
+    hasMain :=1;
+  end if;
+
+  
+  mainString := substr(mainString,6,length(mainString)-5);
+  mainAboutString := replace(mainAboutString,'{',' ');
+  mainAboutString := replace(mainAboutString,'}',' ');
+  mainAboutString := replace(mainAboutString,')',' ');	
+  mainAboutString := replace(mainAboutString,'(',' ');
+  plusString := substr(plusString,2,length(plusString)-1);
+  minusString := substr(minusString,4,length(minusString)-4);
+
+  -- we find the components present and then process them based on the specific combinations
+  code := hasMain*4+hasPlus*2+hasMinus;
+  if(code = 7) then
+    finalString := '('||plusString||','||mainString||'*2.0,about('||mainAboutString||')*0.5) NOT ('||minusString||')';
+  elsif (code = 6) then  
+    finalString := plusString||','||mainString||'*2.0'||',about('||mainAboutString||')*0.5';
+  elsif (code = 5) then  
+    finalString := '('||mainString||',about('||mainAboutString||')) NOT ('||minusString||')';
+  elsif (code = 4) then  
+    finalString := mainString;
+    finalString := replace(finalString,'*1,',NULL); 
+    finalString := '('||finalString||')*2.0,about('||mainAboutString||')';
+  elsif (code = 3) then  
+    finalString := '('||plusString||') NOT ('||minusString||')';
+  elsif (code = 2) then  
+    finalString := plusString;
+  elsif (code = 1) then  
+    -- not is a binary operator for intermedia text
+    finalString := 'totallyImpossibleString'||' NOT ('||minusString||')';
+  elsif (code = 0) then  
+    finalString := '';
+  end if;
+
+  return finalString;
+end;
+/
Index: openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0.1-4.0.2.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0.1-4.0.2.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0.1-4.0.2.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,163 @@
+--
+-- packages/bboard/sql/upgrade-4.0.1-4.0.2.sql
+--
+-- @author John Prevost <jmp@arsdigita.com>
+-- @creation-date 2000-12-01
+-- @cvs-id $Id: upgrade-4.0.1-4.0.2.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+set feedback off
+
+-- arrgh.  This isn't entirely safe, but we can't do anything about it!
+-- locking the table fails (alter table commands hit the lock, bounce,
+-- and the transaction aborts, since DDL isn't transactional.)  Can't
+-- create another constraint with the same behavior to change behind the
+-- back.  Lose lose lose.
+
+alter table bboard_forums
+    drop constraint bboard_forums_bboard_id_fk;
+
+alter table bboard_forums add (
+    constraint bboard_forums_bboard_id_fk
+        foreign key (bboard_id)
+            references apm_packages (package_id)
+                on delete cascade
+);
+
+create index bboard_forums_bboard_id_idx
+    on bboard_forums (bboard_id);
+
+alter table bboard_forum_message_map
+    drop constraint bboard_fmm_forum_id_fk;
+alter table bboard_forum_message_map
+    drop constraint bboard_fmm_message_id_fk;
+
+alter table bboard_forum_message_map add (
+    constraint bboard_fmm_forum_id_fk
+        foreign key (forum_id)
+            references bboard_forums (forum_id)
+                on delete cascade,
+    constraint bboard_fmm_message_id_fk
+        foreign key (message_id)
+            references acs_messages (message_id)
+                on delete cascade
+);
+
+alter table bboard_categories
+    drop constraint bboard_c_forum_id_fk;
+
+alter table bboard_categories add (
+    constraint bboard_c_forum_id_fk
+        foreign key (forum_id)
+            references bboard_forums (forum_id)
+                on delete cascade
+);
+
+create index bboard_categories_forum_id_idx
+    on bboard_categories (forum_id);
+
+alter table bboard_forum_subscribers
+    drop constraint bboard_fs_forum_id_fk;
+alter table bboard_forum_subscribers
+    drop constraint bboard_fs_subscriber_id_fk;
+
+alter table bboard_forum_subscribers add (
+    constraint bboard_fs_forum_id_fk
+        foreign key (forum_id)
+            references bboard_forums (forum_id)
+                on delete cascade,
+    constraint bboard_fs_subscriber_id_fk
+        foreign key (subscriber_id)
+            references parties (party_id)
+                on delete cascade
+);
+
+create index bboard_fs_subscriber_id_idx
+    on bboard_forum_subscribers (subscriber_id);
+
+alter table bboard_category_subscribers
+    drop constraint bboard_cs_category_id_fk;
+alter table bboard_category_subscribers
+    drop constraint bboard_cs_subscriber_id_fk;
+
+alter table bboard_category_subscribers add (
+    constraint bboard_cs_category_id_fk
+        foreign key (category_id)
+            references bboard_categories (category_id)
+                on delete cascade,
+    constraint bboard_cs_subscriber_id_fk
+        foreign key (subscriber_id)
+            references parties (party_id)
+                on delete cascade
+);
+
+create index bboard_cs_subscriber_id_idx
+    on bboard_category_subscribers (subscriber_id);
+
+alter table bboard_thread_subscribers
+    drop constraint bboard_ts_thread_id_fk;
+alter table bboard_thread_subscribers
+    drop constraint bboard_ts_subscriber_id_fk;
+
+alter table bboard_thread_subscribers add (
+    constraint bboard_ts_thread_id_fk
+        foreign key (thread_id)
+            references acs_messages (message_id)
+                on delete cascade,
+    constraint bboard_ts_subscriber_id_fk
+        foreign key (subscriber_id)
+            references parties (party_id)
+                on delete cascade
+);
+
+create index bboard_ts_subscriber_id_idx
+    on bboard_thread_subscribers (subscriber_id);
+
+
+@@ bboard-views
+
+-- NOTE: this is only temporary until we figure out how
+--       packages will register child types to an acs-message
+declare
+    v_exists	integer;
+begin
+
+    select decode(count(*),0,0,1) into v_exists 
+      from cr_type_children
+      where parent_type = 'acs_message_revision'
+      and child_type = 'content_revision';
+
+    if v_exists = 0 then
+      content_type.register_child_type (
+          parent_type => 'acs_message_revision',
+          child_type  => 'content_revision'
+      );
+    end if;
+
+    select decode(count(*),0,0,1) into v_exists 
+      from cr_type_children
+      where parent_type = 'acs_message_revision'
+      and child_type = 'content_revision';
+
+    if v_exists = 0 then
+      content_type.register_child_type (
+          parent_type => 'acs_message_revision',
+          child_type  => 'image'
+      );
+    end if;
+
+    select decode(count(*),0,0,1) into v_exists 
+      from cr_type_children
+      where parent_type = 'acs_message_revision'
+      and child_type = 'content_revision';
+
+    if v_exists = 0 then
+      content_type.register_child_type (
+          parent_type => 'acs_message_revision',
+          child_type  => 'content_extlink'
+      );
+    end if;
+
+end;
+/
+show errors
Index: openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0.2b3-4.0.2b4.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0.2b3-4.0.2b4.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0.2b3-4.0.2b4.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,55 @@
+--
+-- packages/bboard/sql/upgrade-4.0.2b3-4.0.2b4.sql
+--
+-- @author Anukul Kapoor <akk@arsdigita.com>
+-- @creation-date 2001-01-15
+-- @cvs-id $Id: upgrade-4.0.2b3-4.0.2b4.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+set feedback off
+
+-- NOTE: this is only temporary until we figure out how
+--       packages will register child types to an acs-message
+declare
+    v_exists	integer;
+begin
+
+    select decode(count(*),0,0,1) into v_exists 
+      from cr_type_children
+      where parent_type = 'acs_message_revision'
+      and child_type = 'content_revision';
+
+    if v_exists = 0 then
+      content_type.register_child_type (
+          parent_type => 'acs_message_revision',
+          child_type  => 'content_revision'
+      );
+    end if;
+
+    select decode(count(*),0,0,1) into v_exists 
+      from cr_type_children
+      where parent_type = 'acs_message_revision'
+      and child_type = 'content_revision';
+
+    if v_exists = 0 then
+      content_type.register_child_type (
+          parent_type => 'acs_message_revision',
+          child_type  => 'image'
+      );
+    end if;
+
+    select decode(count(*),0,0,1) into v_exists 
+      from cr_type_children
+      where parent_type = 'acs_message_revision'
+      and child_type = 'content_revision';
+
+    if v_exists = 0 then
+      content_type.register_child_type (
+          parent_type => 'acs_message_revision',
+          child_type  => 'content_extlink'
+      );
+    end if;
+
+end;
+/
+show errors
Index: openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0.2b5-4.0.2b6.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0.2b5-4.0.2b6.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0.2b5-4.0.2b6.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,11 @@
+--
+-- packages/bboard/sql/upgrade-4.0.2b5-4.0.2b6.sql
+--
+-- @author John Prevost <jmp@arsdigita.com>
+-- @creation-date 2000-12-01
+-- @cvs-id $Id: upgrade-4.0.2b5-4.0.2b6.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+set feedback off
+
+@@ bboard-views
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0.2b6-4.0.2b7.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0.2b6-4.0.2b7.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0.2b6-4.0.2b7.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,11 @@
+--
+-- packages/bboard/sql/upgrade-4.0.2b6-4.0.2b7.sql
+--
+-- @author Anukul Kapoor <akk@arsdigita.com>
+-- @creation-date 2001-3-21
+-- @cvs-id $Id: upgrade-4.0.2b6-4.0.2b7.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+set feedback off
+
+@@ bboard-packages
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0b-4.0.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0b-4.0.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/oracle/upgrade-4.0b-4.0.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,152 @@
+--
+-- packages/bboard/sql/upgrade-4.0b-4.0.sql
+--
+-- @author John Prevost <jmp@arsdigita.com>
+-- @creation-date 2000-11-22
+-- @cvs-id $Id: upgrade-4.0b-4.0.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+create table bboard_category_subscribers (
+    category_id integer
+        constraint bboard_cs_category_id_fk
+            references bboard_categories (category_id),                   
+    subscriber_id integer                                  
+        constraint bboard_cs_subscriber_id_fk
+            references parties (party_id),
+    constraint bboard_category_subscribers_pk
+        primary key (category_id, subscriber_id)
+);
+
+@@ bboard-packages
+
+-- This was stolen from ACS 3.x www/doc/sql/site-wide-search.sql
+-- to provide functionality until it is refactored into the ACS core
+
+-- Query to take free text user entered query and frob it into something
+-- that will make interMedia happy. Provided by Oracle.
+
+create or replace function bboard_im_convert(
+	query in varchar2 default null
+	) return varchar2
+is
+  i   number :=0;
+  len number :=0;
+  char varchar2(1);
+  minusString varchar2(256);
+  plusString varchar2(256); 
+  mainString varchar2(256);
+  mainAboutString varchar2(500);
+  finalString varchar2(500);
+  hasMain number :=0;
+  hasPlus number :=0;
+  hasMinus number :=0;
+  token varchar2(256);
+  tokenStart number :=1;
+  tokenFinish number :=0;
+  inPhrase number :=0;
+  inPlus number :=0;
+  inWord number :=0;
+  inMinus number :=0;
+  completePhrase number :=0;
+  completeWord number :=0;
+  code number :=0;  
+begin
+  
+  len := length(query);
+
+-- we iterate over the string to find special web operators
+  for i in 1..len loop
+    char := substr(query,i,1);
+    if(char = '"') then
+      if(inPhrase = 0) then
+        inPhrase := 1;
+	tokenStart := i;
+      else
+        inPhrase := 0;
+        completePhrase := 1;
+	tokenFinish := i-1;
+      end if;
+    elsif(char = ' ') then
+      if(inPhrase = 0) then
+        completeWord := 1;
+        tokenFinish := i-1;
+      end if;
+    elsif(char = '+') then
+      inPlus := 1;
+      tokenStart := i+1;
+    elsif((char = '-') and (i = tokenStart)) then
+      inMinus :=1;
+      tokenStart := i+1;
+    end if;
+
+    if(completeWord=1) then
+      token := '{ '||substr(query,tokenStart,tokenFinish-tokenStart+1)||' }';      
+      if(inPlus=1) then
+        plusString := plusString||','||token||'*10';
+	hasPlus :=1;	
+      elsif(inMinus=1) then
+        minusString := minusString||'OR '||token||' ';
+	hasMinus :=1;
+      else
+        mainString := mainString||' NEAR '||token;
+	mainAboutString := mainAboutString||' '||token; 
+	hasMain :=1;
+      end if;
+      tokenStart  :=i+1;
+      tokenFinish :=0;
+      inPlus := 0;
+      inMinus :=0;
+    end if;
+    completePhrase := 0;
+    completeWord :=0;
+  end loop;
+
+  -- find the last token
+  token := '{ '||substr(query,tokenStart,len-tokenStart+1)||' }';
+  if(inPlus=1) then
+    plusString := plusString||','||token||'*10';
+    hasPlus :=1;	
+  elsif(inMinus=1) then
+    minusString := minusString||'OR '||token||' ';
+    hasMinus :=1;
+  else
+    mainString := mainString||' NEAR '||token;
+    mainAboutString := mainAboutString||' '||token; 
+    hasMain :=1;
+  end if;
+
+  
+  mainString := substr(mainString,6,length(mainString)-5);
+  mainAboutString := replace(mainAboutString,'{',' ');
+  mainAboutString := replace(mainAboutString,'}',' ');
+  mainAboutString := replace(mainAboutString,')',' ');	
+  mainAboutString := replace(mainAboutString,'(',' ');
+  plusString := substr(plusString,2,length(plusString)-1);
+  minusString := substr(minusString,4,length(minusString)-4);
+
+  -- we find the components present and then process them based on the specific combinations
+  code := hasMain*4+hasPlus*2+hasMinus;
+  if(code = 7) then
+    finalString := '('||plusString||','||mainString||'*2.0,about('||mainAboutString||')*0.5) NOT ('||minusString||')';
+  elsif (code = 6) then  
+    finalString := plusString||','||mainString||'*2.0'||',about('||mainAboutString||')*0.5';
+  elsif (code = 5) then  
+    finalString := '('||mainString||',about('||mainAboutString||')) NOT ('||minusString||')';
+  elsif (code = 4) then  
+    finalString := mainString;
+    finalString := replace(finalString,'*1,',NULL); 
+    finalString := '('||finalString||')*2.0,about('||mainAboutString||')';
+  elsif (code = 3) then  
+    finalString := '('||plusString||') NOT ('||minusString||')';
+  elsif (code = 2) then  
+    finalString := plusString;
+  elsif (code = 1) then  
+    -- not is a binary operator for intermedia text
+    finalString := 'totallyImpossibleString'||' NOT ('||minusString||')';
+  elsif (code = 0) then  
+    finalString := '';
+  end if;
+
+  return finalString;
+end;
+/
Index: openacs-4/packages/sloan-bboard/sql/postgresql/bboard-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/postgresql/bboard-create.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/postgresql/bboard-create.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,339 @@
+--
+-- packages/bboard/sql/bboard-create.sql
+--
+-- @author Anukul Kapoor <akk@arsdigita.com>
+-- @author John Prevost <jmp@arsdigita.com>
+-- @creation-date 2000-08-29
+-- @cvs-id $Id: bboard-create.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+-- separate parts so that if one fails, the rest happens
+
+-- create the privileges
+
+begin;
+
+ select acs_privilege__create_privilege('bboard_create_forum',null,null);
+ select acs_privilege__create_privilege('bboard_create_category',null,null);
+ select acs_privilege__create_privilege('bboard_create_message',null,null);
+ select acs_privilege__create_privilege('bboard_write_forum',null,null);
+ select acs_privilege__create_privilege('bboard_write_category',null,null);
+ select acs_privilege__create_privilege('bboard_write_message',null,null);
+ select acs_privilege__create_privilege('bboard_read_forum',null,null);
+ select acs_privilege__create_privilege('bboard_read_category',null,null);
+ select acs_privilege__create_privilege('bboard_read_message',null,null);
+ select acs_privilege__create_privilege('bboard_delete_forum',null,null);
+ select acs_privilege__create_privilege('bboard_delete_category',null,null);
+ select acs_privilege__create_privilege('bboard_delete_message',null,null);
+ select acs_privilege__create_privilege('bboard_moderate_forum',null,null);
+
+
+ -- temporarily drop this trigger to avoid a data-change violation 
+ -- on acs_privilege_hierarchy_index while updating the child privileges.
+
+ drop trigger acs_priv_hier_ins_del_tr on acs_privilege_hierarchy;
+
+ select acs_privilege__add_child('create','bboard_create_forum');
+ select acs_privilege__add_child('create','bboard_create_category');
+ select acs_privilege__add_child('create','bboard_create_message');
+ select acs_privilege__add_child('write','bboard_write_forum');
+ select acs_privilege__add_child('write','bboard_write_category');
+ select acs_privilege__add_child('write','bboard_write_message');
+ select acs_privilege__add_child('read','bboard_read_forum');
+ select acs_privilege__add_child('read','bboard_read_category');
+ select acs_privilege__add_child('read','bboard_read_message');
+ select acs_privilege__add_child('delete','bboard_delete_forum');
+ select acs_privilege__add_child('delete','bboard_delete_category');
+ select acs_privilege__add_child('delete','bboard_delete_message');
+ 
+ -- re-enable the trigger before the last insert to force the 
+ -- acs_privilege_hierarchy_index table to be updated.
+
+ create trigger acs_priv_hier_ins_del_tr after insert or delete
+ on acs_privilege_hierarchy for each row
+ execute procedure acs_priv_hier_ins_del_tr ();
+
+select acs_privilege__add_child('admin','bboard_moderate_forum');
+end;
+
+
+create function inline_0 ()
+returns integer as '
+declare
+    default_context integer;
+    registered_users integer;
+    the_public integer;
+begin
+
+    default_context := acs__magic_object_id(''default_context'');
+    registered_users := acs__magic_object_id(''registered_users'');
+    the_public := acs__magic_object_id(''the_public'');
+
+    -- give registered users the power to post by default
+
+    perform acs_permission__grant_permission (
+        default_context,
+        registered_users,
+        ''bboard_create_message''
+    );
+
+    -- give the public the power to read by default
+
+    perform acs_permission__grant_permission (
+        default_context,
+        the_public,
+        ''bboard_read_message''
+    );
+
+    perform acs_permission__grant_permission (
+        default_context,
+        the_public,
+        ''bboard_read_category''
+    );
+
+    perform acs_permission__grant_permission (
+        default_context,
+        the_public,
+        ''bboard_read_forum''
+    );
+
+
+    return 0;
+end;
+' language 'plpgsql';
+
+select inline_0 ();
+drop function inline_0 ();
+
+
+select acs_object_type__create_type (
+    'bboard_forum',
+    'BBoard Forum',
+    'BBoard Forum',
+    'acs_object',
+    'BBOARD_FORUMS',
+    'FORUM_ID',
+    null,
+    'f',
+    null,
+    'BBOARD_FORUM__NAME'
+);
+
+select acs_object_type__create_type (
+    'bboard_category',
+    'BBoard Category',
+    'BBoard Categories',
+    'acs_object',
+    'BBOARD_CATEGORIES',
+    'CATEGORY_ID',
+    null,
+    'f',
+     null,
+    'BBOARD_CATEGORY__NAME'
+);
+
+
+
+-- bboard forums
+--
+-- these act as primary containers for messages
+-- a message's context_id will point to its forum
+
+create table bboard_forums (
+    forum_id integer
+        constraint bboard_forums_forum_id_fk
+            references acs_objects (object_id)
+        constraint bboard_forums_pk
+            primary key,    
+    short_name varchar(400)
+        constraint bboard_forums_short_name_nn
+            not null,
+    charter varchar(4000),
+    moderated_p char(1)
+        constraint bboard_forums_moderated_p_nn
+            not null
+        constraint bboard_forums_moderated_p_ck
+            check (moderated_p in ('t','f')),
+    bboard_id integer
+        constraint bboard_forums_bboard_id_nn
+            not null
+        constraint bboard_forums_bboard_id_fk
+            references apm_packages (package_id)
+                on delete cascade
+);
+
+create index bboard_forums_bboard_id_idx
+    on bboard_forums (bboard_id);
+
+create table bboard_forum_message_map (
+    forum_id integer
+        constraint bboard_fmm_forum_id_fk
+            references bboard_forums (forum_id)
+                on delete cascade,
+    message_id integer
+        constraint bboard_fmm_message_id_fk
+            references acs_messages (message_id)
+                on delete cascade,
+    status varchar(20)
+        constraint bboard_fmm_status_ck
+            check (status in ('unmoderated', 'approved', 'rejected'))
+        constraint bboard_fmm_status_nn
+            not null,
+    last_reply_date timestamp,
+    num_replies integer,
+    constraint bboard_forum_message_map_pk
+        primary key (forum_id, message_id)
+);
+
+create index bboard_fmm_message_id_idx
+    on bboard_forum_message_map (message_id);
+
+create index bboard_fmm_status_idx
+    on bboard_forum_message_map (status);
+
+-- bboard categories
+--
+-- these are for intra-forum categorization
+-- categories will be scoped to forums via their acs_object.context_id
+
+create table bboard_categories (
+    category_id integer
+        constraint bboard_c_category_id_fk
+            references acs_objects (object_id)
+        constraint bboard_c_category_id_pk
+            primary key,
+    short_name varchar(400)
+        constraint bboard_c_short_name_nn
+            not null,
+    forum_id integer
+        constraint bboard_c_forum_id_fk
+            references bboard_forums (forum_id)
+                on delete cascade
+        constraint bboard_c_forum_id_nn
+            not null,
+    description varchar(4000)
+);
+
+create index bboard_categories_forum_id_idx
+    on bboard_categories (forum_id);
+
+create table bboard_category_message_map (
+    category_id integer
+        constraint bboard_cmm_category_id_fk
+            references bboard_categories (category_id)
+                on delete cascade,
+    message_id integer
+        constraint bboard_cmm_message_id_fk
+            references acs_messages (message_id)
+                on delete cascade,
+    constraint bboard_category_message_map_pk
+        primary key (category_id, message_id)
+);
+
+create index bboard_cmm_message_id_idx
+    on bboard_category_message_map (message_id);
+
+-- @@ bboard-views
+
+-- Tables to track subscriptions
+
+create table bboard_forum_subscribers (
+    forum_id integer
+        constraint bboard_fs_forum_id_fk
+            references bboard_forums (forum_id)
+                on delete cascade,
+    subscriber_id integer
+        constraint bboard_fs_subscriber_id_fk
+            references parties (party_id)
+                on delete cascade,
+    constraint bboard_forum_subscribers_pk
+        primary key (forum_id, subscriber_id)
+);
+
+create index bboard_fs_subscriber_id_idx
+    on bboard_forum_subscribers (subscriber_id);
+
+create table bboard_category_subscribers (
+    category_id integer
+        constraint bboard_cs_category_id_fk
+            references bboard_categories (category_id)
+                on delete cascade,
+    subscriber_id integer
+        constraint bboard_cs_subscriber_id_fk
+            references parties (party_id)
+                on delete cascade,
+    constraint bboard_category_subscribers_pk
+        primary key (category_id, subscriber_id)
+);
+
+create index bboard_cs_subscriber_id_idx
+    on bboard_category_subscribers (subscriber_id);
+
+create table bboard_thread_subscribers (
+    thread_id integer
+        constraint bboard_ts_thread_id_fk
+            references acs_messages (message_id)
+                on delete cascade,
+    subscriber_id integer
+        constraint bboard_ts_subscriber_id_fk
+            references parties (party_id)
+                on delete cascade,
+    constraint bboard_thread_subscribers_pk
+        primary key (thread_id, subscriber_id)
+);
+
+create index bboard_ts_subscriber_id_idx
+    on bboard_thread_subscribers (subscriber_id);
+
+\i bboard-views.sql
+\i bboard-packages.sql
+
+insert into cr_mime_types (mime_type) 
+ values ('text/plain; format=flowed');
+
+
+-- -- NOTE: this is only temporary until we figure out how
+-- --       packages will register child types to an acs-message
+-- declare
+--     v_exists	integer;
+-- begin
+
+--     select decode(count(*),0,0,1) into v_exists 
+--       from cr_type_children
+--       where parent_type = 'acs_message_revision'
+--       and child_type = 'content_revision';
+
+--     if v_exists = 0 then
+--       content_type.register_child_type (
+--           parent_type => 'acs_message_revision',
+--           child_type  => 'content_revision'
+--       );
+--     end if;
+
+--     select decode(count(*),0,0,1) into v_exists 
+--       from cr_type_children
+--       where parent_type = 'acs_message_revision'
+--       and child_type = 'content_revision';
+
+--     if v_exists = 0 then
+--       content_type.register_child_type (
+--           parent_type => 'acs_message_revision',
+--           child_type  => 'image'
+--       );
+--     end if;
+
+--     select decode(count(*),0,0,1) into v_exists 
+--       from cr_type_children
+--       where parent_type = 'acs_message_revision'
+--       and child_type = 'content_revision';
+
+--     if v_exists = 0 then
+--       content_type.register_child_type (
+--           parent_type => 'acs_message_revision',
+--           child_type  => 'content_extlink'
+--       );
+--     end if;
+
+-- end;
+-- /
+-- show errors
Index: openacs-4/packages/sloan-bboard/sql/postgresql/bboard-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/postgresql/bboard-drop.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/postgresql/bboard-drop.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,140 @@
+--
+-- packages/message/sql/bboard-drop.sql
+--
+-- @author jmp@arsdigita.com
+-- @creation-date 2000-08-31
+-- @cvs-id $Id: bboard-drop.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+-- This drop script destroys all messages that belong to forums.
+-- It should handle any permission changes that have been done since
+-- install by removing any permissions having to do with the standard
+-- bboard permissions.
+
+-- We need to get rid of things that might be referring to
+-- bboard objects that would prevent removal.  This includes:
+-- email-a-friend droppings
+-- attachments (files and images)
+
+-- if something else is pointing at one of our messages, this script
+-- will fail and removing bboard will be icky.  this is sort of hairy
+-- problem with unknown potential intra-package references.
+
+
+create function inline_0 ()
+returns integer as '
+
+    raise NOTICE ''currently it is impossible to delete multiple threads within a transaction.  please ensure you have removed all forums through the admin interface before you try to drop the package.''
+
+' language 'plpgsql';
+
+select inline_0 ();
+drop function inline_0();
+
+
+-- Delete all subscriptions
+delete from bboard_thread_subscribers;
+delete from bboard_category_subscribers;
+delete from bboard_forum_subscribers;
+
+-- Delete all categories
+delete from bboard_category_message_map;
+delete from bboard_categories;
+delete from acs_objects where object_type = 'bboard_category';
+
+-- Delete all forums
+delete from bboard_forum_message_map;
+delete from bboard_forums;
+delete from acs_objects where object_type = 'bboard_forum';
+
+-- Drop all schema objects
+
+drop function bboard_forum__forum_p (integer);
+drop function bboard_forum__new (integer, varchar, varchar, char, integer,
+                            integer, timestamp, integer, varchar, varchar);
+drop function bboard_forum__delete (integer);
+drop function bboard_forum__set_attrs (integer, varchar, varchar, char, integer);
+drop function bboard_forum__subscribe (integer, integer);
+drop function bboard_forum__forum_containing_message (integer);
+drop function bboard_forum__name (integer);
+drop function bboard_category__category_p (integer);
+drop function bboard_category__new (integer, varchar, varchar, integer, 
+                               integer, timestamp, integer, varchar, varchar);
+drop function bboard_category__delete (integer);
+drop function bboard_category__set_attrs (integer, varchar, varchar, integer);
+drop function bboard_category__subscribe (integer, integer);
+drop function bboard_category__name (integer);
+drop function bboard_message__new (integer, integer, timestamp, integer,
+        varchar, varchar, varchar, varchar, text, 
+        integer, timestamp, integer, varchar, varchar);
+drop function bboard_message__message_p (integer);
+drop function bboard_message__set_attrs (integer, integer, timestamp,
+                                      integer, varchar, varchar, integer);
+drop function bboard_message__set_status (integer, integer, varchar);
+drop function bboard_message__add_category (integer, integer);
+drop function bboard_message__remove_category (integer, integer);
+drop function bboard_message__clear_categories (integer);
+drop function bboard_message__subscribe (integer, integer);
+drop function bboard_message__remove_thread (integer);
+drop function bboard_message__remove (integer);
+
+
+
+drop view bboard_messages_by_category;
+drop view bboard_messages_all;
+drop table bboard_thread_subscribers;
+drop table bboard_category_subscribers;
+drop table bboard_forum_subscribers;
+drop table bboard_category_message_map;
+drop table bboard_categories;
+drop table bboard_forum_message_map;
+drop table bboard_forums;
+
+-- Drop object type metadata
+begin;
+    select acs_object_type__drop_type ('bboard_forum', 'f');
+    select acs_object_type__drop_type ('bboard_category', 'f');
+end;
+
+
+-- Drop permission metadata
+delete from acs_permissions
+    where privilege in
+        ('bboard_create_forum', 'bboard_create_category',
+         'bboard_create_message', 'bboard_write_forum',
+         'bboard_write_category', 'bboard_write_message',
+         'bboard_read_forum', 'bboard_read_category',
+         'bboard_read_message', 'bboard_delete_forum',
+         'bboard_delete_category', 'bboard_delete_message',
+         'bboard_moderate_forum');
+
+delete from acs_privilege_hierarchy
+    where privilege in
+        ('bboard_create_forum', 'bboard_create_category',
+         'bboard_create_message', 'bboard_write_forum',
+         'bboard_write_category', 'bboard_write_message',
+         'bboard_read_forum', 'bboard_read_category',
+         'bboard_read_message', 'bboard_delete_forum',
+         'bboard_delete_category', 'bboard_delete_message',
+         'bboard_moderate_forum');
+
+delete from acs_privilege_hierarchy
+    where child_privilege in
+        ('bboard_create_forum', 'bboard_create_category',
+         'bboard_create_message', 'bboard_write_forum',
+         'bboard_write_category', 'bboard_write_message',
+         'bboard_read_forum', 'bboard_read_category',
+         'bboard_read_message', 'bboard_delete_forum',
+         'bboard_delete_category', 'bboard_delete_message',
+         'bboard_moderate_forum');
+
+delete from acs_privileges
+    where privilege in
+        ('bboard_create_forum', 'bboard_create_category',
+         'bboard_create_message', 'bboard_write_forum',
+         'bboard_write_category', 'bboard_write_message',
+         'bboard_read_forum', 'bboard_read_category',
+         'bboard_read_message', 'bboard_delete_forum',
+         'bboard_delete_category', 'bboard_delete_message',
+         'bboard_moderate_forum');
+
Index: openacs-4/packages/sloan-bboard/sql/postgresql/bboard-packages.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/postgresql/bboard-packages.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/postgresql/bboard-packages.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,569 @@
+--
+-- packages/bboard/sql/bboard-packages.sql
+--
+-- @author Anukul Kapoor <akk@arsdigita.com>
+-- @author John Prevost <jmp@arsdigita.com>
+-- @creation-date 2000-11-22
+-- @cvs-id $Id: bboard-packages.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+------------ bboard_forum package ---------------
+
+create function bboard_forum__forum_p (integer)
+returns char as '
+declare
+    p_forum_id alias for $1;
+    v_check_forum_id integer;
+begin
+    select count(forum_id) into v_check_forum_id
+        from bboard_forums
+        where forum_id = p_forum_id;
+    if v_check_forum_id = 1 then
+        return ''t'';
+    else
+        return ''f'';
+    end if;
+end;
+' language 'plpgsql';
+
+
+create function bboard_forum__new (integer, varchar, varchar, char, integer,
+                            integer, timestamp, integer, varchar, varchar)
+returns integer as '
+declare
+    p_forum_id      alias for $1;         -- default null
+    p_short_name    alias for $2;
+    p_charter       alias for $3;         -- default null
+    p_moderated_p   alias for $4;         -- default ''f''
+    p_bboard_id     alias for $5;
+    p_context_id    alias for $6;         -- default null
+    p_creation_date alias for $7;         -- default now()
+    p_creation_user alias for $8;         -- default null
+    p_creation_ip   alias for $9;         -- default null
+    p_object_type   alias for $10;        -- default ''bboard_forum''
+    v_context_id  integer;
+    v_forum_id    integer;
+begin
+    v_context_id := coalesce(p_context_id, p_bboard_id);
+    v_forum_id := acs_object__new (
+        p_forum_id,
+	p_object_type,
+	p_creation_date,
+	p_creation_user,
+	p_creation_ip,
+	v_context_id
+    );
+
+    insert into bboard_forums
+               (forum_id, short_name, charter, moderated_p, bboard_id)
+        values (v_forum_id, p_short_name, p_charter, p_moderated_p, p_bboard_id);
+    return v_forum_id;   
+end;
+' language 'plpgsql';
+
+
+create function bboard_forum__delete (integer)
+returns integer as '
+declare
+    p_forum_id alias for $1;
+begin
+    delete from bboard_forums
+        where forum_id = p_forum_id;
+    PERFORM acs_object__delete(p_forum_id);
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_forum__set_attrs (integer, varchar, varchar, char, integer)
+returns integer as '
+declare
+    p_forum_id         alias for $1;
+    p_short_name       alias for $2;  -- default null
+    p_charter          alias for $3;  -- default null
+    p_moderated_p      alias for $4;  -- default null
+    p_bboard_id        alias for $5;  -- default null
+    v_check_forum_id integer;
+begin
+    select count(forum_id) into v_check_forum_id
+        from bboard_forums
+        where forum_id = p_forum_id;
+    -- Not a forum.  Fail silently?
+    if v_check_forum_id <> 1 then
+        return -1;
+    end if;
+    if p_short_name is not null then
+        update bboard_forums set short_name = p_short_name
+            where forum_id = p_forum_id;
+    end if;
+        update bboard_forums set charter = p_charter
+            where forum_id = p_forum_id;
+    if p_moderated_p is not null then
+        update bboard_forums set moderated_p = p_moderated_p
+            where forum_id = p_forum_id;
+    end if;
+    if p_bboard_id is not null then
+        update bboard_forums set bboard_id = p_bboard_id
+            where forum_id = p_forum_id;
+        update acs_objects set context_id = p_bboard_id
+            where object_id = p_forum_id;
+    end if;
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_forum__subscribe (integer, integer)
+returns integer as '
+declare
+    p_forum_id      alias for $1;
+    p_subscriber_id alias for $2;
+begin
+    insert into bboard_forum_subscribers (forum_id, subscriber_id)
+        values (p_forum_id, p_subscriber_id);
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_forum__forum_containing_message (integer)
+returns integer as '
+declare
+    p_message_id    alias for $1;
+    v_forum_id      integer;
+begin
+    select max(forum_id) into v_forum_id
+      from bboard_forum_message_map
+     where message_id = p_message_id;
+
+    if v_forum_id is null then
+        return 0;
+    else
+        return v_forum_id;
+    end if;
+end;
+' language 'plpgsql';
+
+
+create function bboard_forum__name (integer)
+returns varchar as '
+declare
+    p_forum_id      alias for $1;
+    v_forum_name   varchar;
+begin
+    select short_name into v_forum_name
+        from bboard_forums
+	    where forum_id = p_forum_id;
+    return v_forum_name;
+end;
+' language 'plpgsql';
+
+
+---------- bboard_category package ---------------
+
+create function bboard_category__category_p (integer)
+returns char as '
+declare
+    p_category_id alias for $1;
+    v_check_category_id integer;
+begin
+    select count(category_id) into v_check_category_id
+        from bboard_categories
+        where category_id = p_category_id;
+    if v_check_category_id = 1 then
+        return ''t'';
+    else
+        return ''f'';
+    end if;
+end;
+' language 'plpgsql';
+
+
+create function bboard_category__new (integer, varchar, varchar, integer, 
+                               integer, timestamp, integer, varchar, varchar)
+returns integer as '
+declare
+    p_category_id   alias for $1;  -- default null
+    p_short_name    alias for $2;
+    p_description   alias for $3;  -- default null
+    p_forum_id      alias for $4;
+    p_context_id    alias for $5;  -- default null
+    p_creation_date alias for $6;  -- default now()
+    p_creation_user alias for $7;  -- default null
+    p_creation_ip   alias for $8;  -- default null
+    p_object_type   alias for $9;  -- default ''bboard_category''
+    v_category_id   integer;
+    v_context_id    integer;
+begin
+    v_context_id := coalesce(p_context_id, p_forum_id);
+    v_category_id := acs_object__new (
+        p_category_id,
+        p_object_type,
+        p_creation_date,
+        p_creation_user,
+        p_creation_ip,
+        v_context_id
+    );
+
+    insert into bboard_categories
+           (category_id, short_name, description, forum_id)
+    values (v_category_id, p_short_name, p_description, p_forum_id);
+
+    return v_category_id;    
+end;
+' language 'plpgsql';
+
+
+create function bboard_category__delete (integer)
+returns integer as '
+declare
+    p_category_id alias for $1;
+begin
+    delete from bboard_categories
+        where category_id = p_category_id;
+    PERFORM acs_object__delete(p_category_id);
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_category__set_attrs (integer, varchar, varchar, integer)
+returns integer as '
+declare
+    p_category_id         alias for $1;
+    p_short_name          alias for $2;  -- default null
+    p_description         alias for $3;  -- default null
+    p_forum_id            alias for $4;  -- default null
+    v_check_category_id integer;
+begin
+    select count(category_id) into v_check_category_id
+        from bboard_categories
+        where category_id = p_category_id;
+    -- Not a category.  Fail silently?
+    if v_check_category_id <> 1 then
+        return -1;
+    end if;
+    -- It is a category.  Go for it.
+    if p_short_name is not null then
+        update bboard_categories set short_name = p_short_name
+            where category_id = p_category_id;
+    end if;
+    if p_description is not null then
+        update bboard_categories set description = p_description
+            where category_id = p_category_id;
+    end if;
+    if p_forum_id is not null then
+        update bboard_categories set forum_id = p_forum_id
+            where category_id = p_category_id;
+        update acs_objects set context_id = p_forum_id
+            where object_id = p_category_id;
+    end if;
+    return 0;
+end;
+' language 'plpgsql';
+
+create function bboard_category__subscribe (integer, integer)
+returns integer as '
+declare
+    p_category_id   alias for $1;
+    p_subscriber_id alias for $2;
+begin
+    insert into bboard_category_subscribers (category_id, subscriber_id)
+        values (p_category_id, p_subscriber_id);
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_category__name (integer)
+returns varchar as '
+declare
+    category_id      alias for $1;
+    v_category_name   varchar;
+begin
+    select short_name into v_category_name
+        from bboard_categories
+	    where category_id = name.category_id;
+    return v_category_name;
+end;
+' language 'plpgsql';
+
+
+--------------- bboard_message package ----------------
+
+create function bboard_message__new (integer, integer, timestamp, integer,
+        varchar, varchar, varchar, varchar, text, 
+        integer, timestamp, integer, varchar, varchar)
+returns integer as '
+declare
+    p_message_id    alias for $1;   -- default null
+    p_reply_to      alias for $2;   -- default null
+    p_sent_date     alias for $3;   -- default sysdate
+    p_sender        alias for $4;   -- default null
+    p_rfc822_id     alias for $5;   -- default null
+    p_title         alias for $6;   -- default null
+    p_mime_type     alias for $7;   -- default ''text/plain''
+    p_text          alias for $8;   -- default null
+    p_data          alias for $9;   -- default null
+    p_context_id    alias for $10;  -- default 0
+    p_creation_date alias for $11;  -- default sysdate
+    p_creation_user alias for $12;  -- default null
+    p_creation_ip   alias for $13;  -- default null
+    p_object_type   alias for $14;  -- default ''acs_message''
+    v_sent_date   timestamp;
+begin
+    v_sent_date := coalesce(p_sent_date, now());
+
+    return acs_message__new (
+        p_message_id,
+        p_reply_to,
+        v_sent_date,
+        p_sender,
+        p_rfc822_id,
+        p_title,
+        null,
+        p_mime_type,
+        p_text,
+        p_data,
+        0,
+        p_context_id,
+        p_creation_user,
+        p_creation_ip,
+        p_object_type,
+        ''t''
+    );
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_message__message_p (integer)
+returns char as '
+declare
+    p_message_id alias for $1;
+    v_check_message_id integer;
+begin
+    select count(message_id) into v_check_message_id
+        from acs_messages
+        where message_id = p_message_id;
+    if v_check_message_id = 1 then
+        return ''t'';
+    else
+        return ''f'';
+    end if;
+end;
+' language 'plpgsql';
+
+
+create function bboard_message__set_attrs (integer, integer, timestamp,
+                                           integer, varchar, varchar, integer)
+returns integer as '
+declare
+    p_message_id         alias for $1;
+    p_reply_to           alias for $2; -- default null
+    p_sent_date          alias for $3; -- default null
+    p_sender             alias for $4; -- default null
+    p_title              alias for $5; -- default null
+    p_mime_type          alias for $6; -- default null
+    p_context_id         alias for $7; -- default null
+    v_check_message_id   integer;
+    v_revision_id        integer;
+begin
+    if bboard_message__message_p(p_message_id) = ''f'' then
+        return -1;
+    end if;
+
+    -- modify the parts that are in acs_messages
+
+    if p_reply_to is not null then
+        update acs_messages set reply_to = p_reply_to
+            where message_id = p_message_id;
+    end if;
+    if p_sent_date is not null then
+        update acs_messages set sent_date = p_sent_date
+            where message_id = p_message_id;
+    end if;
+    if p_sender is not null then
+        update acs_messages set sender = p_sender
+            where message_id = p_message_id;
+    end if;
+
+    -- modify the parts that are in cr_revisions
+    if p_title is not null or p_mime_type is not null then
+        select live_revision into v_revision_id
+            from cr_items where item_id = p_message_id
+            for update;
+        if p_title is not null then
+            update cr_revisions set title = p_title
+                where revision_id = v_revision_id;
+        end if;
+        if p_mime_type is not null then
+            update cr_revisions set mime_type = p_mime_type
+                where revision_id = v_revision_id;
+        end if;
+    end if;
+
+    -- modify the context_id in acs_objects
+
+    if p_context_id is not null then
+        update acs_objects set context_id = p_context_id
+            where object_id = p_message_id;
+    end if;
+
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_message__set_status (integer, integer, varchar)
+returns integer as '
+declare
+    p_message_id alias for $1;
+    p_forum_id   alias for $2;
+    p_status     alias for $3;
+begin
+    if bboard_message__message_p(p_message_id) = ''f''
+            or bboard_forum__forum_p(p_forum_id) = ''f'' then
+        return -1;
+    end if;
+    delete from bboard_forum_message_map
+        where message_id = p_message_id
+            and forum_id = p_forum_id;
+    if p_status is not null then
+        insert into bboard_forum_message_map (forum_id, message_id, status)
+        values (p_forum_id, p_message_id, p_status);
+    end if;
+
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_message__add_category (integer, integer)
+returns integer as '
+declare
+    p_message_id  alias for $1;
+    p_category_id alias for $2;
+begin
+    insert into bboard_category_message_map (message_id, category_id)
+        values (p_message_id, p_category_id);
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_message__remove_category (integer, integer)
+returns integer as '
+declare
+    p_message_id  alias for $1;
+    p_category_id alias for $2;
+begin
+    delete from bboard_category_message_map
+     where category_id = p_category_id
+       and message_id = p_message_id;
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_message__clear_categories (integer)
+returns integer as '
+declare
+    p_message_id alias for $1;
+begin
+    delete from bboard_category_message_map
+     where message_id = p_message_id;
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_message__subscribe (integer, integer)
+returns integer as '
+declare
+    p_thread_id     alias for $1;
+    p_subscriber_id alias for $2;
+begin
+    insert into bboard_thread_subscribers (thread_id, subscriber_id)
+    values (p_thread_id, p_subscriber_id);
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_message__remove_thread (integer)
+returns integer as '
+declare
+    thread_id    alias for $1;
+    child_val record;
+    message_val record;
+    image_p integer;
+    v_search_key varbit;
+begin
+    select tree_sortkey into v_search_key
+      from acs_messages
+     where message_id = thread_id;
+
+    for child_val in 
+        select object_id as child_id, object_type
+          from acs_objects o, acs_messages m
+         where o.context_id = m.message_id 
+           and m.tree_sortkey between v_search_key and tree_right(v_search_key)
+    loop
+        if child_val.object_type = ''acs_message'' then
+           perform acs_message__delete(child_val.child_id);
+        elsif child_val.object_type = ''content_item'' then
+            select count(*) into image_p
+	      from images
+             where image_id = child_val.child_id;
+            if image_p = 1 then
+                perform acs_message__delete_image(child_val.child_id);
+            else
+                perform acs_message__delete_file(child_val.child_id);
+            end if;
+       end if;
+    end loop;
+
+    for message_val in 
+        select message_id
+	  from acs_messages
+         where tree_sortkey between v_search_key and tree_right(v_search_key)
+    loop
+        perform acs_message__delete(message_val.message_id);
+    end loop;
+
+    return 0;
+end;
+' language 'plpgsql';
+
+
+create function bboard_message__remove (integer)
+returns integer as '
+declare
+    message_id alias for $1;
+    child_val record;
+    image_p integer;
+begin
+    for child_val in 
+        select object_id as child_id, object_type
+	  from acs_objects
+         where context_id = message_id
+    loop
+	if child_val.object_type = ''acs_message'' then
+	   perform acs_message__delete(child_val.child_id);
+	elsif child_val.object_type = ''content_item'' then
+	    select count(*) into image_p
+	      from images
+                where image_id = child_val.child_id;
+            if image_p = 1 then
+                perform acs_message__delete_image(child_val.child_id);
+            else
+                perform acs_message__delete_file(child_val.child_id);
+            end if;
+       end if;
+   end loop;
+
+   perform acs_message__delete(message_id);
+   return 0;
+end;
+' language 'plpgsql';
Index: openacs-4/packages/sloan-bboard/sql/postgresql/bboard-views.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/sql/postgresql/bboard-views.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/sql/postgresql/bboard-views.sql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,37 @@
+--
+-- packages/bboard/sql/bboard-views.sql
+--
+-- @author Anukul Kapoor <akk@arsdigita.com>
+-- @author John Prevost <jmp@arsdigita.com>
+-- @creation-date 2001-02-05
+-- @cvs-id $Id: bboard-views.sql,v 1.1 2002/02/15 21:27:06 ben Exp $
+--
+
+-- DRB: This view is several orders of magnitude faster than the old one
+-- using "in".  It would be nice to avoid having two aggregate subselects
+-- but there's no easy way to to do this.  
+
+-- Also ... Postgres does seem to optimize away the two subselects that
+-- calculate the number of replies and last reply date if the query 
+-- using the view doesn't include those columns in its resultset.  So 
+-- at the moment it does not appear necessary to create simpler views
+-- with those stripped out.
+
+create view bboard_messages_all as
+    select m.message_id, m.reply_to, m.sent_date, m.sender,
+           m.title, m.mime_type, m.content, f.forum_id, f.status,
+           (select count(1) from acs_messages m2, bboard_forum_message_map mf
+            where m2.message_id = mf.message_id 
+              and m2.tree_sortkey between m.tree_sortkey and tree_right(m.tree_sortkey))
+           as num_replies,
+           (select max(sent_date) from acs_messages m2, bboard_forum_message_map mf
+            where m2.message_id = mf.message_id 
+              and m2.tree_sortkey between m.tree_sortkey and tree_right(m.tree_sortkey))
+              as last_reply_date
+    from acs_messages_all m, bboard_forum_message_map f
+    where m.message_id = f.message_id;
+
+create view bboard_messages_by_category as
+    select msg.*, cat.category_id
+    from bboard_messages_all msg left join bboard_category_message_map cat on (msg.message_id = cat.message_id);
+
Index: openacs-4/packages/sloan-bboard/tcl/bboard-init.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/tcl/bboard-init.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/tcl/bboard-init.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,11 @@
+ad_library {
+
+    bboard init - sets up scheduled procs
+
+    @cvs-id $Id: bboard-init.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+    @author Anukul Kapoor <akk@arsdigita.com>
+    @date 2001-02-13
+
+}
+
+ad_schedule_proc -thread t 86400 bboard_garbage_collect
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/tcl/bboard-procs-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/tcl/bboard-procs-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/tcl/bboard-procs-oracle.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,495 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="bboard_forum_p.bboard_forum_p">      
+      <querytext>
+      
+        begin
+            :1 := bboard_forum.forum_p(:forum_id);
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_forum_new.create_forum">      
+      <querytext>
+      
+        begin
+            :1 := bboard_forum.new (
+                forum_id => :forum_id,
+                short_name => :short_name,
+                charter => :charter,
+                moderated_p => :moderated_p,
+                bboard_id => :bboard_id,
+                context_id => :context_id,
+                creation_user => :creation_user,
+                creation_ip => :creation_ip
+            );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_forum_set.update_forum">      
+      <querytext>
+      
+        begin
+            bboard_forum.set_attrs (
+                forum_id => :forum_id,
+                short_name => :short_name,
+                charter => :charter,
+                moderated_p => :moderated_p,
+                bboard_id => :bboard_id
+            );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_category_p.bboard_category_p">      
+      <querytext>
+      
+        begin
+            :1 := bboard_category.category_p(:category_id);
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_category_new.create_category">      
+      <querytext>
+      
+	begin
+	    :1 := bboard_category.new (
+	        category_id => :category_id,
+	        short_name => :short_name,
+	        description => :description,
+	        forum_id => :forum_id
+	    );
+	end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_category_set.update_category">      
+      <querytext>
+      
+        begin
+            bboard_category.set_attrs (
+                category_id => :category_id,
+                short_name => :short_name,
+                description => :description,
+                forum_id => :forum_id
+            );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_new.message_new">      
+      <querytext>
+      
+        begin
+            :1 := bboard_message.new (
+                message_id => :message_id,
+                reply_to => :reply_to,
+                sent_date => :sent_date,
+                sender => :sender,
+                title => :title,
+                mime_type => :mime_type,
+                data => empty_blob(),
+                context_id => :context_id,
+                creation_user => :creation_user,
+                creation_ip => :creation_ip
+            );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_new.message_new_set_blob">      
+      <querytext>
+      
+        update cr_revisions
+            set content = empty_blob()
+            where revision_id = :revision_id
+        returning content into :1
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_set.message_set_attr">      
+      <querytext>
+      
+        begin
+            bboard_message.set_attrs (
+                message_id => :message_id,
+                reply_to => :reply_to,
+                sent_date => :sent_date,
+                sender => :sender,
+                title => :title,
+                mime_type => :mime_type,
+                context_id => :context_id
+            );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_set.message_set_content">      
+      <querytext>
+      
+        update cr_revisions
+            set content = empty_blob()
+            where revision_id = :revision_id
+        returning content into :1
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_clear_categories.bboard_message_clear_categories">      
+      <querytext>
+      
+        begin
+            bboard_message.clear_categories ( :message_id );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_add_category.bboard_message_add_category">      
+      <querytext>
+      
+        begin
+            bboard_message.add_category (
+                message_id => :message_id,
+                category_id => :category_id
+            );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_remove_category.bboard_message_remove_category">      
+      <querytext>
+      
+        begin
+            bboard_message.remove_category (
+                message_id => :message_id,
+                category_id => :category_id
+            );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_set_status.bboard_message_set_status">      
+      <querytext>
+      
+        begin
+            bboard_message.set_status (
+                message_id => :message_id,
+                forum_id => :forum_id,
+                status => :status
+            );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_subscribe_forum.forum_subscribe">      
+      <querytext>
+      
+        begin
+            bboard_forum.subscribe (
+                forum_id => :forum_id,
+                subscriber_id => :subscriber_id
+            );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_subscribe_category.category_subscribe">      
+      <querytext>
+      
+        begin
+            bboard_category.subscribe (
+                category_id => :category_id,
+                subscriber_id => :subscriber_id
+            );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_subscribe_thread.thread_subscribe">      
+      <querytext>
+      
+        begin
+            bboard_message.subscribe (
+                thread_id => :thread_id,
+                subscriber_id => :subscriber_id
+            );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_subscribed_p.check_message_subscribed">      
+      <querytext>
+      
+	select count(*) as subscribed_p from bboard_thread_subscribers
+	where subscriber_id = :user_id
+	      and thread_id in (select message_id
+	                        from acs_messages b
+	                        connect by b.message_id = prior b.reply_to 
+	                        start with message_id = :message_id)
+
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_forum.bboard_forum_containing_message">      
+      <querytext>
+      
+	select bboard_forum.forum_containing_message(:message_id) as forum_id
+	  from dual
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_url.first_ancestor">      
+      <querytext>
+      
+	select acs_message.first_ancestor(:message_id) as ancestor_id 
+            from dual
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_attach_image.insert_image">      
+      <querytext>
+      
+             begin
+                :1 := acs_message.new_image (
+                    message_id     => :message_id,
+                    image_id       => :file_id,
+                    file_name      => :short_filename,
+                    title          => :title,
+                    mime_type      => :mime_type,
+                    content        => empty_blob(),
+                    width          => :width,
+                    height         => :height,
+                    creation_user  => :user_id,
+                    creation_ip    => :creation_ip,
+                    is_live        => 't'
+            );
+            end;
+        
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_attach_image.get_revision">      
+      <querytext>
+      
+        select content_item.get_latest_revision(:file_id) as revision_id
+        from dual
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_attach_image.set_content_size">      
+      <querytext>
+      
+	update cr_revisions
+ 	set filename = :filename,
+	    content_length = :size
+	where revision_id = :revision_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_attach_file.insert_file">      
+      <querytext>
+      
+            begin
+                :1 := acs_message.new_file (
+                    message_id     => :message_id,
+                    file_id        => :file_id,
+                    file_name      => :short_filename,
+                    title          => :title,
+                    mime_type      => :mime_type,
+                    content        => empty_blob(),
+                    creation_user  => :user_id,
+                    creation_ip    => :creation_ip,
+                    is_live        => 't'
+            );
+            end;
+        
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_attach_file.get_revision">      
+      <querytext>
+      
+        select content_item.get_latest_revision(:file_id) as revision_id
+        from dual
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_attach_file.set_content_size">      
+      <querytext>
+      
+	update cr_revisions
+ 	set filename = :filename,
+	    content_length = :size
+	where revision_id = :revision_id
+      
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_delete_attachment.is_file_image">      
+      <querytext>
+      
+	select image_id
+            from images
+            where image_id = content_item.get_latest_revision(:file_id)
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_delete_attachment.delete_image">      
+      <querytext>
+      
+	    begin
+	        acs_message.delete_image(:file_id);
+	    end;
+	
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_delete_attachment.delete_file">      
+      <querytext>
+      
+	    begin
+   	        acs_message.delete_file(:file_id);
+	    end;
+	
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_garbage_collect.clear_revision_references">      
+      <querytext>
+
+update cr_items 
+   set latest_revision=null, live_revision=null
+ where item_id = -1;
+
+      </querytext>
+</fullquery>
+
+<fullquery name="bboard_garbage_collect.bboard_alert_clean">      
+      <querytext>
+      
+	declare
+	    cursor alerts_cursor is
+ 
+ 	    select object_id
+ 	         from acs_objects
+ 	         where object_id in (select object_id
+                                       from acs_objects
+                                      where object_type = 'acs_message'
+                  	              start with context_id in (select forum_id
+                                                                  from bboard_forums)
+ 	                              connect by prior object_id = context_id)
+ 	               and object_id not in (select message_id
+ 	                                       from bboard_forum_message_map)
+             order by object_id desc;
+	begin
+  	    for alert_val in alerts_cursor loop
+	        bboard_message.remove(alert_val.object_id);
+	    end loop;
+	end;
+    
+      </querytext>
+</fullquery>
+
+<partialquery name="bboard_schedule_sends.thread_subscribers">      
+  <querytext>
+        select subscriber_id as recipient_id, thread_id as grouping_id,
+               sysdate as wait_until
+          from bboard_thread_subscribers s
+          where s.thread_id in (select message_id 
+                                  from acs_messages
+                                 start with message_id = :message_id
+                               connect by message_id = prior reply_to)
+            and s.subscriber_id in (select party_id 
+                                      from all_object_party_privilege_map 
+                                     where object_id = :message_id 
+                                       and privilege = 'bboard_read_message')
+  </querytext>
+</partialquery>
+ 
+<partialquery name="bboard_schedule_sends.category_subscribers">      
+  <querytext>
+	select s.subscriber_id as recipient_id, s.category_id as grouping_id,
+	       sysdate as wait_until
+	  from bboard_category_subscribers s, bboard_category_message_map m
+	  where m.message_id = :message_id
+	    and s.category_id = m.category_id
+            and s.subscriber_id in (select party_id 
+                                      from acs_object_party_privilege_map 
+                                     where object_id = :message_id 
+                                       and privilege = 'bboard_read_message')
+  </querytext>
+</partialquery>
+
+
+<partialquery name="bboard_schedule_sends.forum_subscribers">      
+  <querytext>
+        select s.subscriber_id as recipient_id, s.forum_id as grouping_id,
+               sysdate as wait_until
+            from bboard_forum_subscribers s, bboard_forum_message_map m
+            where m.message_id = :message_id
+              and s.forum_id = m.forum_id
+              and s.subscriber_id in (select party_id 
+                                        from acs_object_party_privilege_map 
+                                       where object_id = :message_id 
+                                         and privilege = 'bboard_read_message')
+  </querytext>
+</partialquery>
+</queryset>
+
Index: openacs-4/packages/sloan-bboard/tcl/bboard-procs-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/tcl/bboard-procs-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/tcl/bboard-procs-postgresql.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,460 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="bboard_forum_p.bboard_forum_p">      
+      <querytext>
+            select bboard_forum__forum_p(:forum_id);
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_forum_new.create_forum">      
+      <querytext>
+            select bboard_forum__new (
+                :forum_id,
+                :short_name,
+                :charter,
+                :moderated_p,
+                :bboard_id,
+                :context_id,
+                now(),
+                :creation_user,
+                :creation_ip,
+                'bboard_forum'
+            );
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_forum_set.update_forum">      
+      <querytext>
+         select bboard_forum__set_attrs (
+                :forum_id,
+                :short_name,
+                :charter,
+                :moderated_p,
+                :bboard_id
+            );
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_category_p.bboard_category_p">      
+      <querytext>
+        select bboard_category__category_p(:category_id);
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_category_new.create_category">      
+      <querytext>
+	    select bboard_category__new (
+	        :category_id,
+	        :short_name,
+	        :description,
+	        :forum_id,
+                null,
+                now(),
+                null,
+                null,
+                'bboard_category'
+	    );
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_category_set.update_category">      
+      <querytext>
+            select bboard_category__set_attrs (
+                :category_id,
+                :short_name,
+                :description,
+                :forum_id
+            );
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_new.message_new">      
+      <querytext>
+            select bboard_message__new (
+                :message_id,
+                :reply_to,
+                :sent_date,
+                :sender,
+                null,          -- rfc822_id
+                :title,
+                :mime_type,
+                null,          -- text
+	        null,          -- data
+                :context_id,
+                now(),
+                :creation_user,
+                :creation_ip,
+                'acs_message'
+            );
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_new.message_new_set_blob">      
+      <querytext>
+
+        update cr_revisions
+            set content = :content
+            where revision_id = :revision_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_set.message_set_attr">      
+      <querytext>
+
+          select bboard_message__set_attrs (
+                :message_id,
+                :reply_to,
+                :sent_date,
+                :sender,
+                :title,
+                :mime_type,
+                :context_id
+            );
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_set.message_set_content">      
+      <querytext>
+	update cr_revisions
+ 	set content = '$content'
+        where revision_id = :revision_id
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_clear_categories.bboard_message_clear_categories">      
+      <querytext>
+
+          select bboard_message__clear_categories ( :message_id );
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_add_category.bboard_message_add_category">      
+      <querytext>
+
+        select bboard_message__add_category (
+                :message_id,
+                :category_id
+            );
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_remove_category.bboard_message_remove_category">      
+      <querytext>
+
+            select bboard_message__remove_category (
+                :message_id,
+                :category_id
+            );
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_set_status.bboard_message_set_status">      
+      <querytext>
+
+            select bboard_message__set_status (
+                :message_id,
+                :forum_id,
+                :status
+            );
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_subscribe_forum.forum_subscribe">      
+      <querytext>
+
+            select bboard_forum__subscribe (
+                :forum_id,
+                :subscriber_id
+            );
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_subscribe_category.category_subscribe">      
+      <querytext>
+
+            select bboard_category__subscribe (
+                :category_id,
+                :subscriber_id
+            );
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_subscribe_thread.thread_subscribe">      
+      <querytext>
+
+            select bboard_message__subscribe (
+                :thread_id,
+                :subscriber_id
+            );
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_subscribed_p.check_message_subscribed">      
+      <querytext>
+
+	select count(*) as subscribed_p
+         from bboard_thread_subscribers bs, acs_messages m, acs_messages m2
+	 where bs.subscriber_id = :user_id
+	   and bs.thread_id = m.message_id 
+           and m2.message_id = :message_id
+           and m.tree_sortkey between m2.tree_sortkey and tree_right(m2.tree_sortkey)
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_forum.bboard_forum_containing_message">      
+      <querytext>
+      
+	select bboard_forum__forum_containing_message(:message_id) as forum_id
+	  
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_url.first_ancestor">      
+      <querytext>
+      
+	select acs_message__first_ancestor(:message_id) as ancestor_id 
+            
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_attach_image.insert_image">      
+      <querytext>
+
+                select acs_message__new_image (
+                    :message_id,
+                    :file_id,
+                    :short_filename,
+                    :title,
+                    null,       -- description
+                    :mime_type,
+                    null,       -- data
+                    :width,
+                    :height,
+                    now(),
+                    :user_id,
+                    :creation_ip,
+                    't',        -- is_live
+                    'file'
+                );
+        
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_attach_image.get_revision">      
+      <querytext>
+      
+        select content_item__get_latest_revision(:file_id) as revision_id
+        
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_attach_image.set_content_size">      
+      <querytext>
+	update cr_revisions
+ 	set content = :filename,
+	    content_length = :size
+        where revision_id = :revision_id
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_attach_file.insert_file">      
+      <querytext>
+                select acs_message__new_file (
+                    :message_id,
+                    :file_id,
+                    :short_filename,
+                    :title,
+                    null,           -- description
+                    :mime_type,
+                    null,           -- content
+                    now(),
+                    :user_id,
+                    :creation_ip,
+                    't',             -- is_live
+                    'file'
+                );
+        
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_attach_file.get_revision">      
+      <querytext>
+      
+        select content_item__get_latest_revision(:file_id) as revision_id
+        
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_attach_file.set_content_size">      
+      <querytext>
+	update cr_revisions
+ 	set content = :filename,
+	    content_length = :size
+        where revision_id = :revision_id
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_delete_attachment.is_file_image">      
+      <querytext>
+      
+	select image_id
+            from images
+            where image_id = content_item__get_latest_revision(:file_id)
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_delete_attachment.delete_image">      
+      <querytext>
+
+	    select acs_message__delete_image(:file_id);
+	
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_delete_attachment.delete_file">      
+      <querytext>
+
+   	    select acs_message__delete_file(:file_id);
+	
+      </querytext>
+</fullquery>
+
+ 
+ 
+<fullquery name="bboard_garbage_collect.clear_revision_references">      
+      <querytext>
+
+update cr_items
+   set latest_revision=null, live_revision=null
+ where item_id in 
+       (select object_id as message_id
+          from acs_objects
+         where object_type = 'acs_message'
+           and object_id not in (select message_id 
+                                 from bboard_forum_message_map));
+    
+      </querytext>
+</fullquery>
+
+<fullquery name="bboard_garbage_collect.bboard_alert_clean">      
+      <querytext>
+
+declare
+    message_rec record;
+begin
+    for message_rec in
+        select o.object_id as message_id
+          from acs_objects o
+         where o.object_type = 'acs_message'
+            and not exists (select 1
+                            from bboard_forum_message_map bfmm, acs_objects o2
+                            where o2.object_id = bfmm.message_id and
+                              o.tree_sortkey between o2.tree_sortkey and tree_right(o2.tree_sortkey))
+    loop
+        perform bboard_message__remove(message_rec.message_id);
+    end loop;
+
+    return 0;
+end;
+    
+      </querytext>
+</fullquery>
+
+
+<partialquery name="bboard_schedule_sends.thread_subscribers">      
+  <querytext>
+        select s.subscriber_id as recipient_id, s.thread_id as grouping_id,
+               now() as wait_until
+          from bboard_thread_subscribers s, acs_messages m,
+            (select tree_ancestor_keys(acs_message_get_tree_sortkey(:message_id)) as tree_sortkey) parents
+         where s.thread_id = m.message_id
+           and m.tree_sortkey = parents.tree_sortkey
+           and exists (select 1
+                       from all_object_party_privilege_map map
+                       where map.object_id = :message_id and
+                           map.party_id = s.subscriber_id and
+                           privilege = 'bboard_read_message')
+
+  </querytext>
+</partialquery>
+ 
+<partialquery name="bboard_schedule_sends.category_subscribers">      
+  <querytext>
+  
+	select s.subscriber_id as recipient_id, s.category_id as grouping_id,
+	       now() as wait_until
+	  from bboard_category_subscribers s, bboard_category_message_map m
+	  where m.message_id = :message_id
+	    and s.category_id = m.category_id
+            and exists (select 1
+                        from all_object_party_privilege_map map
+                        where map.object_id = :message_id and
+                            map.party_id = s.subscriber_id and
+                            privilege = 'bboard_read_message')
+
+  </querytext>
+</partialquery>
+
+
+<partialquery name="bboard_schedule_sends.forum_subscribers">      
+  <querytext>
+        select s.subscriber_id as recipient_id, s.forum_id as grouping_id,
+               now() as wait_until
+            from bboard_forum_subscribers s, bboard_forum_message_map m
+            where m.message_id = :message_id
+              and s.forum_id = m.forum_id
+              and exists (select 1
+                          from all_object_party_privilege_map map
+                          where map.object_id = :message_id and
+                              map.party_id = s.subscriber_id and
+                              privilege = 'bboard_read_message')
+  </querytext>
+</partialquery>
+
+</queryset>
Index: openacs-4/packages/sloan-bboard/tcl/bboard-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/tcl/bboard-procs.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/tcl/bboard-procs.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,1040 @@
+ad_library {
+
+    Provides functions for creating and updating bboard messages, forums,
+    and categories.  Also provides functions for constructing queries
+    for bboard messages.
+
+    @creation-date 2000-10-21
+    @author John Prevost <jmp@arsdigita.com>
+    @cvs-id $Id: bboard-procs.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+
+}
+
+ad_proc -public bboard_forum_p {
+    {forum_id}
+} {
+    Check if an integer is a valid bboard forum id.
+} {
+    return [string equal [db_exec_plsql bboard_forum_p {
+        begin
+            :1 := bboard_forum.forum_p(:forum_id);
+        end;
+    }] "t"]
+}
+
+ad_page_contract_filter bboard_forum_id { name value } {
+    Checks whether the value (assumed to be an integer) is the id of
+    an already-existing bboard forum.
+} {
+    # empty is okay (handled by notnull)
+    if [empty_string_p $value] {
+	return 1
+    }
+    if ![bboard_forum_p $value] {
+	ad_complain "$name ($value) does not refer to a valid bboard forum"
+	return 0
+    }
+    return 1
+}
+
+ad_proc -public bboard_forum_new {
+    {-forum_id ""}
+    {-short_name:required}
+    {-charter ""}
+    {-moderated_p f}
+    {-bboard_id:required}
+    {-context_id ""}
+    {-creation_user ""}
+    {-creation_ip ""}
+} {
+    Create a new forum.
+} {
+    return [db_exec_plsql create_forum {
+        begin
+            :1 := bboard_forum.new (
+                forum_id => :forum_id,
+                short_name => :short_name,
+                charter => :charter,
+                moderated_p => :moderated_p,
+                bboard_id => :bboard_id,
+                context_id => :context_id,
+                creation_user => :creation_user,
+                creation_ip => :creation_ip
+            );
+        end;
+    }]
+}
+
+ad_proc -public bboard_forum_set {
+    {-forum_id:required}
+    {-short_name ""}
+    {-charter ""}
+    {-moderated_p ""}
+    {-bboard_id ""}
+} {
+    Modify some or all of a forum's attributes.
+} {
+    db_exec_plsql update_forum {
+        begin
+            bboard_forum.set_attrs (
+                forum_id => :forum_id,
+                short_name => :short_name,
+                charter => :charter,
+                moderated_p => :moderated_p,
+                bboard_id => :bboard_id
+            );
+        end;
+    }
+}
+
+ad_proc -public bboard_forum_get {
+    {-forum_id:required}
+    {-column_array:required}
+} {
+    Get the columns for a given forum into an array variable.
+} {
+    upvar $rowvar row
+    db_1row forum_get {
+        select * from bboard_forums where forum_id = :forum_id
+    } -column_array row
+}
+
+ad_proc -public bboard_category_p {
+    {category_id}
+} {
+    Check if an integer is a valid bboard category id.
+} {
+    return [string equal [db_exec_plsql bboard_category_p {
+        begin
+            :1 := bboard_category.category_p(:category_id);
+        end;
+    }] "t"]
+}
+
+ad_page_contract_filter bboard_category_id { name value } {
+    Checks whether the value (assumed to be an integer) is the id of
+    an already-existing bboard category.
+} {
+    # empty is okay (handled by notnull)
+    if [empty_string_p $value] {
+	return 1
+    }
+    if ![bboard_category_p $value] {
+	ad_complain "$name ($value) does not refer to a valid bboard category"
+	return 0
+    }
+    return 1
+}
+
+ad_proc -public bboard_category_new {
+    {-category_id ""}
+    {-short_name:required}
+    {-description ""}
+    {-forum_id:required}
+} {
+    Create a new category.
+} {
+    return [db_exec_plsql create_category {
+	begin
+	    :1 := bboard_category.new (
+	        category_id => :category_id,
+	        short_name => :short_name,
+	        description => :description,
+	        forum_id => :forum_id
+	    );
+	end;
+    }]
+}
+
+ad_proc -public bboard_category_set {
+    {-category_id:required}
+    {-short_name ""}
+    {-description ""}
+    {-forum_id ""}
+} {
+    Modify some or all of a category's attributes.
+} {
+    db_exec_plsql update_category {
+        begin
+            bboard_category.set_attrs (
+                category_id => :category_id,
+                short_name => :short_name,
+                description => :description,
+                forum_id => :forum_id
+            );
+        end;
+    }
+}
+
+ad_proc -public bboard_category_get {
+    {-category_id:required}
+    {-column_array:required}
+} {
+    Get the columns for a given category into an array variable.
+} {
+    upvar $rowvar row
+    db_1row category_get {
+        select * from bboard_categories where category_id = :category_id
+    } -column_array row
+}
+
+ad_proc -public bboard_message_new {
+    {-message_id ""}
+    {-reply_to ""}
+    {-sent_date ""}
+    {-sender ""}
+    {-title ""}
+    {-mime_type ""}
+    {-content ""}
+    {-context_id ""}
+    {-creation_user ""}
+    {-creation_ip ""}
+} {
+    Create a new message.
+} {
+    set result [db_exec_plsql message_new {
+        begin
+            :1 := bboard_message.new (
+                message_id => :message_id,
+                reply_to => :reply_to,
+                sent_date => :sent_date,
+                sender => :sender,
+                title => :title,
+                mime_type => :mime_type,
+                data => empty_blob(),
+                context_id => :context_id,
+                creation_user => :creation_user,
+                creation_ip => :creation_ip
+            );
+        end;
+    }]
+
+
+    if [string equal $message_id ""] {
+	set message_id $result
+    }
+
+    db_1row message_new_revision {
+        select live_revision as revision_id
+            from cr_items
+            where item_id = :message_id
+        for update
+    }
+
+    db_dml message_new_set_blob {
+        update cr_revisions
+            set content = empty_blob()
+            where revision_id = :revision_id
+        returning content into :1
+    } -blobs [list $content]
+
+    return $result
+}
+
+ad_proc -public bboard_message_set {
+    {-message_id:required}
+    {-reply_to ""}
+    {-sent_date ""}
+    {-sender ""}
+    {-title ""}
+    {-mime_type ""}
+    {-context_id ""}
+    {-content ""}
+} {
+    Modify one or more attributes of a given message.
+} {
+    db_exec_plsql message_set_attr {
+        begin
+            bboard_message.set_attrs (
+                message_id => :message_id,
+                reply_to => :reply_to,
+                sent_date => :sent_date,
+                sender => :sender,
+                title => :title,
+                mime_type => :mime_type,
+                context_id => :context_id
+            );
+        end;
+    }
+    db_1row message_revision {
+        select live_revision as revision_id from cr_items
+            where item_id = :message_id
+            for update
+    }
+    db_dml message_set_content {
+        update cr_revisions
+            set content = empty_blob()
+            where revision_id = :revision_id
+        returning content into :1
+    } -blobs [list $content]
+}
+
+ad_proc -public bboard_message_clear_categories {
+    {-message_id:required}
+} {
+    Clear all category associations from one message.
+} {
+    db_exec_plsql bboard_message_clear_categories {
+        begin
+            bboard_message.clear_categories ( :message_id );
+        end;
+    }
+}
+
+ad_proc -public bboard_message_add_category {
+    {-message_id:required}
+    {-category_id:required}
+} {
+    Add one category relationship to a message.
+} {
+    db_exec_plsql bboard_message_add_category {
+        begin
+            bboard_message.add_category (
+                message_id => :message_id,
+                category_id => :category_id
+            );
+        end;
+    }
+}
+
+ad_proc -public bboard_message_remove_category {
+    {-message_id:required}
+    {-category_id:required}
+} {
+    Remove one category relationship from a message.
+} {
+    db_exec_plsql bboard_message_remove_category {
+        begin
+            bboard_message.remove_category (
+                message_id => :message_id,
+                category_id => :category_id
+            );
+        end;
+    }
+}
+
+ad_proc -public bboard_message_set_status {
+    {-message_id:required}
+    {-forum_id:required}
+    {-status:required}
+} {
+    Modify the status of a message in a particular forum.  Null status is
+    not in the forum.  Acceptable statuses are unmoderated, approved, and
+    rejected.
+} {
+    db_exec_plsql bboard_message_set_status {
+        begin
+            bboard_message.set_status (
+                message_id => :message_id,
+                forum_id => :forum_id,
+                status => :status
+            );
+        end;
+    }
+}
+
+ad_proc -public bboard_message_get {
+    {-message_id:required}
+    {-column_array:required}
+} {
+    Get the columns for a given message into an array variable.
+} {
+    upvar $rowvar row
+    db_1row message_get {
+        select * from acs_messages_all where message_id = :message_id
+    } -column_array row
+}
+
+ad_proc -public bboard_schedule_sends {
+    {-message_id:required}
+    {-email_message_id}
+} {
+    Schedule all message sends for the given message.
+    
+    Supports sending an email version of the message given the
+    optional email_message_id.  In this case the message stored with
+    $email_message_id is sent out to whoever is subscribed to
+    $message_id.  
+} {
+
+    # If we don't have a specific message that is to be sent, just use
+    # the original.
+
+    if ![info exists email_message_id] {
+	set email_message_id $message_id
+    }
+
+    # Thread based sends
+    acs_messaging_send_query -message_id $email_message_id \
+	    -query [db_map thread_subscribers] \
+            -bind [list message_id $message_id]
+
+    # Category based sends
+    acs_messaging_send_query -message_id $email_message_id \
+	    -query [db_map category_subscribers] \
+	    -bind [list message_id $message_id]
+
+    # Forum based sends
+    acs_messaging_send_query -message_id $email_message_id \
+	    -query [db_map forum_subscribers] \
+	    -bind [list message_id $message_id]
+}
+
+ad_proc -public bboard_subscribe_forum {
+    {-forum_id:required}
+    {-subscriber_id:required}
+} {
+    Subscribe a user to the given forum (for instant updates, right now.)
+} {
+    db_exec_plsql forum_subscribe {
+        begin
+            bboard_forum.subscribe (
+                forum_id => :forum_id,
+                subscriber_id => :subscriber_id
+            );
+        end;
+    }
+}
+
+ad_proc -public bboard_unsubscribe_forum {
+    {-forum_id:required}
+    {-subscriber_id:required}
+} {
+    Unsubscribe a user from the given forum.
+} {
+    db_dml forum_unsubscribe {
+        delete from bboard_forum_subscribers
+            where forum_id = :forum_id
+                and subscriber_id = :subscriber_id
+    }
+}
+
+ad_proc -public bboard_subscribe_category {
+    {-category_id:required}
+    {-subscriber_id:required}
+} {
+    Subscribe a user to the given category (for instant updates, right now.)
+} {
+    db_exec_plsql category_subscribe {
+        begin
+            bboard_category.subscribe (
+                category_id => :category_id,
+                subscriber_id => :subscriber_id
+            );
+        end;
+    }
+}
+
+ad_proc -public bboard_unsubscribe_category {
+    {-category_id:required}
+    {-subscriber_id:required}
+} {
+    Unsubscribe a user from the given category.
+} {
+    db_dml category_unsubscribe {
+        delete from bboard_category_subscribers
+            where category_id = :category_id
+                and subscriber_id = :subscriber_id
+    }
+}
+
+ad_proc -public bboard_subscribe_thread {
+    {-thread_id:required}
+    {-subscriber_id:required}
+} {
+    Subscribe a user to the given thread (for instant updates, right now.)
+} {
+    db_exec_plsql thread_subscribe {
+        begin
+            bboard_message.subscribe (
+                thread_id => :thread_id,
+                subscriber_id => :subscriber_id
+            );
+        end;
+    }
+}
+
+ad_proc -public bboard_unsubscribe_thread {
+    {-thread_id:required}
+    {-subscriber_id:required}
+} {
+    Unsubscribe a user from the given thread.
+} {
+    db_dml thread_unsubscribe {
+        delete from bboard_thread_subscribers
+            where thread_id = :thread_id
+                and subscriber_id = :subscriber_id
+    }
+}
+
+ad_proc -public bboard_category_subscribed_p {
+    {-direct:boolean}
+    user_id
+    category_id
+} {
+    Returns "t" or "f" based on whether a user is subscribed to a 
+    particular category.  The -direct switch checks only category
+    subscriptions whereas leaving it off checks for the category,
+    and any forums the category is in.
+} {
+    db_0or1row check_category_subscribed {
+        select count(*) as subscribed_p from bboard_category_subscribers
+            where category_id = :category_id
+                and subscriber_id = :user_id
+    }
+
+    if {$subscribed_p > 0} {
+	return "t"
+    } else {
+	if {!$direct_p} {
+	    # if direct isn't defined, we should also check
+	    # for 
+
+	    db_0or1row check_category_forums_subscribed {
+		select count(*) as subscribed_p from bboard_forum_subscribers
+     	            where subscriber_id = :user_id
+		        and forum_id in (select bc.forum_id
+		                            from bboard_categories bc
+  		                            where bc.category_id = 
+                                                  :category_id)
+	    }
+
+	    if {$subscribed_p > 0} {
+		return "t"
+	    }
+	}
+    }
+
+    return "f"
+}
+
+ad_proc -public bboard_forum_subscribed_p {
+    user_id
+    forum_id
+} {
+    Returns "t" or "f" based on whether a user is subscribed to a 
+    particular forum, category, or thread.
+} {
+    db_0or1row check_forum_subscribed {
+        select count(*) as subscribed_p 
+            from bboard_forum_subscribers
+            where forum_id = :forum_id
+                and subscriber_id = :user_id
+    }
+
+    if {$subscribed_p > 0} {
+	return "t"
+    } else {
+	return "f"
+    }
+}
+
+ad_proc -public bboard_message_subscribed_p {
+    {-direct:boolean}
+    user_id
+    message_id
+} {
+    Returns "t" or "f" based on whether a user is subscribed to a 
+    particular thread.
+} {
+    db_1row check_message_subscribed {
+	select count(*) as subscribed_p from bboard_thread_subscribers
+	where subscriber_id = :user_id
+	      and thread_id in (select message_id
+	                        from acs_messages b
+	                        connect by b.message_id = prior b.reply_to 
+	                        start with message_id = :message_id)
+
+    }
+
+    if {$subscribed_p > 0} {
+	return "t"
+    } else {
+	if {! $direct_p } {
+	    db_1row check_message_cats_subscribed {
+		select count(*) as subscribed_p 
+		from bboard_category_subscribers
+		where subscriber_id = :user_id
+		      and category_id in (select bcmm.category_id
+		                          from bboard_category_message_map bcmm
+		                          where bcmm.message_id = :message_id)
+
+	    }
+
+	    if {$subscribed_p > 0} {
+		return "t"
+	    } else {
+		db_0or1row check_message_forums_subscribed {
+		    select count(*) as subscribed_p 
+		    from bboard_forum_subscribers
+		    where subscriber_id = :user_id
+		          and forum_id in (select bfmm.forum_id
+   		                           from bboard_forum_message_map bfmm
+		                           where bfmm.message_id = :message_id)
+		}
+
+		if {$subscribed_p > 0} {
+		    return "t"
+		}
+	    }
+	}
+    }
+    return "f"
+}
+
+ad_proc -public bboard_message_forum {
+    {message_id}
+} {
+    Returns a forum_id for a forum that the supplied message is in.  Returns 0
+    if the message id isn't found.
+} {
+    db_1row bboard_forum_containing_message {
+	select bboard_forum.forum_containing_message(:message_id) as forum_id
+	  from dual
+    }
+
+    return $forum_id
+}
+
+ad_proc -public bboard_forum_moderated_p {
+    {forum_id}
+} {
+    Returns "t" if the forum is moderated, "f" otherwise
+} {
+    db_1row forum_moderated_p {
+	select moderated_p
+  	  from bboard_forums
+	  where forum_id = :forum_id
+    }
+
+    return $moderated_p
+}
+
+ad_proc bboard_message_page {
+} {
+    Returns the appropriate page name to display a message.  This
+    proc consults preferences to determine different display styles.
+} {
+    if {[string compare [ad_parameter "ThreadingEnabledP"] "t"] == 0} {
+	return "message-threaded"
+    } else {
+	return "message"
+    }
+}
+
+ad_proc -public bboard_message_url {
+    {-absolute:boolean}
+    {-top:boolean}
+    {message_id}
+    {forum_id ""}
+} {
+    Returns the proper URL for displaying the message with the supplied message_id.
+
+    If given the -absolute flag it will return a full url.
+
+    When the absolute flag is specified, this proc must be called from
+    within a live page since it depends on ad_conn being around.
+
+} {
+    # This is a workaround to a bug in acs-messaging-procs/first_ancestor
+    # that won't be deployed until after this next bboard release -akk
+
+    if {! $top_p} {
+        db_1row first_ancestor {
+	    select acs_message.first_ancestor(:message_id) as ancestor_id 
+                from dual
+        }
+    } else {
+        set ancestor_id $message_id
+    }
+
+    if { $message_id == $ancestor_id } {
+	set anchor ""
+    } else {
+	set anchor "#$message_id"
+    }
+
+    # if we don't have a forum_id, let's pick one!
+
+    # use of this violates the assumption
+    # that messages can be in multiple forums
+
+    if [string equal $forum_id ""] {
+	set forum_id [bboard_message_forum $ancestor_id]
+    }
+
+    set message_id $ancestor_id
+    if {$absolute_p} {
+	set prefix "[ad_conn location][ad_conn package_url]"
+    } else {
+	set prefix ""
+    }
+
+    return "$prefix[bboard_message_page]?message_id=$message_id&forum_id=$forum_id$anchor"
+}
+
+ad_proc -public bboard_subscriptions_url {} {
+    Returns URL for managing bboard subscriptions.
+} {
+    return "[ad_conn location][ad_conn package_url]subscriptions"
+}
+
+# if i were cool, i'd implement an Omega(log n) solution for this
+# i am not however, cool
+
+ad_proc -public bboard_n_spaces {
+    {n}
+} {
+    Returns a string containg n HTML spaces i.e &amp;nbsp;
+} {
+    set spaces ""
+    for {set i 0} {$i < $n} {incr i} {
+	append spaces "&nbsp;"
+    }
+    return $spaces
+}
+
+
+ad_proc -public bboard_upload_extension {
+    {filename}
+} {
+    This proc returns the stripped file extensions of a filename.
+} {
+    # get the file extension
+    set file_extension [string tolower [file extension $filename]]
+
+    # remove the first . from the file extension
+    regsub {\.} $file_extension "" file_extension
+    
+    return $file_extension
+}
+
+ad_proc -public bboard_upload_basename {
+    {filename}
+} {
+    This proc attempts to return the base of a passed in filename i.e.
+    it strips off the C:\directories and associated crud.
+    e.g. C:\bar\baz\qux.flad -> qux.flad
+} {
+    # strip off the C:\directories... crud and just get the file name
+    if ![regexp {([^/\\]+)$} $filename match filename] {
+	# couldn't find a match
+	set filename $filename
+    }
+
+    return $filename
+}
+
+ad_proc -public bboard_image_size {
+    {file_extension}
+    {filename}
+} {
+    This proc returns a list [width height] from an image if it can determine
+    this information from the file and file extension.
+} {
+
+    set what_aolserver_told_us ""
+
+    if { $file_extension == "jpeg" || $file_extension == "jpg" } {
+	catch { set what_aolserver_told_us [ns_jpegsize $filename] }
+    } elseif { $file_extension == "gif" } {
+	catch { set what_aolserver_told_us [ns_gifsize $filename] }
+    }
+    
+    # the AOLserver jpegsize command has some bugs where the height comes 
+    # through as 1 or 2 
+    if { ![empty_string_p $what_aolserver_told_us] && 
+          [lindex $what_aolserver_told_us 0] > 10 && 
+          [lindex $what_aolserver_told_us 1] > 10 } {
+	return $what_aolserver_told_us
+    } else {
+	return [list "" ""]
+    }
+}
+
+ad_proc -public bboard_check_and_register_mime_type {
+    {type}
+} {
+    This proc checks for or registers a mime_type in the content
+    repository type registry.
+} {
+    # we don't do this as a transaction.
+    # or god forbid hold an exclusive lock
+
+    # since if someone else adds this type at the same
+    # moment, we don't care.
+
+    db_0or1row check_mime_type {
+	select mime_type
+	    from cr_mime_types
+	    where mime_type = :type
+    }
+
+    if ![info exists mime_type] {
+	    db_dml insert_mime {
+		insert into cr_mime_types (mime_type)
+		values (:type)
+	    }
+    }
+}
+
+ad_proc -public bboard_attach_image {
+    {-message_id:required}
+    {-file_id ""}
+    {-short_filename:required}
+    {-local_filename:required}
+    {-mime_type:required}
+    {-width ""}
+    {-height ""}
+    {-title ""}
+    {-user_id ""}
+    {-creation_ip ""}
+} {
+    Creates a message image attachment.
+} {
+        db_exec_plsql insert_image {
+             begin
+                :1 := acs_message.new_image (
+                    message_id     => :message_id,
+                    image_id       => :file_id,
+                    file_name      => :short_filename,
+                    title          => :title,
+                    mime_type      => :mime_type,
+                    content        => empty_blob(),
+                    width          => :width,
+                    height         => :height,
+                    creation_user  => :user_id,
+                    creation_ip    => :creation_ip,
+                    is_live        => 't'
+            );
+            end;
+        }
+
+    db_1row get_revision {
+        select content_item.get_latest_revision(:file_id) as revision_id
+        from dual
+    }
+
+    set filename [cr_create_content_file $file_id $revision_id $local_filename]
+    set size [file size $local_filename]
+
+    db_dml set_content_size ""
+}
+
+ad_proc -public bboard_attach_file {
+    {-message_id:required}
+    {-file_id ""}
+    {-short_filename:required}
+    {-local_filename:required}
+    {-mime_type:required}
+    {-title ""}
+    {-user_id ""}
+    {-creation_ip ""}
+} {
+    Creates a new bboard attachment.
+} {
+        db_exec_plsql insert_file {
+            begin
+                :1 := acs_message.new_file (
+                    message_id     => :message_id,
+                    file_id        => :file_id,
+                    file_name      => :short_filename,
+                    title          => :title,
+                    mime_type      => :mime_type,
+                    content        => empty_blob(),
+                    creation_user  => :user_id,
+                    creation_ip    => :creation_ip,
+                    is_live        => 't'
+            );
+            end;
+        }
+
+    db_1row get_revision {
+        select content_item.get_latest_revision(:file_id) as revision_id
+        from dual
+    }
+    
+    set filename [cr_create_content_file $file_id $revision_id $local_filename]
+    set size [file size $local_filename]
+
+    db_dml set_content_size ""
+}
+
+
+ad_proc -public bboard_delete_attachment {
+    {file_id}
+} {
+    Deletes an attachment.
+} {
+    if [db_0or1row is_file_image {
+	select image_id
+            from images
+            where image_id = content_item.get_latest_revision(:file_id)
+    }] {
+	db_exec_plsql delete_image {
+	    begin
+	        acs_message.delete_image(:file_id);
+	    end;
+	}
+    } else {
+	db_exec_plsql delete_file {
+	    begin
+   	        acs_message.delete_file(:file_id);
+	    end;
+	}
+    }
+}
+
+ad_proc -public bboard_alert_from_address {
+} {
+    Returns an appropriate from address for bboard alerts.
+} {
+    return "bboard-robot@[ad_conn host]"
+}
+
+ad_proc -public bboard_alert_message {
+    {-mime_type:required}
+    {-content:required}
+    {-message_id:required}
+    {-forum_id:required}
+    {-sender:required}
+} {
+    Takes a bboard message and returns a text message
+} {
+    db_1row forum_info {
+	select short_name as forum_name
+	    from bboard_forums
+	    where forum_id = :forum_id
+    }
+
+    if {[string equal $mime_type "text/plain"]} {
+	set result $content
+    } elseif {[string equal $mime_type "text/plain; format=flowed"]} {
+	set result [wrap_string $content]
+    } elseif {[string equal $mime_type "text/html"]} {
+	set result [ad_html_to_text $content]
+    } else {
+	set result "Error display bboard posting as email!
+Our bboard system has received a post we don't know how to 
+send via email.  Please go to the below URL for a better shot 
+at displaying."
+    }
+    
+    set header "Posted by:  $sender"
+
+    set footer "--------------------
+This is a posting from the $forum_name bboard.
+To reply you can go to:
+[bboard_message_url -absolute $message_id $forum_id]
+To unsubscribe from this or other bboard posts go to:
+[bboard_subscriptions_url]"
+
+    return "${header}
+
+${result}
+
+${footer}"
+}
+
+ad_proc -public bboard_alert_one_mesg {
+    {-message_id:required}
+    {-forum_id:required}
+    {-user_id:required}
+    {-creation_ip ""}
+} {
+    This proc does generates the appropriate alerts for a new bboard post.
+
+    This proc must be called from within a live page since it depends on
+    ad_conn being around.
+} {
+    db_1row bboard_mesg_info {
+	select reply_to, sender, title, mime_type, content, email,
+               first_names||' '||last_name as full_name
+            from acs_messages_all, persons, parties
+            where message_id = :message_id
+                  and person_id = sender
+	          and party_id = person_id
+    }
+
+    db_1row forum_info {
+	select short_name as forum_name
+	    from bboard_forums
+	    where forum_id = :forum_id
+    }
+
+    set email_mesg_id [bboard_message_new -sender $user_id \
+                         -title "$title \[$forum_name\]" \
+                         -mime_type "text/plain" \
+                         -content [bboard_alert_message -mime_type $mime_type \
+                                       -content $content \
+                                       -sender "$full_name <$email>" \
+                                       -message_id $message_id \
+                                       -forum_id $forum_id] \
+                         -context_id $message_id -creation_user $user_id \
+                         -creation_ip $creation_ip]
+
+    bboard_schedule_sends -message_id $message_id \
+                          -email_message_id $email_mesg_id
+}
+
+ad_proc -private bboard_garbage_collect {
+} {
+    garbage collects deleted messages, message email artifacts, etc.,
+
+    In particular, this deletes message objects that aren't currently
+    in a forum, but that are children of bboard messages or bboard forums.
+
+    DRB: The bboard package duplicates messages when you choose to mail one
+    to a friend, setting the new message's context_id to the original message.
+    This new message doesn't belong to a forum.  The context_id is used to
+    retrieve these via CONNECT BY and they're then deleted (presumably under
+    the assumption that they've been e-mailed immediately).
+
+    This is context_id abuse.  Context_id is supposed to be used for 
+    permissions inheritance only.  This is one of several instances in the
+    toolkit where context_id is used to link objects together in a hierarchy
+    in a way that has nothing to do with permissions.  It sucks and must be
+    fixed later (along with a bunch of other crap in this relatively ugly
+    package).
+
+    I don't think orphans arise in other circumstances but I could be wrong
+    as I've not scoured the code thoroughly yet.
+
+} {
+    acs_messaging_process_queue
+
+    if {[db_type] == "postgresql"} {
+	bboard_garbage_collect_postgresql
+    } else {
+	db_exec_plsql bboard_alert_clean ""
+    }
+}
+
+
+ad_proc -private bboard_garbage_collect_postgresql {} {
+    Works around postgresql bugs that make it impossible
+    to delete multiple items in a single transaction
+
+    DRB fixed the assumption that only general-comments and bboard use acs_messaging
+
+} {
+    db_foreach get_orphans {
+          select object_id as message_id
+          from acs_objects o
+          where o.object_type = 'acs_message'
+            and not exists (select 1
+                            from bboard_forum_message_map bfmm, acs_objects o2
+                            where o2.object_id = bfmm.message_id and
+                            o.tree_sortkey between o2.tree_sortkey and tree_right(o2.tree_sortkey))
+    } {
+        db_dml clear_revision_references {
+            update cr_items
+               set latest_revision=null, live_revision=null
+             where item_id = :message_id
+        }
+
+        db_exec_plsql delete_message {
+            select bboard_message__remove(:message_id);
+        }
+    }
+}
Index: openacs-4/packages/sloan-bboard/tcl/bboard-procs.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/tcl/bboard-procs.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/tcl/bboard-procs.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,221 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="bboard_forum_get.forum_get">      
+      <querytext>
+      
+        select * from bboard_forums where forum_id = :forum_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_category_get.category_get">      
+      <querytext>
+      
+        select * from bboard_categories where category_id = :category_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_new.message_new_revision">      
+      <querytext>
+      
+        select live_revision as revision_id
+            from cr_items
+            where item_id = :message_id
+        for update
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_set.message_revision">      
+      <querytext>
+      
+        select live_revision as revision_id from cr_items
+            where item_id = :message_id
+            for update
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_get.message_get">      
+      <querytext>
+      
+        select * from acs_messages_all where message_id = :message_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_unsubscribe_forum.forum_unsubscribe">      
+      <querytext>
+      
+        delete from bboard_forum_subscribers
+            where forum_id = :forum_id
+                and subscriber_id = :subscriber_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_unsubscribe_category.category_unsubscribe">      
+      <querytext>
+      
+        delete from bboard_category_subscribers
+            where category_id = :category_id
+                and subscriber_id = :subscriber_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_unsubscribe_thread.thread_unsubscribe">      
+      <querytext>
+      
+        delete from bboard_thread_subscribers
+            where thread_id = :thread_id
+                and subscriber_id = :subscriber_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_category_subscribed_p.check_category_subscribed">      
+      <querytext>
+      
+        select count(*) as subscribed_p from bboard_category_subscribers
+            where category_id = :category_id
+                and subscriber_id = :user_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_category_subscribed_p.check_category_forums_subscribed">      
+      <querytext>
+      
+		select count(*) as subscribed_p from bboard_forum_subscribers
+     	            where subscriber_id = :user_id
+		        and forum_id in (select bc.forum_id
+		                            from bboard_categories bc
+  		                            where bc.category_id = 
+                                                  :category_id)
+	    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_forum_subscribed_p.check_forum_subscribed">      
+      <querytext>
+      
+        select count(*) as subscribed_p 
+            from bboard_forum_subscribers
+            where forum_id = :forum_id
+                and subscriber_id = :user_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_subscribed_p.check_message_cats_subscribed">      
+      <querytext>
+      
+		select count(*) as subscribed_p 
+		from bboard_category_subscribers
+		where subscriber_id = :user_id
+		      and category_id in (select bcmm.category_id
+		                          from bboard_category_message_map bcmm
+		                          where bcmm.message_id = :message_id)
+
+	    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_message_subscribed_p.check_message_forums_subscribed">      
+      <querytext>
+      
+		    select count(*) as subscribed_p 
+		    from bboard_forum_subscribers
+		    where subscriber_id = :user_id
+		          and forum_id in (select bfmm.forum_id
+   		                           from bboard_forum_message_map bfmm
+		                           where bfmm.message_id = :message_id)
+		
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_forum_moderated_p.forum_moderated_p">      
+      <querytext>
+      
+	select moderated_p
+  	  from bboard_forums
+	  where forum_id = :forum_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_check_and_register_mime_type.check_mime_type">      
+      <querytext>
+      
+	select mime_type
+	    from cr_mime_types
+	    where mime_type = :type
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_check_and_register_mime_type.insert_mime">      
+      <querytext>
+      
+		insert into cr_mime_types (mime_type)
+		values (:type)
+	    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_alert_message.forum_info">      
+      <querytext>
+      
+	select short_name as forum_name
+	    from bboard_forums
+	    where forum_id = :forum_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_alert_one_mesg.bboard_mesg_info">      
+      <querytext>
+      
+	select reply_to, sender, title, mime_type, content, email,
+               first_names||' '||last_name as full_name
+            from acs_messages_all, persons, parties
+            where message_id = :message_id
+                  and person_id = sender
+	          and party_id = person_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_alert_message.forum_info">      
+      <querytext>
+      
+	select short_name as forum_name
+	    from bboard_forums
+	    where forum_id = :forum_id
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/attachment-delete.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/attachment-delete.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/attachment-delete.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,16 @@
+ad_page_contract {
+    Delete an attachment.
+
+    @author Anukul Kapoor (akk@arsdigita.com)
+    @creation-date 2000-12-30
+    @cvs $Id: attachment-delete.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+} {
+    file_id:integer,notnull
+    message_id:integer,notnull
+}
+
+ad_require_permission $file_id bboard_write_message
+
+bboard_delete_attachment $file_id
+
+ad_returnredirect [bboard_message_url $message_id]
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/attachment.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/attachment.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/attachment.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,16 @@
+ad_page_contract {
+    This serves an attachment file.
+
+    @author Anukul Kapoor <akk@arsdigita.com>
+    @creation-date 2000-12-30
+    @cvs-id $Id: attachment.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+} {
+    file_id:integer,notnull
+}
+
+if [string equal [ad_parameter "AttachmentsEnabledP"] "t"] {
+    ad_require_permission $file_id bboard_read_forum
+    cr_write_content -item_id $file_id
+} else {
+    ad_return_complaint 1 "Attachments are currently disabled"
+}
Index: openacs-4/packages/sloan-bboard/www/category-delete-2-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-delete-2-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-delete-2-oracle.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="delete_category">      
+      <querytext>
+      
+    begin
+        bboard_category.delete (:category_id);
+    end;
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/category-delete-2-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-delete-2-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-delete-2-postgresql.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="delete_category">      
+      <querytext>
+        select bboard_category__delete (:category_id);
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/category-delete-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-delete-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-delete-2.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,25 @@
+ad_page_contract {
+
+    Delete a category
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-12-01
+    @cvs-id $Id: category-delete-2.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+
+} {
+    category_id:integer,notnull,bboard_category_id
+}
+
+ad_require_permission $category_id bboard_delete_category
+
+db_1row forum_id {
+    select forum_id from bboard_categories where category_id = :category_id
+}
+
+db_exec_plsql delete_category {
+    begin
+        bboard_category.delete (:category_id);
+    end;
+}
+
+ad_returnredirect "forum?forum_id=$forum_id"
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/category-delete-2.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-delete-2.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-delete-2.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="forum_id">      
+      <querytext>
+      
+    select forum_id from bboard_categories where category_id = :category_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/category-delete.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-delete.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-delete.adp	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,13 @@
+<master src="master">
+<property name="context_bar">@context_bar@</property>
+<property name="title">Delete a Category</property>
+
+You are going to delete the category "@category_name@", causing all
+@message_count@ messages in it to be placed in the category "Unknown".
+
+<center>
+<p>Are you sure you want to delete this category?<p>
+
+<a href="category-delete-2?category_id=@category_id@">Yes</a> &nbsp; &nbsp;
+<a href="<%= [get_referrer_and_query_string] %>">No</a>
+</center>
Index: openacs-4/packages/sloan-bboard/www/category-delete.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-delete.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-delete.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,40 @@
+ad_page_contract {
+
+    Displays a confirmation of "do you really want to delete this category?"
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-12-01
+    @cvs-id $Id: category-delete.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+
+} {
+    category_id:integer,notnull,bboard_category_id
+} -properties {
+    context_bar:onevalue
+    category_id:onevalue
+    category_name:onevalue
+    message_count:onevalue
+}
+
+ad_require_permission $category_id bboard_delete_category
+
+db_1row forum_short_name_id {
+    select f.short_name as forum_name, f.forum_id
+        from bboard_forums f, bboard_categories c
+        where c.category_id = :category_id
+          and c.forum_id = f.forum_id
+}
+
+db_1row category_short_name {
+    select short_name as category_name
+        from bboard_categories
+        where category_id = :category_id
+}
+
+db_1row category_message_count {
+    select count(*) as message_count
+        from bboard_category_message_map
+        where category_id = :category_id
+}
+
+set context_bar [list [list "forum?[export_url_vars forum_id]" $forum_name] \
+                      {"Delete Category"}]
Index: openacs-4/packages/sloan-bboard/www/category-delete.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-delete.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-delete.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="forum_short_name_id">      
+      <querytext>
+      
+    select f.short_name as forum_name, f.forum_id
+        from bboard_forums f, bboard_categories c
+        where c.category_id = :category_id
+          and c.forum_id = f.forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="category_short_name">      
+      <querytext>
+      
+    select short_name as category_name
+        from bboard_categories
+        where category_id = :category_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="category_message_count">      
+      <querytext>
+      
+    select count(*) as message_count
+        from bboard_category_message_map
+        where category_id = :category_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/category-edit-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-edit-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-edit-2.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,26 @@
+ad_page_contract {
+
+    Edit a category
+
+    @author John Prevost <jprevost@arsdigita.com>
+    @creation-date 2000-09-07
+    @cvs-id $Id: category-edit-2.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+
+    @param category_id The ID of the category to update
+    @param short_name  The short name of the forum
+    @param forum_id    The forum ID the category is in (to redirect back to)
+
+} {
+    category_id:integer,notnull,bboard_category_id
+    short_name:notnull,trim
+    forum_id:integer,notnull,bboard_forum_id
+}
+
+ad_require_permission $category_id bboard_write_category
+
+db_transaction {
+    bboard_category_set -category_id $category_id -short_name $short_name
+}
+# on error ...
+
+ad_returnredirect "forum?[export_url_vars forum_id]"
Index: openacs-4/packages/sloan-bboard/www/category-edit.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-edit.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-edit.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,44 @@
+ad_page_contract {
+
+    Displays a form for editing a category in a forum.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-09-07
+    @cvs-id $Id: category-edit.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+
+} {
+    category_id:integer,notnull,bboard_category_id
+} -properties {
+    context_bar:onevalue
+    forum_name:onevalue
+    forum_id:onevalue
+    category_id:onevalue
+    action:onevalue
+    title:onevalue
+}
+
+ad_require_permission $category_id bboard_write_category
+
+set action "category-edit-2"
+set submit_label "Save Changes"
+set title "Edit a Category"
+
+# bboard_category_get -category_id $category_id -column_array category
+# bboard_forum_get -forum_id $category(forum_id) -column_array forum
+
+# set forum_name $forum(short_name)
+# set forum_id $forum(forum_id)
+# set short_name $category(short_name)
+
+db_1row category_info {
+    select f.short_name as forum_name, f.forum_id, c.short_name
+      from bboard_forums f, bboard_categories c
+      where c.category_id = :category_id
+        and f.forum_id = c.forum_id
+}
+
+set context_bar \
+	[list [list "forum?[export_url_vars forum_id]" $forum_name] \
+	      "Edit a Category"]
+
+ad_return_template category-entry
Index: openacs-4/packages/sloan-bboard/www/category-edit.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-edit.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-edit.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="category_info">      
+      <querytext>
+      
+    select f.short_name as forum_name, f.forum_id, c.short_name
+      from bboard_forums f, bboard_categories c
+      where c.category_id = :category_id
+        and f.forum_id = c.forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/category-entry.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-entry.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-entry.adp	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,20 @@
+<master src="master">
+<property name="title">@forum_name@: @title@</property>
+<property name="context_bar">@context_bar@</property>
+
+<form action="@action@" method="POST">
+ <input type="hidden" name="forum_id" value="@forum_id@">
+ <input type="hidden" name="category_id" value="@category_id@">
+ <blockquote>
+  <table>
+   <tr>
+    <th align="right">Short Name:</th>
+    <td><input size="50" name="short_name" value="@short_name@"></td>
+   </tr>
+   <tr>
+    <th></th>
+    <td><input type="submit" value="@submit_label@"></td>
+  </table>
+ </blockquote>
+</form>
+
Index: openacs-4/packages/sloan-bboard/www/category-new-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-new-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-new-2.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,26 @@
+ad_page_contract {
+
+    Create a new category in a forum.
+
+    @author John Prevost <jprevost@arsdigita.com>
+    @creation-date 2000-08-30
+    @cvs-id $Id: category-new-2.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+
+    @param category_id The ID of the new category to be created (debounce)
+    @param forum_id    The ID of the forum to create it in
+    @param short_name  The short name of the forum
+} {
+    category_id:integer,notnull
+    forum_id:integer,notnull,bboard_forum_id
+    short_name:notnull,trim
+}
+
+ad_require_permission $forum_id bboard_create_category
+
+db_transaction {
+    bboard_category_new -category_id $category_id -forum_id $forum_id \
+	    -short_name $short_name
+}
+# on error ...
+
+ad_returnredirect "forum?[export_url_vars forum_id]"
Index: openacs-4/packages/sloan-bboard/www/category-new.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-new.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-new.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,39 @@
+ad_page_contract {
+    
+    Displays a form for creating a category in a forum.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-08-31
+    @cvs-id $Id: category-new.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+} {
+    forum_id:integer,notnull,bboard_forum_id
+} -properties {
+    context_bar:onevalue
+    forum_name:onevalue
+    forum_id:onevalue
+    short_name:onevalue
+    submit_label:onevalue
+    category_id:onevalue
+    action:onevalue
+    title:onevalue
+}
+
+ad_require_permission $forum_id bboard_create_category
+
+set action "category-new-2"
+set short_name ""
+set submit_label "Create Category"
+set title "Create a Category"
+
+db_1row forum_short_name {
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+}
+
+set context_bar \
+	[list [list "forum?[export_url_vars forum_id]" $forum_name] \
+              "Create a Category"]
+
+set category_id [db_nextval acs_object_id_seq]
+
+ad_return_template category-entry
Index: openacs-4/packages/sloan-bboard/www/category-new.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-new.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-new.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="forum_short_name">      
+      <querytext>
+      
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/category-subscribe.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-subscribe.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-subscribe.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,27 @@
+ad_page_contract {
+
+    Unsubscribe the current user from a given category.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-10-28
+    @cvs-id $Id: category-subscribe.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+
+} {
+    category_id:integer,notnull,bboard_category_id
+}
+
+db_1row category_forum {
+    select forum_id from bboard_categories where category_id = :category_id
+}
+
+# Not strictly right
+ad_require_permission $forum_id bboard_create_message
+
+catch {
+    bboard_subscribe_category \
+	-category_id $category_id -subscriber_id [ad_verify_and_get_user_id]
+}
+
+ad_returnredirect "forum-by-category?forum_id=$forum_id&category_id=$category_id"
+
+
Index: openacs-4/packages/sloan-bboard/www/category-subscribe.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-subscribe.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-subscribe.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="category_forum">      
+      <querytext>
+      
+    select forum_id from bboard_categories where category_id = :category_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/category-unsubscribe.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/category-unsubscribe.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/category-unsubscribe.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,27 @@
+ad_page_contract {
+
+    Unsubscribe the current user from a given category.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-10-28
+    @cvs-id $Id: category-unsubscribe.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+
+} {
+    forum_id:integer,notnull
+    category_id:integer,notnull,bboard_category_id
+    {sub_page ""}
+}
+
+# Not strictly right
+ad_require_permission $forum_id bboard_create_message
+
+catch {
+    bboard_unsubscribe_category \
+	-category_id $category_id -subscriber_id [ad_verify_and_get_user_id]
+}
+
+if [empty_string_p $sub_page] {
+    ad_returnredirect "forum-by-category?category_id=$category_id&forum_id=$forum_id"
+} else {
+    ad_returnredirect "subscriptions"
+}
Index: openacs-4/packages/sloan-bboard/www/forum-by-category-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-by-category-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-by-category-oracle.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="categories_select_none">      
+      <querytext>
+      
+    select 1 from dual where 0 = 1
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="messages_select_by_cat">      
+      <querytext>
+      
+    select message_id, title, num_replies,
+         first_names||' '||last_name as full_name,
+  	 to_char(last_reply_date,'MM/DD/YY hh12:Mi am') as last_updated
+    from bboard_messages_by_category b, persons
+    where person_id = sender
+        and reply_to is null
+        and forum_id = :forum_id
+  	$category_sql
+        $moderated_sql
+    order by sent_date desc
+	
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="unapproved_none">      
+      <querytext>
+      
+	select 1 from dual where 1 = 0
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="rejected_none">      
+      <querytext>
+      
+	select 1 from dual where 1 = 0
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/forum-by-category-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-by-category-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-by-category-postgresql.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="categories_select_none">      
+      <querytext>
+      
+    select 1  where 0 = 1
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="messages_select_by_cat">      
+      <querytext>
+      
+    select message_id, title, num_replies,
+         first_names||' '||last_name as full_name,
+  	 to_char(last_reply_date,'MM/DD/YY hh12:MI am') as last_updated
+    from bboard_messages_by_category b, persons
+    where person_id = sender
+        and reply_to is null
+        and forum_id = :forum_id
+  	$category_sql
+        $moderated_sql
+    order by sent_date desc
+	
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="unapproved_none">      
+      <querytext>
+      
+	select 1  where 1 = 0
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="rejected_none">      
+      <querytext>
+      
+	select 1  where 1 = 0
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/forum-by-category.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-by-category.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-by-category.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,144 @@
+ad_page_contract {
+
+    Displays a list of messages in a forum
+
+    @author John Prevost (jmp@arsdigita.com)
+    @creation-date 2000-08-29
+    @cvs-id $Id: forum-by-category.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+} {
+    category_id:integer,bboard_category_id
+    forum_id:integer,notnull,bboard_forum_id
+} -properties {
+    forum_write_p:onevalue
+    forum_create_p:onevalue
+    context_bar:onevalue
+    title:onevalue
+    forum_name:onevalue
+    forum_id:onevalue
+    category_id:onevalue
+    messages:multirow
+    categories:multirow
+    moderator_p:onevalue
+    unapproved:multirow
+    rejected:multirow
+    subscribed_p:onevalue
+}
+
+ad_require_permission $forum_id bboard_read_forum
+
+set moderator_p 0
+
+set category_create_p 0
+
+set user_id [ad_verify_and_get_user_id]
+
+set subscribed_p 0
+
+set admin_p [ad_permission_p $forum_id admin]
+
+db_1row forum_info {
+    select f.short_name as forum_name, f.moderated_p
+        from bboard_forums f
+        where f.forum_id = :forum_id
+}
+
+
+if ![string eq $category_id ""] {
+    db_1row forum_info {
+        select f.forum_id, f.short_name as forum_name, f.moderated_p
+            from bboard_categories c, bboard_forums f
+            where c.category_id = :category_id
+                and c.forum_id = f.forum_id
+    }
+
+    if [string equal $moderated_p "t"] {
+	set moderator_p [ad_permission_p $forum_id bboard_moderate_forum]
+    }
+
+    db_1row category_info {
+        select short_name as category_name from bboard_categories
+          where category_id = :category_id
+    }
+
+} else {
+    set category_name "Uncategorized"
+}
+
+
+if { ![string eq $category_id ""] && [string equal [bboard_category_subscribed_p -direct $user_id $category_id] "t"]} {
+    set subscribed_p 1
+} else {
+    set subscribed_p 0
+}
+
+set context_bar [list [list "forum?[export_url_vars forum_id]" $forum_name] \
+		      $category_name]
+set title "$forum_name: $category_name"
+
+set package_id [ad_conn package_id]
+
+db_multirow categories categories_select_none {
+    select 1 from dual where 0 = 1
+}
+
+if [string equal $moderated_p "f"] {
+    set moderated_sql ""
+} else {
+    set moderated_sql "and status = 'approved'"
+}
+
+if {[string eq $category_id ""]} {
+    set category_sql "and category_id is null"
+} else {
+    set category_sql "and category_id = :category_id"
+}
+
+
+db_multirow messages messages_select_by_cat "
+    select message_id, title, num_replies,
+         first_names||' '||last_name as full_name,
+  	 to_char(last_reply_date,'MM/DD/YY hh12:Mi am') as last_updated
+    from bboard_messages_by_category b, persons
+    where person_id = sender
+        and reply_to is null
+        and forum_id = :forum_id
+  	$category_sql
+        $moderated_sql
+    order by sent_date desc
+	"
+
+if { !$moderator_p } {
+
+    db_multirow unapproved unapproved_none {
+	select 1 from dual where 1 = 0
+    }
+
+    db_multirow rejected rejected_none {
+	select 1 from dual where 1 = 0
+    }
+
+} else {
+
+    db_multirow unapproved messages_select_unmoderated {
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name
+	  from bboard_messages_by_category, persons
+	  where category_id = :category_id
+	    and person_id = sender
+	    and reply_to is null
+	    and status = 'unmoderated'
+    }
+
+    db_multirow rejected rejected_messages_select {
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name
+	  from bboard_messages_by_category, persons
+	  where category_id = :category_id
+	    and person_id = sender
+	    and reply_to is null
+	    and status = 'rejected'
+    }
+
+}
+
+ad_return_template "forum-view"
Index: openacs-4/packages/sloan-bboard/www/forum-by-category.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-by-category.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-by-category.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,65 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="forum_info">      
+      <querytext>
+      
+    select f.short_name as forum_name, f.moderated_p
+        from bboard_forums f
+        where f.forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="category_info">      
+      <querytext>
+      
+        select f.forum_id, f.short_name as forum_name, f.moderated_p
+            from bboard_categories c, bboard_forums f
+            where c.category_id = :category_id
+                and c.forum_id = f.forum_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="category_info">      
+      <querytext>
+        select short_name as category_name from bboard_categories
+          where category_id = :category_id    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="messages_select_unmoderated">      
+      <querytext>
+      
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name
+	  from bboard_messages_by_category, persons
+	  where category_id = :category_id
+	    and person_id = sender
+	    and reply_to is null
+	    and status = 'unmoderated'
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="rejected_messages_select">      
+      <querytext>
+      
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name
+	  from bboard_messages_by_category, persons
+	  where category_id = :category_id
+	    and person_id = sender
+	    and reply_to is null
+	    and status = 'rejected'
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/forum-delete-2-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-delete-2-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-delete-2-oracle.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="categories_delete">      
+      <querytext>
+      
+	declare
+	    cursor category_cursor is
+	        select distinct category_id
+                    from bboard_categories c
+                    where c.forum_id = :forum_id;
+        begin
+	    for category_val in category_cursor loop
+ 
+ 	        delete from acs_permissions 
+                   where object_id = category_val.category_id;
+
+                bboard_category.delete(category_val.category_id);
+            end loop;
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="forum_delete">      
+      <querytext>
+      
+	begin
+	    bboard_forum.delete (:forum_id);
+	end;
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/forum-delete-2-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-delete-2-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-delete-2-postgresql.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="categories_delete">      
+      <querytext>
+	declare
+	    category_val record;
+        begin
+	    for category_val in select distinct category_id
+                     from bboard_categories c
+                    where c.forum_id = :forum_id 
+            loop
+ 
+ 	        delete from acs_permissions 
+                   where object_id = category_val.category_id;
+
+                perform bboard_category__delete(category_val.category_id);
+            end loop;
+	    return 0;
+        end;    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="forum_delete">      
+      <querytext>
+	select bboard_forum__delete (:forum_id);
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/forum-delete-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-delete-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-delete-2.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,37 @@
+ad_page_contract {
+    Presents confirmation screen for deleting a forum.
+
+    @author Anukul Kapoor (akk@arsdigita.com)
+    @creation-date 2000-30-11
+    @cvs-id $Id: forum-delete-2.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+} {
+    forum_id:integer,notnull,bboard_forum_id
+} -properties {
+    forum_id:onevalue
+    short_name:onevalue
+    charter:onevalue
+}
+
+set user_id [ad_verify_and_get_user_id]
+
+ad_require_permission $forum_id admin
+
+# postgresql can't do all this in a transaction
+
+if {[db_type] == "postgresql"} {
+    db_dml messages_delete ""
+    bboard_garbage_collect
+    db_exec_plsql categories_delete ""
+    db_dml permissions_delete ""
+    db_exec_plsql forum_delete ""
+} else { 
+    db_transaction {
+	db_dml messages_delete ""
+	bboard_garbage_collect
+	db_exec_plsql categories_delete ""
+	db_dml permissions_delete ""
+	db_exec_plsql forum_delete ""
+    }
+}
+
+ad_returnredirect ""
Index: openacs-4/packages/sloan-bboard/www/forum-delete-2.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-delete-2.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-delete-2.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="messages_delete">      
+      <querytext>
+
+        delete from bboard_forum_message_map 
+         where forum_id = :forum_id
+
+      </querytext>
+
+</fullquery>
+
+
+<fullquery name="permissions_delete">      
+      <querytext>
+      
+	delete from acs_permissions 
+  	  where object_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/forum-delete.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-delete.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-delete.adp	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,14 @@
+<master src="master">
+<property name="context_bar">@context_bar@</property>
+<property name="title">@forum_name@</property>
+
+<h3>Delete @forum_name@ forum?</h3>
+
+You have chosen to delete the @forum_name@ forum.<p>  This forum and its
+messages (@message_count@) will be <strong>irrevocably deleted</strong>.<p>
+
+<form method="post" action="forum-delete-2">
+<input type="hidden" name="forum_id" value="@forum_id@">
+<input type="submit" value="Delete Forum">
+</form>
+
Index: openacs-4/packages/sloan-bboard/www/forum-delete.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-delete.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-delete.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,34 @@
+ad_page_contract {
+    Presents confirmation screen for deleting a forum.
+
+    @author Anukul Kapoor (akk@arsdigita.com)
+    @creation-date 2000-30-11
+    @cvs-id $Id: forum-delete.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+} {
+    forum_id:integer,notnull,bboard_forum_id
+} -properties {
+    forum_id:onevalue
+    short_name:onevalue
+    charter:onevalue
+}
+
+set package_id [ad_conn package_id]
+
+set context_bar {}
+set user_id [ad_verify_and_get_user_id]
+
+ad_require_permission $forum_id admin
+
+db_1row forum_info {
+    select short_name as forum_name, charter as forum_charter
+    from bboard_forums
+    where forum_id = :forum_id
+}
+
+db_1row forum_message_count {
+    select count(*) as message_count
+    from bboard_forum_message_map bfmm
+    where bfmm.forum_id = :forum_id
+}
+
+ad_return_template
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/forum-delete.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-delete.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-delete.xql	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="forum_info">      
+      <querytext>
+      
+    select short_name as forum_name, charter as forum_charter
+    from bboard_forums
+    where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="forum_message_count">      
+      <querytext>
+      
+    select count(*) as message_count
+    from bboard_forum_message_map bfmm
+    where bfmm.forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/forum-edit-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-edit-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-edit-2.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,36 @@
+ad_page_contract {
+
+    Save changes to a forum.
+
+    @author John Prevost <jprevost@arsdigita.com>
+    @creation-date 2000-09-07
+    @cvs-id $Id: forum-edit-2.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+
+    @param forum_id    The ID of the forum to be changed
+    @param short_name  The short name of the forum
+    @param charter     The long description (charter) of the forum
+    @param moderated_p Should the forum be moderated?
+} {
+    forum_id:integer,notnull,bboard_forum_id
+    short_name:notnull,trim
+    charter:trim
+    {moderated_p:optional ""}
+} 
+
+ad_require_permission $forum_id admin
+
+if [empty_string_p $moderated_p] {
+    set moderated_p "f"
+} else {
+    set moderated_p "t"
+}
+
+set package_id [ad_conn package_id]
+
+db_transaction {
+    bboard_forum_set -forum_id $forum_id -short_name $short_name \
+	    -charter $charter -moderated_p $moderated_p
+}
+# on error ...
+
+ad_returnredirect "."
Index: openacs-4/packages/sloan-bboard/www/forum-edit.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-edit.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-edit.tcl	15 Feb 2002 21:27:06 -0000	1.1
@@ -0,0 +1,34 @@
+ad_page_contract {
+
+    Displays a form for editing a forum.
+
+    @author John Prevost (jmp@arsdigita.com)
+    @creation-date 2000-09-07
+    @cvs-id $Id: forum-edit.tcl,v 1.1 2002/02/15 21:27:06 ben Exp $
+
+} {
+    forum_id:integer,notnull,bboard_forum_id
+} -properties {
+    context_bar:onevalue
+    forum_id:onevalue
+    title:onevalue
+    action:onevalue
+    submit_label:onevalue
+    short_name:onevalue
+    charter:onevalue
+    moderated_p:onevalue
+}
+
+ad_require_permission $forum_id admin
+
+db_1row forum_info {
+    select short_name, charter, moderated_p from bboard_forums
+      where forum_id = :forum_id
+}
+
+set context_bar {"Edit a Forum"}
+set title "Edit a Forum"
+set action "forum-edit-2"
+set submit_label "Save Changes"
+
+ad_return_template "forum-entry"
Index: openacs-4/packages/sloan-bboard/www/forum-edit.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-edit.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-edit.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="forum_info">      
+      <querytext>
+      
+    select short_name, charter, moderated_p from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/forum-entry.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-entry.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-entry.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,31 @@
+<master src="master">
+<property name="context_bar">@context_bar@</property>
+<property name="title">@title@</property>
+
+<form action="@action@" method="POST">
+ <input type="hidden" name="forum_id" value="@forum_id@">
+ <blockquote>
+  <table>
+   <tr>
+    <th align="right">Short Name:</th>
+    <td><input size="50" name="short_name" value="@short_name@"></td>
+   </tr>
+   <tr valign="top">
+    <th align="right"><br>Charter (optional):</td>
+    <td><textarea name="charter" rows="20" cols="50"><%= [ns_quotehtml $charter] %></textarea></td>
+   </tr>
+   <tr>
+    <th align="right">Moderated:</td>
+    <if @moderated_p@ eq "t">
+     <td><input type="checkbox" name="moderated_p" checked></td>
+    </if>
+    <else>
+     <td><input type="checkbox" name="moderated_p"></td>
+    </else>
+   </tr>
+   <tr>
+    <th></th>
+    <td><input type="submit" value="@submit_label@"></td>
+  </table>
+ </blockquote>
+</form>
Index: openacs-4/packages/sloan-bboard/www/forum-move-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-move-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-move-2.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,41 @@
+ad_page_contract {
+    
+    Move a forum's messages to another forum.
+
+    @author Anukul Kapoor <akk@arsdigita.com>
+    @creation-date 2001-04-12
+    @cvs-id $Id: forum-move-2.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    forum_id:integer,notnull,bboard_forum_id
+    dest_forum_id:integer,notnull,bboard_forum_id
+}
+
+ad_require_permission $forum_id admin
+ad_require_permission $dest_forum_id admin
+
+set user_id [ad_conn user_id]
+
+db_transaction {
+    db_dml update_bboard_contexts {
+	update acs_objects
+	    set context_id = :dest_forum_id
+	    where context_id = :forum_id
+	          and (object_type = 'acs_message' or
+                       object_type = 'bboard_category')
+    }
+
+    db_dml move_bboard_messages {
+        update bboard_forum_message_map 
+            set forum_id = :dest_forum_id
+            where forum_id = :forum_id
+    }
+
+    db_dml move_bboard_categories {
+	update bboard_categories
+	    set forum_id = :dest_forum_id
+            where forum_id = :forum_id
+    }
+}
+
+ad_returnredirect "forum?forum_id=$forum_id"
Index: openacs-4/packages/sloan-bboard/www/forum-move-2.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-move-2.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-move-2.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="update_bboard_contexts">      
+      <querytext>
+      
+	update acs_objects
+	    set context_id = :dest_forum_id
+	    where context_id = :forum_id
+	          and (object_type = 'acs_message' or
+                       object_type = 'bboard_category')
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="move_bboard_messages">      
+      <querytext>
+      
+        update bboard_forum_message_map 
+            set forum_id = :dest_forum_id
+            where forum_id = :forum_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="move_bboard_categories">      
+      <querytext>
+      
+	update bboard_categories
+	    set forum_id = :dest_forum_id
+            where forum_id = :forum_id
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/forum-move.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-move.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-move.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,28 @@
+<master src="master">
+<property name="title">Move a forum's messages</property>
+<property name="context_bar">Move</property>
+
+<form action="forum-move-2" method="POST">
+ @form_data@
+
+<blockquote> <table>
+
+<tr><th>Forum:</th><td>@forum_name@</td></tr>
+<tr><th>Charter:</th>
+ <td valign="top">
+ @charter@</td>
+</tr></table>
+ <p>
+
+Move to this forum's messages to: <select name="dest_forum_id">
+	  <multiple name="forums">
+	    <option value="@forums.forum_id@">@forums.short_name@</option>
+	  </multiple>
+	</select> forum?
+<br>
+This will <strong>move all of this forum's messages and categories</strong> and is not easily undoable.
+
+
+ <blockquote><input type="submit" value="Confirm"></blockquote>
+ </blockquote>
+</form>
Index: openacs-4/packages/sloan-bboard/www/forum-move.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-move.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-move.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,40 @@
+ad_page_contract {
+    
+    Confirmation screem for moving a forum's messages to another forum.
+
+    @author Anukul Kapoor <akk@arsdigita.com>
+    @creation-date 2001-04-12
+    @cvs-id $Id: forum-move.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    forum_id:integer,notnull,bboard_forum_id
+} -properties {
+    forum_id:onevalue
+    forum_name:onevalue
+    charter:onevalue
+    forums:multirow
+}
+
+ad_require_permission $forum_id admin
+
+set user_id [ad_conn user_id]
+
+db_1row forum_info {
+    select short_name as forum_name, charter, moderated_p from bboard_forums
+      where forum_id = :forum_id
+}
+
+db_multirow forums allowed_target_forums {
+    select forum_id, short_name
+      from bboard_forums
+      where not forum_id = :forum_id
+        and exists (select 1 from acs_object_party_privilege_map
+                      where object_id = forum_id
+                        and party_id in (:user_id, -1)
+                        and privilege = 'admin')
+
+}
+
+set form_data [export_form_vars forum_id]
+
+ad_return_template
Index: openacs-4/packages/sloan-bboard/www/forum-move.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-move.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-move.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="forum_info">      
+      <querytext>
+      
+    select short_name as forum_name, charter, moderated_p from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="allowed_target_forums">      
+      <querytext>
+      
+    select forum_id, short_name
+      from bboard_forums
+      where not forum_id = :forum_id
+        and exists (select 1 from all_object_party_privilege_map
+                      where object_id = forum_id
+                        and party_id in (:user_id, -1)
+                        and privilege = 'admin')
+
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/forum-new-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-new-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-new-2.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,38 @@
+ad_page_contract {
+
+    Create a new forum.
+
+    @author John Prevost <jprevost@arsdigita.com>
+    @creation-date 2000-08-30
+    @cvs-id $Id: forum-new-2.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+    @param forum_id    The ID of the new forum to be created (debounce)
+    @param short_name  The short name of the forum
+    @param charter     The long description (charter) of the forum
+    @param moderated_p Should the forum be moderated?
+} {
+    forum_id:integer,notnull
+    short_name:notnull,trim
+    charter:trim
+    {moderated_p:optional ""}
+}
+
+ad_require_permission [ad_conn package_id] admin
+
+if [empty_string_p $moderated_p] {
+    set moderated_p "f"
+} else {
+    set moderated_p "t"
+}
+
+set package_id [ad_conn package_id]
+
+db_transaction {
+    bboard_forum_new -forum_id $forum_id -short_name $short_name \
+	    -charter $charter -moderated_p $moderated_p \
+	    -bboard_id $package_id -creation_user [ad_verify_and_get_user_id] \
+	    -creation_ip [ad_conn peeraddr] -context_id $package_id
+}
+# on error ...
+
+ad_returnredirect "."
Index: openacs-4/packages/sloan-bboard/www/forum-new.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-new.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-new.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,31 @@
+ad_page_contract {
+
+    Displays a form for creating a new forum.
+
+    @author John Prevost (jmp@arsdigita.com)
+    @creation-date 2000-08-29
+    @cvs-id $Id: forum-new.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+} {
+} -properties {
+    context_bar:onevalue
+    forum_id:onevalue
+    title:onevalue
+    action:onevalue
+    submit_label:onevalue
+    short_name:onevalue
+    charter:onevalue
+}
+
+ad_require_permission [ad_conn package_id] admin
+
+set context_bar {"Create a Forum"}
+set title "Create a Forum"
+set action "forum-new-2"
+set submit_label "Create Forum"
+set short_name ""
+set charter ""
+set moderated_p "f"
+
+set forum_id [db_nextval acs_object_id_seq]
+
+ad_return_template "forum-entry"
Index: openacs-4/packages/sloan-bboard/www/forum-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-oracle.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="forum_info">      
+      <querytext>
+      
+    select short_name as forum_name, moderated_p,
+       acs_permission.permission_p(:forum_id, :user_id, 'admin') as admin_p,
+       acs_permission.permission_p(:forum_id, :user_id, 'bboard_create_category') 
+          as category_create_p
+      from bboard_forums
+     where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="messages_select">      
+      <querytext>
+      
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name,
+	       to_char(last_reply_date,'MM/DD/YY hh12:Mi am') as last_updated
+          from bboard_messages_all b, persons
+          where forum_id = :forum_id
+	    and sent_date > case when :last_n_days = 0 then '1976-01-01' else to_char(sysdate - :last_n_days) end
+	    and person_id = sender
+            and reply_to is null
+	order by sent_date desc
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="categories_select">      
+      <querytext>
+      
+	select c.category_id, c.short_name,
+             count(m.message_id) as message_count
+	  from bboard_categories c,
+	       (select c.category_id, c.message_id
+	          from bboard_category_message_map c,
+	               bboard_forum_message_map f
+	          where c.message_id = f.message_id
+                    and f.forum_id = :forum_id) m
+	  where c.forum_id = :forum_id
+            and m.category_id(+) = c.category_id
+	    and (m.message_id is null 
+                or m.message_id in (select f.message_id
+                                     from bboard_forum_message_map f
+                                     where f.forum_id = :forum_id))
+	  group by c.category_id, short_name
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="messages_select_approved">      
+      <querytext>
+      
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name,
+	       to_char(last_reply_date,'MM/DD/YY hh12:Mi am') as last_updated
+          from bboard_messages_all b, persons
+          where forum_id = :forum_id
+	    and sent_date > case when :last_n_days = 0 then '1976-01-01' else to_char(sysdate - :last_n_days) end
+	    and person_id = sender
+            and reply_to is null
+	    and status = 'approved'
+	order by sent_date desc
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="categories_select_approved">      
+      <querytext>
+      
+	select c.category_id, c.short_name,
+             count(m.message_id) as message_count
+	  from bboard_categories c,
+	       (select c.category_id, c.message_id
+	          from bboard_category_message_map c,
+	               bboard_forum_message_map f
+	          where c.message_id = f.message_id
+                    and f.status = 'approved'
+                    and f.forum_id = :forum_id) m
+	  where c.forum_id = :forum_id
+            and m.category_id(+) = c.category_id
+	    and (m.message_id is null 
+                or m.message_id in (select f.message_id
+                                     from bboard_forum_message_map f
+                                     where f.forum_id = :forum_id))
+	  group by c.category_id, short_name
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="unapproved_none">      
+      <querytext>
+      
+	select 1 from dual where 1 = 0
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="rejected_none">      
+      <querytext>
+      
+	select 1 from dual where 1 = 0
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/forum-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-postgresql.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="forum_info">      
+      <querytext>
+      
+    select short_name as forum_name, moderated_p,
+       acs_permission__permission_p(:forum_id, :user_id, 'admin') as admin_p,
+       acs_permission__permission_p(:forum_id, :user_id, 'bboard_create_category') 
+          as category_create_p
+      from bboard_forums
+     where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+
+<fullquery name="messages_select">      
+      <querytext>
+      
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name,
+	       to_char(last_reply_date,'MM/DD/YY hh12:MI am') as last_updated
+          from bboard_messages_all b, persons
+          where forum_id = :forum_id
+            and age(sent_date) < case when :last_n_days = 0 
+                                 then interval '99 years'
+                                 else interval '$last_n_days days'
+                                 end
+	    and person_id = sender
+            and reply_to is null
+	order by sent_date desc
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="categories_select">      
+      <querytext>
+    
+        select short_name, count(message_id) as message_count, category_id
+        from bboard_forum_message_map f join
+             (bboard_categories c left outer join bboard_category_message_map m using (category_id))
+             using (message_id)
+        where f.forum_id = :forum_id
+        group by category_id, short_name
+        order by category_id;
+  
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="messages_select_approved">      
+      <querytext>
+      
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name,
+	       to_char(last_reply_date,'MM/DD/YY hh12:MI am') as last_updated
+          from bboard_messages_all b, persons
+          where forum_id = :forum_id
+            and age(sent_date) < case when :last_n_days = 0 
+                                 then interval '99 years'
+                                 else interval '$last_n_days days'
+                                 end
+	    and person_id = sender
+            and reply_to is null
+	    and status = 'approved'
+	order by sent_date desc
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="categories_select_approved">      
+      <querytext>
+
+        select short_name, count(message_id) as message_count, category_id
+        from bboard_forum_message_map f join
+             (bboard_categories c left outer join bboard_category_message_map m using (category_id))
+             using (message_id)
+        where f.forum_id = :forum_id
+          and f.status = 'approved'
+        group by category_id, short_name
+        order by category_id;
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="unapproved_none">      
+      <querytext>
+      
+	select 1  where 1 = 0
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="rejected_none">      
+      <querytext>
+      
+	select 1  where 1 = 0
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/forum-subscribe.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-subscribe.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-subscribe.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,21 @@
+ad_page_contract {
+
+    Subscribe the current user to a given forum.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-10-28
+    @cvs-id $Id: forum-subscribe.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    forum_id:integer,notnull,bboard_forum_id
+}
+
+# Not strictly right
+ad_require_permission $forum_id bboard_create_message
+
+catch {
+    bboard_subscribe_forum \
+	-forum_id $forum_id -subscriber_id [ad_verify_and_get_user_id]
+}
+
+ad_returnredirect "forum?forum_id=$forum_id"
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/forum-unsubscribe.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-unsubscribe.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-unsubscribe.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,23 @@
+ad_page_contract {
+
+    Unsubscribe the current user from a given forum.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-10-28
+    @cvs-id $Id: forum-unsubscribe.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    forum_id:integer,notnull,bboard_forum_id
+    {sub_page ""}
+}
+
+catch {
+    bboard_unsubscribe_forum \
+	-forum_id $forum_id -subscriber_id [ad_verify_and_get_user_id]
+}
+
+if [empty_string_p $sub_page] {
+    ad_returnredirect "forum?forum_id=$forum_id"
+} else {
+    ad_returnredirect "subscriptions"
+}
Index: openacs-4/packages/sloan-bboard/www/forum-view.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum-view.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum-view.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,110 @@
+<master src="master">
+<property name="context_bar">@context_bar@</property>
+<property name="title">@title@</property>
+
+<table width="100%" cellspacing="0" cellpadding="0"><tr><td>
+ <if @category_id@ not nil>
+  [ <b><a href="message-new?forum_id=@forum_id@&category_id=@category_id@">Post a message</a></b> ]
+ </if>
+ <else>
+  [<b><a href="message-new?forum_id=@forum_id@">Post a message</a></b>]
+ </else>
+
+</if>
+</td>
+
+<td align="right">
+ <if @subscribed_p@ eq 0>
+  <if @category_id@ not nil>
+   [<a href="category-subscribe?category_id=@category_id@">Subscribe to Category</a>]
+  </if>
+  <else>
+   [<a href="forum-subscribe?forum_id=@forum_id@">Subscribe to Forum</a>]
+  </else>
+ </if>
+ <else>
+  <if @category_id@ not nil>
+   You're subscribed to this category [<a href="category-unsubscribe?category_id=@category_id@">Unsubscribe</a>]
+  </if>
+  <else>
+   You're subscribed to this forum [<a href="forum-unsubscribe?forum_id=@forum_id@">Unsubscribe</a>]
+  </else>
+ </else>
+</td>
+</tr></table><p>
+
+<table width="100%" cellspacing="0" cellpadding="0"><tr><td>
+<h3>Messages</h3><td>
+
+ <if @last_n_days@ not nil and @last_n_days@ ne 0>
+ <td align="right"> Last @last_n_days@ days.  <a href="forum?forum_id=@forum_id@&last_n_days=0">Show All Messages</a>.</td>
+ </if>
+</tr></table>
+
+<if @moderator_p@ ne 0>
+ <if @unapproved:rowcount@ gt 0>
+  <h4>Not Yet Approved</h4>
+  <ul>
+   <multiple name=unapproved>
+    <li><a href="<%=[bboard_message_page]%>?forum_id=@forum_id@&message_id=@unapproved.message_id@">@unapproved.title@</a>
+     (@unapproved.num_replies@)  &nbsp; @unapproved.full_name@
+     [<a href="message-approve?forum_id=@forum_id@&message_id=@unapproved.message_id@">approve</a>]
+     [<a href="message-reject?forum_id=@forum_id@&message_id=@unapproved.message_id@">reject</a>]
+    </li>   
+   </multiple>
+  </ul>
+  <h4>Approved</h4>
+ </if>
+</if>
+
+<include src="message-list" &=messages forum_id="@forum_id@" last_updated_p="t" top_p="t"/>
+
+<if @moderator_p@ ne 0>
+ <if @rejected:rowcount@ gt 0>
+  <h4>Rejected</h4>
+  <ul>
+   <multiple name=rejected>
+    <li><a href="<%=[bboard_message_page]%>?forum_id=@forum_id@&message_id=@rejected.message_id@">@rejected.title@</a>
+     (@rejected.num_replies@) &nbsp; @rejected.full_name@
+    </li>   
+   </multiple>
+  </ul>
+ </if>
+</if>
+
+<if @categories:rowcount@ ne 0 or @category_create_p@ ne 0>
+ <h3>By Category</h3>
+</if>
+<if @categories:rowcount@ ne 0>
+ <ul>
+  <multiple name=categories>
+   <li><a href="forum-by-category?forum_id=@forum_id@&category_id=@categories.category_id@">@categories.short_name@</a>
+    (@categories.message_count@)
+    <if @admin_p@ eq "t">
+     [<a href="category-edit?category_id=@categories.category_id@">edit</a>]
+     [<a href="category-delete?category_id=@categories.category_id@">delete</a>]
+    </if>
+   </li>
+  </multiple>
+  <li><a href="forum-by-category?forum_id=@forum_id@&category_id=">Uncategorized</a>(@uncategorized_count@)</li>
+ </ul>
+</if>
+
+<if @category_create_p@ ne 0>
+ [<a href="category-new?forum_id=@forum_id@">Create a category</a>]
+</if> <p>
+
+<h3>Search</h3>
+<form method="get" action="search">
+ <input type="hidden" name="forum_id" value="@forum_id@">
+ <input type="text" name="query"> 
+ <input type="submit" value="Go!">
+</form>
+
+<p>
+
+<if @admin_p@ eq "t">
+ <h3>Admin</h3>
+ [<a href="forum-move?forum_id=@forum_id@">Move messages to other forum</a>]
+ [<a href="/permissions/one?object_id=@forum_id@">Set Permissions</a>]
+</if>
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/forum.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,179 @@
+ad_page_contract {
+
+    Displays a list of messages in a forum
+
+    @author John Prevost (jmp@arsdigita.com)
+    @creation-date 2000-08-29
+    @cvs-id $Id: forum.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+} {
+    forum_id:integer,notnull
+    {last_n_days:integer,optional ""}
+} -properties {
+    forum_write_p:onevalue
+    forum_create_p:onevalue
+    context_bar:onevalue
+    title:onevalue
+    forum_name:onevalue
+    forum_id:onevalue
+    messages:multirow
+    categories:multirow
+    moderator_p:onevalue
+    unapproved:multirow
+    rejected:multirow
+    subscribed_p:onevalue
+    last_n_days:onevalue
+    uncategorized_count:onevalue
+}
+
+set user_id [ad_verify_and_get_user_id]
+
+ad_require_permission $forum_id bboard_read_forum
+
+db_1row forum_info {
+    select short_name as forum_name, moderated_p,
+       acs_permission.permission_p(:forum_id, :user_id, 'admin') as admin_p,
+       acs_permission.permission_p(:forum_id, :user_id, 'bboard_create_category') 
+          as category_create_p
+      from bboard_forums
+     where forum_id = :forum_id
+}
+
+set moderator_p 0
+
+if [string equal $moderated_p "t"] {
+    set moderator_p [ad_permission_p $forum_id bboard_moderate_forum]
+}
+
+
+if [string equal [bboard_forum_subscribed_p $user_id $forum_id] "t"] {
+    set subscribed_p 1
+} else {
+    set subscribed_p 0
+}
+
+if [string equal $last_n_days ""] {
+    set last_n_days [ad_parameter DisplayLastNDays]
+    
+    if [string equal $last_n_days ""] {
+	set last_n_days "0"
+    }
+}
+
+set context_bar [list $forum_name]
+set title $forum_name
+
+set package_id [ad_conn package_id]
+
+if [string equal $moderated_p "f"] {
+
+    db_multirow messages messages_select {
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name,
+	       to_char(last_reply_date,'MM/DD/YY hh12:Mi am') as last_updated
+          from bboard_messages_all b, persons
+          where forum_id = :forum_id
+	    and sent_date > decode(:last_n_days, 0, '1976-01-01', sysdate - :last_n_days)
+	    and person_id = sender
+            and reply_to is null
+	order by sent_date desc
+    }
+
+    db_multirow categories categories_select {
+ 	select c.category_id, short_name, count(m.message_id) as message_count
+	  from bboard_categories c,
+	       bboard_category_message_map m
+	  where c.forum_id = :forum_id
+            and m.category_id(+) = c.category_id
+	    and (m.message_id is null 
+                or m.message_id in (select f.message_id
+                                     from bboard_forum_message_map f
+                                     where f.forum_id = :forum_id))
+	  group by c.category_id, short_name
+    }
+
+    db_1row uncategorized_count {
+	select count(*) as uncategorized_count
+            from bboard_messages_by_category b
+	    where category_id is null
+	          and forum_id = :forum_id
+    }
+
+
+} else {
+
+    db_multirow messages messages_select_approved {
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name,
+	       to_char(last_reply_date,'MM/DD/YY hh12:Mi am') as last_updated
+          from bboard_messages_all b, persons
+          where forum_id = :forum_id
+	    and sent_date > decode(:last_n_days, 0, '1976-01-01', sysdate - :last_n_days)
+	    and person_id = sender
+            and reply_to is null
+	    and status = 'approved'
+	order by sent_date desc
+    }
+
+    db_multirow categories categories_select_approved {
+	select c.category_id, c.short_name,
+             count(m.message_id) as message_count
+	  from bboard_categories c,
+	       (select c.category_id, c.message_id
+	          from bboard_category_message_map c,
+	               bboard_forum_message_map f
+	          where c.message_id = f.message_id
+                    and f.status = 'approved'
+                    and f.forum_id = :forum_id) m
+	  where c.forum_id = :forum_id
+            and m.category_id(+) = c.category_id
+	    and (m.message_id is null 
+                or m.message_id in (select f.message_id
+                                     from bboard_forum_message_map f
+                                     where f.forum_id = :forum_id))
+	  group by c.category_id, short_name
+    }
+
+    db_1row uncategorized_approved_count {
+	select count(*) as uncategorized_count
+            from bboard_messages_by_category b
+	    where category_id is null
+	          and forum_id = :forum_id
+    }
+
+}
+
+if { !$moderator_p } {
+
+    db_multirow unapproved unapproved_none {
+	select 1 from dual where 1 = 0
+    }
+
+    db_multirow rejected rejected_none {
+	select 1 from dual where 1 = 0
+    }
+
+} else {
+
+    db_multirow unapproved messages_select_unmoderated {
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name
+	  from bboard_messages_all, persons
+	  where forum_id = :forum_id
+	    and person_id = sender
+	    and reply_to is null
+	    and status = 'unmoderated'
+    }
+
+    db_multirow rejected rejected_messages_select {
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name
+	  from bboard_messages_all, persons
+	  where forum_id = :forum_id
+	    and person_id = sender
+	    and reply_to is null
+	    and status = 'rejected'
+    }
+
+}
+
+ad_return_template "forum-view"
Index: openacs-4/packages/sloan-bboard/www/forum.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/forum.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/forum.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="uncategorized_count">      
+      <querytext>
+      
+	select count(*) as uncategorized_count
+            from bboard_forum_message_map msg
+	    where forum_id = :forum_id
+              and not exists (select 1
+                              from bboard_category_message_map cat
+                              where msg.message_id = cat.message_id)
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="uncategorized_approved_count">      
+      <querytext>
+      
+	select count(*) as uncategorized_count
+            from bboard_forum_message_map msg
+	    where forum_id = :forum_id
+              and status = 'approved'
+              and not exists (select 1
+                              from bboard_category_message_map cat
+                              where msg.message_id = cat.message_id)
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="messages_select_unmoderated">      
+      <querytext>
+      
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name
+	  from bboard_messages_all, persons
+	  where forum_id = :forum_id
+	    and person_id = sender
+	    and reply_to is null
+	    and status = 'unmoderated'
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="rejected_messages_select">      
+      <querytext>
+      
+	select message_id, title, num_replies,
+               first_names||' '||last_name as full_name
+	  from bboard_messages_all, persons
+	  where forum_id = :forum_id
+	    and person_id = sender
+	    and reply_to is null
+	    and status = 'rejected'
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/index-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/index-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/index-oracle.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="forums_select">      
+      <querytext>
+      
+    select forum_id, short_name, moderated_p, charter 
+      from bboard_forums f
+      where bboard_id = :package_id
+        and acs_permission.permission_p(forum_id,:user_id,'bboard_read_forum') = 't'
+    order by short_name
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/index-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/index-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/index-postgresql.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="forums_select">      
+      <querytext>
+      
+    select forum_id, short_name, moderated_p, charter
+      from bboard_forums f
+      where bboard_id = :package_id
+        and acs_permission__permission_p(forum_id,:user_id,'bboard_read_forum') = 't'
+    order by short_name
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/index.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/index.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/index.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,39 @@
+<master src="master">
+<property name="context_bar">@context_bar@</property>
+<property name="title">Forums</property>
+
+[<a href="subscriptions">Manage Subscriptions</a>]
+
+<if @forums:rowcount@ eq 0>
+ <i>There are no forums available.</i><p>
+</if>
+
+<else>
+ <ul>
+  <multiple name=forums>
+   <li><a href="forum?forum_id=@forums.forum_id@">@forums.short_name@</a>
+    <if @forums.moderated_p@ eq "t">
+     (moderated)
+    </if>
+    <if @admin_p@ ne "0">
+     [<a href="forum-edit?forum_id=@forums.forum_id@">edit</a>]
+     [<a href="forum-delete?forum_id=@forums.forum_id@">delete</a>]
+    </if>
+    <if @forums.charter@ ne "">
+    <br />
+    @forums.charter@
+    <br />
+    </if>
+   </li>
+  </multiple>
+ </ul>
+</else>
+
+<p />
+
+<if @admin_p@ ne 0>
+ [<a href="forum-new">Create a forum</a>]
+ [<a href="/admin/site-map/parameter-set?package_id=@package_id@">Set Parameters</a>] 
+ [<a href="/permissions/one?object_id=@package_id@">Admin Permissions</a>]
+</if>
+<p>
Index: openacs-4/packages/sloan-bboard/www/index.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/index.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/index.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,32 @@
+ad_page_contract {
+
+    Displays a list of forums on the site
+
+    @author John Prevost (jmp@arsdigita.com)
+    @creation-date 2000-08-29
+    @cvs-id $Id: index.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+} {
+} -properties {
+  context_bar:onevalue
+  package_id:onevalue
+  user_id:onevalue
+  forums:multirow
+}
+
+set package_id [ad_conn package_id]
+
+set context_bar {}
+
+set user_id [ad_verify_and_get_user_id]
+
+set admin_p [ad_permission_p $package_id admin]
+
+db_multirow forums forums_select {
+    select forum_id, short_name, moderated_p, charter 
+      from bboard_forums f
+      where bboard_id = :package_id
+        and acs_permission.permission_p(forum_id,:user_id,'bboard_read_forum') = 't'
+    order by short_name
+}
+
+ad_return_template
Index: openacs-4/packages/sloan-bboard/www/master.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/master.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/master.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,9 @@
+<master>
+<property name="title">@title@</property>
+
+<h2>@title@</h2>
+ <if @context_bar@ not nil>
+  <%= [eval ad_context_bar $context_bar] %>
+ </if>
+<hr>
+<slave>
Index: openacs-4/packages/sloan-bboard/www/message-approve.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-approve.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-approve.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,27 @@
+ad_page_contract {
+    
+    Marks a message as approved for display in a moderated forum.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-09-10
+    @cvs-id $Id: message-approve.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    message_id:integer,notnull,acs_message_id
+    forum_id:integer,notnull,bboard_forum_id
+}
+
+ad_require_permission $forum_id bboard_moderate_forum
+
+bboard_message_set_status -message_id $message_id -forum_id $forum_id \
+	-status "approved"
+
+db_1row sender_info {
+    select sender from acs_messages where message_id = :message_id
+}
+
+# Should this check if it was already approved?
+bboard_alert_one_mesg -message_id $message_id -forum_id $forum_id \
+	-user_id $sender -creation_ip [ad_conn peeraddr]
+
+ad_returnredirect "forum?forum_id=$forum_id"
Index: openacs-4/packages/sloan-bboard/www/message-approve.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-approve.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-approve.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="sender_info">      
+      <querytext>
+      
+    select sender from acs_messages where message_id = :message_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-attach-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-attach-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-attach-2.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,72 @@
+ad_page_contract {
+
+    We will do the grunt work here of creating an attachment.
+
+    @author Anukul Kapoor (akk@arsdigita.com)
+    @creation-date 2000-12-18
+    @cvs $Id: message-attach-2.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    message_id:integer,notnull
+    file_id:integer,notnull
+    file_title:notnull
+    upload_file:notnull
+    upload_file.tmpfile:tmpfile
+} 
+
+ad_require_permission $message_id bboard_write_message
+
+# authenticate the user
+set user_id [ad_verify_and_get_user_id]
+
+# aolserver will give us a guessed mime type for the upload
+set guessed_file_type [ns_guesstype $upload_file]
+
+# let us get the useful bits out of the long filename
+set full_filename ${upload_file.tmpfile}
+set base_filename [bboard_upload_basename $upload_file]
+set file_ext [bboard_upload_extension $full_filename]
+
+# check file size against user parameters
+
+set n_bytes [file size $full_filename]
+set max_file_size [ad_parameter MaxAttachmentSize]
+
+if { $n_bytes > $max_file_size && $max_file_size > 0 } {
+    ad_return_complaint 1 "Your file is too large.  The publisher of
+                 [ad_system_name] has chosen to limit attachments to
+                 [util_commify_number $max_file_size] bytes.\n"
+}
+if { $n_bytes == 0 } {
+    ad_return_complaint 1 "Your file is zero-length.  Either you attempted to
+                 upload a zero length file, a file which does not exists, 
+                 or something went wrong during the transfer.\n"
+}
+
+
+# insert the file into the database
+
+db_transaction {
+
+    # check for and add MIME types missing from cr mime types table
+    bboard_check_and_register_mime_type $guessed_file_type
+
+    if { $file_ext == "jpeg" || $file_ext == "jpg" || $file_ext == "gif" } {
+	set image_size [bboard_image_size $file_ext $upload_file]
+	set width [lindex $image_size 0]
+	set height [lindex $image_size 1]
+	
+	bboard_attach_image -message_id $message_id -file_id $file_id \
+		-short_filename $base_filename -local_filename $full_filename\
+		-mime_type $guessed_file_type -user_id $user_id \
+		-creation_ip [ad_conn peeraddr] -title $file_title \
+		-width $width -height $height
+    } else {
+	bboard_attach_file -message_id $message_id -file_id $file_id \
+		-short_filename $base_filename -local_filename $full_filename\
+		-mime_type $guessed_file_type -user_id $user_id \
+		-creation_ip [ad_conn peeraddr] -title $file_title
+    }
+}
+
+ad_returnredirect [bboard_message_url $message_id]
Index: openacs-4/packages/sloan-bboard/www/message-attach.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-attach.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-attach.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,28 @@
+<master src="master">
+<property name="title">@title@</property>
+<property name="context_bar">@context_bar@</property>
+
+<form enctype="multipart/form-data" method=POST action="message-attach-2">
+<%= [export_form_vars file_id message_id] %>
+
+<blockquote>
+<table>
+  <tr>
+    <td valign="top" align="right">Title:</td>
+    <td><input size="40" name="file_title" value=""></td>
+  </tr>
+  <tr>
+    <td valign="top" align="right">Filename: </td>
+    <td>
+     <input type="file" name="upload_file" size="40"><br>
+     <span class="note">Use the "Browse..." button to locate your file, then click "Open".</span>
+    </td>
+  </tr>
+</table>
+</blockquote>
+
+<p>
+<center>
+<input type=submit value="Proceed">
+</center>
+</form>
Index: openacs-4/packages/sloan-bboard/www/message-attach.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-attach.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-attach.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,27 @@
+ad_page_contract {
+
+    This page presents a form for creating a message attachment.
+
+    @author Anukul Kapoor (akk@arsdigita.com)
+    @creation-datee 2000-12-18
+    @cvs $Id: message-attach.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    forum_id:integer,notnull,bboard_forum_id
+    message_id:integer,notnull
+} -properties {
+    title:onevalue
+    context_bar:onevalue
+    file_id:onevalue
+    message_id:onevalue
+    forum_id:onevalue
+}
+
+ad_require_permission $message_id bboard_write_message
+
+set title "Upload message attachment"
+set context_bar ""
+
+set file_id [db_nextval acs_object_id_seq]
+
+ad_return_template
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/message-delete-2-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-delete-2-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-delete-2-oracle.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="bboard_delete_threads">      
+      <querytext>
+      
+	delete from bboard_forum_message_map bfm
+	    where message_id in (select message_id
+                                     from acs_messages m
+                                     connect by prior message_id = reply_to
+                                     start with message_id = :message_id)
+                  and exists (select 1 from all_object_party_privilege_map
+                                  where object_id = bfm.message_id
+                                        and party_id in (:user_id, -1)
+                                        and privilege = 'bboard_delete_message')
+
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-delete-2-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-delete-2-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-delete-2-postgresql.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="bboard_delete_threads">      
+      <querytext>
+
+	delete from bboard_forum_message_map
+        where message_id in
+          (select m.message_id
+           from acs_messages m, acs_messages m2
+           where m2.message_id = :message_id
+             and m.tree_sortkey between m2.tree_sortkey and tree_right(m2.tree_sortkey))
+          and exists (select 1 from all_object_party_privilege_map
+                      where object_id = message_id
+                        and party_id = :user_id
+                        and privilege = 'bboard_delete_message')
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-delete-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-delete-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-delete-2.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,41 @@
+ad_page_contract {
+
+    Delete a message
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-09-06
+    @cvs-id $Id: message-delete-2.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    message_id:integer,notnull,acs_message_id
+    forum_id:integer,notnull,bboard_forum_id
+    {replies ""}
+}
+
+if {[ad_parameter "UserPostsDeletableP"] == "t"} {
+    ad_require_permission $message_id bboard_write_message
+} else {
+    ad_require_permission $message_id admin
+}
+
+set user_id [ad_verify_and_get_user_id]
+
+if [string eq $replies ""] {
+    bboard_message_set_status -message_id $message_id -forum_id $forum_id \
+	    -status [db_null]
+} else {
+    db_dml bboard_delete_threads {
+	delete from bboard_forum_message_map bfm
+	    where message_id in (select message_id
+                                     from acs_messages m
+                                     connect by prior message_id = reply_to
+                                     start with message_id = :message_id)
+                  and exists (select 1 from acs_object_party_privilege_map
+                                  where object_id = bfm.message_id
+                                        and party_id in (:user_id, -1)
+                                        and privilege = 'bboard_delete_message')
+
+    }
+}
+
+ad_returnredirect "forum?forum_id=$forum_id"
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/message-delete.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-delete.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-delete.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,24 @@
+<master src="master">
+<property name="context_bar">@context_bar@</property>
+<property name="title">Delete a Message</property>
+
+<include src="simple-message" title="@message.title@" author="@message.full_name@"
+	 mime_type="@message.mime_type@" content="@message.content@"
+	 date="@message.sent_date@" id="@message.message_id@"
+	 link_p="f" forum_id="@forum_id@">
+
+<center>
+
+<if @replies@ ne "t">
+<p>Are you sure you want to delete this message?<p>
+
+<a href="message-delete-2?forum_id=@forum_id@&message_id=@message_id@">Yes</a>
+</if>
+<else>
+<p>Are you sure you want to delete this message and all of its replies?<p>
+
+<a href="message-delete-2?forum_id=@forum_id@&message_id=@message_id@&replies=t">Yes</a> &nbsp; &nbsp;
+</else>
+&nbsp; &nbsp;
+<a href="<%= [get_referrer_and_query_string] %>">No</a>
+</center>
Index: openacs-4/packages/sloan-bboard/www/message-delete.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-delete.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-delete.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,50 @@
+ad_page_contract {
+
+    Displays a confirmation of "do you really want to delete this message?"
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-09-06
+    @cvs-id $Id: message-delete.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    message_id:integer,notnull,acs_message_id
+    forum_id:integer,notnull,bboard_forum_id
+    {replies ""}
+} -properties {
+    context_bar:onevalue
+    message_id:onevalue
+    forum_id:onevalue
+    message:onerow
+    replies:onevalue
+}
+
+if {[ad_parameter "UserPostsDeletableP"] == "t"} {
+    ad_require_permission $message_id bboard_write_message
+} else {
+    ad_require_permission $message_id admin
+}
+
+if ![db_0or1row message_info {
+        select m.message_id, m.reply_to, m.title,
+               m.sent_date, m.mime_type, m.content, 
+               p.first_names ||' '||p.last_name as full_name
+            from acs_messages_all m, persons p, bboard_forum_message_map f
+            where m.message_id = :message_id
+                and f.message_id = :message_id
+                and f.forum_id = :forum_id
+                and p.person_id = m.sender
+    } -column_array message] {
+    # It's not in that forum!
+    ad_returnredirect "forum?forum_id=$forum_id"
+    ad_script_abort
+}
+
+db_1row forum_short_name {
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+}
+
+set context_bar [list [list "forum?[export_url_vars forum_id]" $forum_name] \
+		      {"Delete Message"}]
+
+ad_return_template
Index: openacs-4/packages/sloan-bboard/www/message-delete.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-delete.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-delete.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,30 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="message_info">      
+      <querytext>
+      
+        select m.message_id, m.reply_to, m.title,
+               m.sent_date, m.mime_type, m.content, 
+               p.first_names ||' '||p.last_name as full_name
+            from acs_messages_all m, persons p, bboard_forum_message_map f
+            where m.message_id = :message_id
+                and f.message_id = :message_id
+                and f.forum_id = :forum_id
+                and p.person_id = m.sender
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="forum_short_name">      
+      <querytext>
+      
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-edit-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-edit-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-edit-2.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,74 @@
+ad_page_contract {
+    
+    Confirmation page for editing a message.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-datee 2000-09-08
+    @cvs $Id: message-edit-2.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+    @param message_id  The message to update
+    @param title       The new title
+    @param content     The new content
+    @param mime_type   The new mime type
+    @param category_id The new category
+} {
+    message_id:integer,notnull,acs_message_id
+    forum_id:integer,notnull,bboard_forum_id
+    title:notnull,trim
+    content:notnull,allhtml,trim
+    mime_type:notnull
+    category_id:integer,bboard_category_id
+} -validate {
+    content_html -requires {content mime_type} {
+        if [string eq $mime_type "text/html"] {
+            set complaint [ad_check_for_naughty_html $content]
+            if ![empty_string_p $complaint] {
+                ad_complain $complaint
+		return 0
+            }
+        }
+	return 1
+    }
+} -properties { 
+    forum_id:onevalue
+    page_title:onevalue
+    context_bar:onevalue
+    forum_name:onevalue
+    content_for_display:onevalue
+    title:onevalue
+    message_id:onevalue
+    form_vars:onevalue
+    reply_to:onevalue
+    target:onevalue
+    msg_mime_type:onevalue
+}
+
+ad_require_permission $message_id bboard_write_message
+
+db_1row forum_short_name {
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+}
+
+set target "message-edit-3"
+
+set msg_mime_type $mime_type
+
+db_1row forum_short_name {
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+}
+
+set page_title "Confirm Message Changes in $forum_name"
+
+set context_bar [list \
+        [list "forum?[export_url_vars forum_id]" $forum_name] \
+        "Confirm Message Edit"]
+
+set content_for_display [acs_messaging_format_as_html $mime_type $content]
+
+
+set form_vars [export_form_vars message_id forum_id title content \
+                                mime_type category_id reply_to]
+
+ad_return_template "message-preview"
Index: openacs-4/packages/sloan-bboard/www/message-edit-2.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-edit-2.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-edit-2.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="forum_short_name">      
+      <querytext>
+      
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="forum_short_name">      
+      <querytext>
+      
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-edit-3.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-edit-3.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-edit-3.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,50 @@
+ad_page_contract {
+    
+    Update edited message
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-datee 2000-09-08
+    @cvs $Id: message-edit-3.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+    @param message_id   The message to update
+    @param category_id  The new category
+    @param title        The new title
+    @param content      The new content
+    @param mime_type    The new mime type
+
+} {
+    forum_id:integer,notnull,bboard_forum_id
+    message_id:integer,notnull,acs_message_id
+    category_id:integer,bboard_category_id
+    title:notnull,trim
+    content:allhtml,notnull,trim
+    mime_type:notnull
+} -validate {
+    content_html -requires {content mime_type} {
+	if [string eq $mime_type "text/html"] {
+	    set complaint [ad_check_for_naughty_html $content]
+	    if ![empty_string_p $complaint] {
+		ad_complain $complaint
+	    }
+	}
+    }
+} 
+
+ad_require_permission $message_id bboard_write_message
+
+db_transaction {
+
+    bboard_message_clear_categories -message_id $message_id
+    
+    if ![empty_string_p $category_id] {
+        bboard_message_add_category -message_id $message_id \
+                -category_id $category_id
+    }
+
+    bboard_message_set -message_id $message_id -title $title \
+            -mime_type $mime_type -content $content
+
+}
+# on error ...
+
+ad_returnredirect "forum?[export_url_vars forum_id]"
Index: openacs-4/packages/sloan-bboard/www/message-edit.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-edit.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-edit.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,83 @@
+ad_page_contract {
+    
+    A form for editing a message
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-datee 2000-09-08
+    @cvs $Id: message-edit.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+    @param message_id The message to edit
+
+} {
+    message_id:integer,notnull,acs_message_id
+    forum_id:integer,notnull,bboard_forum_id
+} -properties { 
+    context_bar:onevalue
+    forum_id:onevalue
+    forum_name:onevalue
+    categories:multirow
+    category_id:onevalue
+    reply_to:onevalue
+    quote:onerow
+    has_quote:onevalue
+    page_title:onevalue
+    target:onevalue
+    title:onevalue
+    content:onevalue
+    submit_label:onevalue
+    message_id:onevalue
+    msg_mime_type:onevalue
+}
+
+ad_require_permission $message_id bboard_write_message
+
+db_1row message_info {
+    select message_id, reply_to, title, mime_type, content
+        from acs_messages_all m
+        where message_id = :message_id
+}
+
+set msg_mime_type $mime_type
+
+set category_id ""
+
+db_0or1row first_category {
+    select min(category_id) as category_id from bboard_category_message_map
+        where message_id = :message_id
+        group by message_id
+}
+
+db_1row forum_short_name {
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+}
+
+set page_title "Edit a Message in $forum_name"
+
+set target "message-edit-2"
+set submit_label "Confirm Changes"
+
+set context_bar \
+	[list [list "forum?[export_url_vars forum_id]" $forum_name] \
+              "Edit a Message"]
+
+set user_id [ad_verify_and_get_user_id]
+
+set category_pulldown_list ""
+
+db_0or1row quote_info {
+    select m.reply_to, m.title, m.sent_date,
+           m.mime_type, m.content, 
+           p.first_names||' '||p.last_name as full_name
+      from acs_messages_all m, persons p
+      where message_id = :reply_to
+        and person_id = sender
+} -column_array quote
+
+db_multirow categories category_list {
+    select c.category_id, c.short_name
+      from bboard_categories c
+      where forum_id = :forum_id
+}
+
+ad_return_template "message-entry"
Index: openacs-4/packages/sloan-bboard/www/message-edit.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-edit.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-edit.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="message_info">      
+      <querytext>
+      
+    select message_id, reply_to, title, mime_type, content
+        from acs_messages_all m
+        where message_id = :message_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="first_category">      
+      <querytext>
+      
+    select min(category_id) as category_id from bboard_category_message_map
+        where message_id = :message_id
+        group by message_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="forum_short_name">      
+      <querytext>
+      
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="quote_info">      
+      <querytext>
+      
+    select m.reply_to, m.title, m.sent_date,
+           m.mime_type, m.content, 
+           p.first_names||' '||p.last_name as full_name
+      from acs_messages_all m, persons p
+      where message_id = :reply_to
+        and person_id = sender
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="category_list">      
+      <querytext>
+      
+    select c.category_id, c.short_name
+      from bboard_categories c
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-entry.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-entry.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-entry.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,63 @@
+<master src="master">
+<property name="title">@page_title@</property>
+<property name="context_bar">@context_bar@</property>
+
+<form action="@target@" method="POST">
+ <input type="hidden" name="forum_id" value="@forum_id@">
+ <input type="hidden" name="reply_to" value="@reply_to@">
+ <if @message_id@ not nil>
+  <input type="hidden" name="message_id" value="@message_id@">
+ </if>
+ <blockquote>
+  <table>
+   <if @quote.title@ not nil>
+    <tr>
+     <th align="right" valign="top">In Reply To:</td>
+     <td>
+      <include src="simple-message" title="@quote.title@" author="@quote.full_name@"
+               date="@quote.sent_date@" mime_type="@quote.mime_type@" forum_id="@forum_id@"
+	       content="@quote.content@" display_attach_p="f">
+      <br />
+     </td>
+    </tr>
+   </if>
+   <tr>
+    <th align="right">Subject:</th>
+    <td><input size="50" name="title" value="@title@"></td>
+   </tr>
+   <tr>
+    <th align="right">Category:</th>
+    <td>
+      <select name="category_id">
+        <option value="">Unknown</option>
+	<multiple name="categories">
+	 <if @category_id@ eq @categories.category_id@>
+	  <option value="@categories.category_id@" selected>@categories.short_name@</option>
+	 </if>
+	 <else>
+	  <option value="@categories.category_id@">@categories.short_name@</option>
+	 </else>
+	</multiple>
+      </select>
+    </td>
+   </tr>
+   <tr valign="top">
+    <th align="right"><br>Message:</td>
+    <td><textarea name="content" rows="20" cols="50" wrap><%= [ns_quotehtml $content] %></textarea></td>
+   </tr>
+   <tr>
+    <th align="right">Text type?</th>
+    <td>
+     <select name="mime_type">
+      <option value="text/plain; format=flowed" <if @msg_mime_type@ nil or @msg_mime_type@ eq "text/plain; format=flowed">selected</if>>Plain</option>
+      <option value="text/plain" <if @msg_mime_type@ not nil and @msg_mime_type@ eq "text/plain">selected</if>>Preformatted</option>
+      <option value="text/html" <if @msg_mime_type@ not nil and @msg_mime_type@ eq "text/html">selected</if>>HTML</option>
+     </select>
+    </td>
+   </tr>
+   <tr>
+    <th></th>
+    <td><input type="submit" value="@submit_label@"></td>
+  </table>
+ </blockquote>
+</form>
Index: openacs-4/packages/sloan-bboard/www/message-list.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-list.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-list.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,51 @@
+<if @messages:rowcount@ eq 0>
+  <i>There are no messages available.</i><p>
+</if>
+
+<else>
+ <table width="90%" cellpadding="3" cellspacing="0" border="0">
+  <tr bgcolor="#ECECEC">
+   <if @score_p@ not nil and @score_p@ eq 1>
+    <th align="left" width="10%">Score</th>
+   </if>
+   <th align="left">Subject</th> 
+   <if @author_p@ nil or @author_p@ ne 0>
+    <th align="left">Author</th>  
+   </if>
+   <if @reply_count_p@ nil or @reply_count_p@ ne 0>
+    <th align="left">Replies</th>
+   </if>
+    <if @last_updated_p@ not nil and @last_updated_p@ ne 0>
+     <th align="left">Last update</th>
+    </if>	
+    <if @sent_date_p@ not nil and @sent_date_p@ ne 0>
+     <th align="left">Date</th>
+    </if>	
+  </tr>
+  <multiple name=messages>
+   <tr>
+    <if @score_p@ not nil and @score_p@ eq 1>
+     <td>@messages.the_score@</td>
+    </if>
+    <if @top_p@ not nil and @top_p@ ne 0>
+     <td><a href="<%=[bboard_message_url -top @messages.message_id@ @forum_id@]%>">@messages.title@</a></td>
+    </if> 
+    <else>
+     <td><a href="<%=[bboard_message_url @messages.message_id@ @forum_id@]%>">@messages.title@</a></td>
+    </else>
+   <if @author_p@ nil or @author_p@ ne 0>
+     <td>@messages.full_name@</td> 
+    </if> 
+    <if @reply_count_p@ nil or @reply_count_p@ ne 0>
+     <td><%= [expr @messages.num_replies@-1] %></td>
+    </if> 
+    <if @last_updated_p@ not nil and @last_updated_p@ ne 0>
+     <td>@messages.last_updated@</td>
+    </if>	
+    <if @sent_date_p@ not nil and @sent_date_p@ ne 0>
+     <td>@messages.sent_date@</td>
+    </if>	
+   </tr>
+  </multiple>
+ </table>
+</else>
Index: openacs-4/packages/sloan-bboard/www/message-mail-2-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-mail-2-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-mail-2-oracle.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="forward_queue">      
+      <querytext>
+      
+        begin
+            acs_message.send (
+                message_id => :new_message_id,
+                to_address => :email,
+                grouping_id => :new_message_id,
+                wait_until => sysdate
+            );
+        end;
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-mail-2-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-mail-2-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-mail-2-postgresql.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="forward_queue">      
+      <querytext>
+
+            select acs_message__send (
+                :new_message_id,
+                :email,
+                :new_message_id,
+                current_timestamp
+            );
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-mail-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-mail-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-mail-2.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,59 @@
+ad_page_contract {
+    
+    Confirmation page for a new posting.
+
+    @author Anukul Kapoor (akk@arsdigita.com)
+    @creation-datee 2000-08-29
+    @cvs $Id: message-mail-2.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+    @param forum_id        The forum ID to return to
+    @param message_id      The message ID to copy and return to
+    @param new_message_id  Debounce for the new message creation
+    @param email           Recipient of email
+} {
+    forum_id:integer,notnull,bboard_forum_id
+    message_id:integer,notnull,acs_message_id
+    new_message_id:integer,notnull
+    email:notnull,trim
+}
+
+ad_require_permission $forum_id bboard_create_message
+
+set user_id [ad_verify_and_get_user_id]
+set creation_ip [ad_conn peeraddr]
+
+db_transaction {
+
+    db_1row user_email {
+        select email as user_email from parties where party_id = :user_id
+    }
+
+    db_1row message_info {
+        select reply_to, sender, title, mime_type, content
+            from acs_messages_all
+            where message_id = :message_id
+    }
+
+    bboard_message_new -message_id $new_message_id \
+            -sender $user_id -title "\[Fwd by $user_email\] $title" \
+            -mime_type $mime_type -content $content -context_id $message_id
+
+    if ![string equal [bboard_forum_moderated_p $forum_id] "t"] {
+	bboard_schedule_sends -message_id $message_id
+    }
+
+    # queue it up to be sent
+    db_exec_plsql forward_queue {
+        begin
+            acs_message.send (
+                message_id => :new_message_id,
+                to_address => :email,
+                grouping_id => :new_message_id,
+                wait_until => sysdate
+            );
+        end;
+    }
+
+}
+
+ad_returnredirect "[bboard_message_url $message_id $forum_id]"
Index: openacs-4/packages/sloan-bboard/www/message-mail-2.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-mail-2.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-mail-2.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,24 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="user_email">      
+      <querytext>
+      
+        select email as user_email from parties where party_id = :user_id
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="message_info">      
+      <querytext>
+      
+        select reply_to, sender, title, mime_type, content
+            from acs_messages_all
+            where message_id = :message_id
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-mail.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-mail.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-mail.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,29 @@
+<master src="master">
+<property name="title">Mail to a friend</property>
+<property name="context_bar">@context_bar@</property>
+
+<form action="message-mail-2" method="POST">
+ <input type="hidden" name="forum_id" value="@forum_id@">
+ <input type="hidden" name="message_id" value="@message_id@">
+ <input type="hidden" name="new_message_id" value="@new_message_id@">
+ <blockquote>
+  <table>
+   <tr>
+    <th align="right" valign="top">Forwarding:</td>
+    <td>
+     <include src="simple-message" author="@quote.full_name@"
+              title="\[Fwd by @sender_email@\] @quote.title@"
+              date="@quote.sent_date@" mime_type="@quote.mime_type@"
+              content="@quote.content@">
+    </td>
+   </tr>
+   <tr>
+    <th align="right" valign="center">Recipient Email:</td>
+    <td><input type="text" name="email" size="50"></td>
+   </tr>
+   <tr>
+    <th></th>
+    <td><input type="submit" value="Send Email"></td>
+  </table>
+ </blockquote>
+</form>
Index: openacs-4/packages/sloan-bboard/www/message-mail.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-mail.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-mail.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,54 @@
+ad_page_contract {
+    
+    A form for posting a new message to a bboard forum.
+
+    @author Anukul Kapoor (akk@arsdigita.com)
+    @creation-datee 2000-08-29
+    @cvs $Id: message-mail.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+    @param forum_id    The forum to post in
+    @param category_id The default category for the message
+    @param reply_to    The message this post should be in reply to
+
+} {
+    forum_id:integer,notnull,bboard_forum_id
+    message_id:integer,notnull,acs_message_id
+} -properties { 
+    context_bar:onevalue
+    forum_id:onevalue
+    message:onerow
+    message_id:onevalue
+    new_message_id:onevalue
+    sender_email:onevalue
+}
+
+ad_require_permission $forum_id bboard_create_message
+
+db_1row forum_short_name {
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+}
+
+set user_id [ad_verify_and_get_user_id]
+
+db_1row sender_email {
+    select email as sender_email from parties
+        where party_id = :user_id
+}
+
+set new_message_id [db_nextval acs_object_id_seq]
+
+set context_bar \
+	[list [list "forum?[export_url_vars forum_id]" $forum_name] \
+              "Post"]
+
+db_0or1row message_info {
+    select reply_to, title, sent_date,
+           mime_type, content, 
+           first_names||' '||last_name as full_name
+      from acs_messages_all m, persons p
+      where message_id = :message_id
+        and person_id = sender
+} -column_array quote
+
+ad_return_template "message-mail"
Index: openacs-4/packages/sloan-bboard/www/message-mail.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-mail.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-mail.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="forum_short_name">      
+      <querytext>
+      
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="sender_email">      
+      <querytext>
+      
+    select email as sender_email from parties
+        where party_id = :user_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="message_info">      
+      <querytext>
+      
+    select reply_to, title, sent_date,
+           mime_type, content, 
+           first_names||' '||last_name as full_name
+      from acs_messages_all m, persons p
+      where message_id = :message_id
+        and person_id = sender
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-move-2-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-move-2-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-move-2-oracle.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="update_bboard_contexts">      
+      <querytext>
+      
+	update acs_objects
+	    set context_id = :dest_forum_id
+	    where context_id = :forum_id
+	          and object_type = 'acs_message'
+                  and object_id in (select message_id
+                                        from acs_messages m
+                                        connect by prior message_id = reply_to
+                                        start with message_id = :message_id) 
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="move_bboard_messages">      
+      <querytext>
+      
+        update bboard_forum_message_map 
+            set forum_id = :dest_forum_id
+            where forum_id = :forum_id
+                  and message_id in (select message_id
+                                         from acs_messages m
+                                         connect by prior message_id = reply_to
+                                         start with message_id = :message_id) 
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-move-2-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-move-2-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-move-2-postgresql.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="update_bboard_contexts">      
+      <querytext>
+
+	update acs_objects
+	    set context_id = :dest_forum_id
+	    where context_id = :forum_id
+              and object_type = 'acs_message'
+              and object_id in 
+                  (select m.message_id
+                     from acs_messages m, acs_messages m2
+                    where m2.message_id = :message_id
+                      and m.tree_sortkey between m2.tree_sortkey and tree_right(m2.tree_sortkey)) 
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="move_bboard_messages">      
+      <querytext>
+
+        update bboard_forum_message_map 
+            set forum_id = :dest_forum_id
+            where forum_id = :forum_id
+              and message_id in 
+                  (select m.message_id
+                   from acs_messages m, acs_messages m2
+                   where m2.message_id = :message_id
+                     and m.tree_sortkey between m2.tree_sortkey and tree_right(m2.tree_sortkey))
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-move-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-move-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-move-2.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,44 @@
+ad_page_contract {
+    
+    Moves a message or thread to another forum.
+
+    @author Anukul Kapoor <akk@arsdigita.com>
+    @creation-date 2001-02-20
+    @cvs-id $Id: message-move-2.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    message_id:integer,notnull,acs_message_id
+    forum_id:integer,notnull,bboard_forum_id
+    dest_forum_id:integer,notnull,bboard_forum_id
+} 
+
+ad_require_permission $forum_id admin
+ad_require_permission $dest_forum_id admin
+
+set user_id [ad_conn user_id]
+
+db_transaction {
+    db_dml update_bboard_contexts {
+	update acs_objects
+	    set context_id = :dest_forum_id
+	    where context_id = :forum_id
+	          and object_type = 'acs_message'
+                  and object_id in (select message_id
+                                        from acs_messages m
+                                        connect by prior message_id = reply_to
+                                        start with message_id = :message_id) 
+    }
+
+    db_dml move_bboard_messages {
+        update bboard_forum_message_map 
+            set forum_id = :dest_forum_id
+            where forum_id = :forum_id
+                  and message_id in (select message_id
+                                         from acs_messages m
+                                         connect by prior message_id = reply_to
+                                         start with message_id = :message_id) 
+    }
+
+}
+
+ad_returnredirect "forum?forum_id=$forum_id"
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/message-move.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-move.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-move.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,22 @@
+<master src="master">
+<property name="title">Move a message</property>
+<property name="context_bar">Move</property>
+
+<form action="message-move-2" method="POST">
+ @form_data@
+
+ <include src="simple-message" title="@title@" headings_p="t"
+          content="@content@" mime_type="@msg_mime_type@">
+ <br>
+
+Move to this message and its replies to which forum?<br>
+	<select name="dest_forum_id">
+	  <multiple name="forums">
+	    <option value="@forums.forum_id@">@forums.short_name@</option>
+	  </multiple>
+	</select>
+<br>
+
+ <blockquote><input type="submit" value="Confirm">
+ </blockquote>
+</form>
Index: openacs-4/packages/sloan-bboard/www/message-move.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-move.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-move.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,50 @@
+ad_page_contract {
+    
+    Confirmation screem for moving a message to another forum.
+
+    @author Anukul Kapoor <akk@arsdigita.com>
+    @creation-date 2001-02-20
+    @cvs-id $Id: message-move.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    message_id:integer,notnull,acs_message_id
+    forum_id:integer,notnull,bboard_forum_id
+    {replies ""}
+} -properties {
+    message_id:onevalue
+    forum_id:onevalue
+    title:onevalue
+    sender_name:onevalue
+    content:onevalue
+    msg_mime_type:onevalue
+    forums:multirow
+    form_date:onevalue
+}
+
+ad_require_permission $message_id admin
+
+set user_id [ad_conn user_id]
+
+db_1row message_info {
+    select p.first_names ||' '|| p.last_name as sender_name, b.title,
+           b.mime_type as msg_mime_type, b.content
+      from bboard_messages_all b, persons p
+      where message_id = :message_id
+            and b.sender = p.person_id
+}
+
+
+db_multirow forums allowed_target_forums {
+    select forum_id, short_name
+      from bboard_forums
+      where not forum_id = :forum_id
+        and exists (select 1 from acs_object_party_privilege_map
+                      where object_id = forum_id
+                        and party_id in (:user_id, -1)
+                        and privilege = 'admin')
+
+}
+
+set form_data [export_form_vars message_id forum_id]
+
+ad_return_template
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/message-move.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-move.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-move.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="message_info">      
+      <querytext>
+      
+    select p.first_names ||' '|| p.last_name as sender_name, b.title,
+           b.mime_type as msg_mime_type, b.content
+      from bboard_messages_all b, persons p
+      where message_id = :message_id
+            and b.sender = p.person_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="allowed_target_forums">      
+      <querytext>
+      
+    select forum_id, short_name
+      from bboard_forums
+      where not forum_id = :forum_id
+        and exists (select 1 from all_object_party_privilege_map
+                      where object_id = forum_id
+                        and party_id = :user_id
+                        and privilege = 'admin')
+
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-new-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-new-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-new-2.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,84 @@
+ad_page_contract {
+    
+    Confirmation page for a new posting.
+
+    @author Anukul Kapoor (akk@arsdigita.com)
+    @creation-datee 2000-08-29
+    @cvs $Id: message-new-2.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+    @param forum_id    The forum to post to
+    @param title       The message title
+    @param content     The message contents
+    @param category_id The category to post to
+    @param reply_to    The message this is in reply to
+} {
+    forum_id:integer,notnull,bboard_forum_id
+    title:notnull,trim
+    content:notnull,allhtml,trim
+    mime_type:notnull
+    category_id:integer,bboard_category_id
+    {reply_to:integer,acs_message_id ""}
+} -validate {
+    content_html -requires {content mime_type} {
+	if [string eq $mime_type "text/html"] {
+	    set complaint [ad_html_security_check $content]
+	    if ![empty_string_p $complaint] {
+		ad_complain $complaint
+	    }
+	}
+    }
+} -properties { 
+    page_title:onevalue
+    context_bar:onevalue
+    forum_name:onevalue
+    content_for_display:onevalue
+    title:onevalue
+    message_id:onevalue
+    form_vars:onevalue
+    reply_to:onevalue
+    target:onevalue
+    subscribe_p:onevalue
+    msg_mime_type:onevalue
+}
+
+ns_log Notice "mime_type is $mime_type"
+set subscribe_p 1
+
+set user_id [ad_verify_and_get_user_id]
+
+ad_require_permission $forum_id bboard_create_message
+
+set target "message-new-3"
+
+db_1row forum_short_name {
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+}
+
+set page_title "Confirm Message for Posting in $forum_name"
+
+set context_bar [list \
+	[list "forum?[export_url_vars forum_id]" $forum_name] \
+	"Post"]
+
+set content_for_display [acs_messaging_format_as_html $mime_type $content]
+
+set message_id [db_nextval acs_object_id_seq]
+
+set msg_mime_type $mime_type
+
+set form_vars [export_form_vars message_id forum_id title content \
+	                        mime_type category_id reply_to]
+
+if ![string equal $reply_to ""] {
+    set subscribe_p 0
+} else {
+    if {[string equal [bboard_category_subscribed_p $user_id $category_id] "t"] ||
+        [string equal [bboard_forum_subscribed_p $user_id $forum_id] "t"]} {
+	set subscribe_p 0
+    } else {
+	set subscribe_p 1
+    }
+}
+
+ad_return_template "message-preview"
Index: openacs-4/packages/sloan-bboard/www/message-new-2.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-new-2.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-new-2.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="forum_short_name">      
+      <querytext>
+      
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-new-3-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-new-3-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-new-3-oracle.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,17 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="grant">      
+      <querytext>
+      
+	    begin
+	    acs_permission.grant_permission(:message_id, :user_id, 'bboard_write_message');
+	    end;
+	
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-new-3-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-new-3-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-new-3-postgresql.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="grant">      
+      <querytext>
+
+	    select acs_permission__grant_permission(:message_id, :user_id, 'bboard_write_message');
+	
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-new-3.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-new-3.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-new-3.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,63 @@
+ad_page_contract {
+    
+    Confirmation page for a new posting.
+
+    @author Anukul Kapoor (akk@arsdigita.com)
+    @creation-datee 2000-08-29
+    @cvs $Id: message-new-3.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+    @param forum_id
+    @param short_name
+    @param content
+    @param mime_type
+} {
+    message_id:integer,notnull
+    forum_id:integer,notnull,bboard_forum_id
+    category_id:integer,bboard_category_id
+    title:notnull,trim
+    content:allhtml,notnull,trim
+    mime_type:notnull
+    {reply_to:integer,acs_message_id ""}
+    {subscribe_p:optional ""}
+}
+
+ad_require_permission $forum_id bboard_create_message
+
+set user_id [ad_verify_and_get_user_id]
+set creation_ip [ad_conn peeraddr]
+
+db_transaction {
+
+    bboard_message_new -message_id $message_id -reply_to $reply_to \
+            -sender $user_id -title $title -mime_type $mime_type \
+            -content $content -context_id $forum_id \
+	    -creation_ip $creation_ip
+
+    bboard_message_set_status \
+            -message_id $message_id -forum_id $forum_id -status "unmoderated"
+
+    if {![empty_string_p $category_id]} {
+        bboard_message_add_category \
+                -message_id $message_id -category_id $category_id
+    }
+
+    if ![empty_string_p $subscribe_p] {
+	bboard_subscribe_thread -thread_id $message_id -subscriber_id $user_id
+    }
+
+    if ![string equal [bboard_forum_moderated_p $forum_id] "t"] {
+	bboard_alert_one_mesg -message_id $message_id -forum_id $forum_id \
+		-user_id $user_id -creation_ip $creation_ip
+    }
+
+    if [string equal [ad_parameter "UserPostsEditableP"] "t"] {
+	db_exec_plsql grant {
+	    begin
+	    acs_permission.grant_permission(:message_id, :user_id, 'bboard_write_message');
+	    end;
+	}
+    }
+
+}
+
+ad_returnredirect "forum?[export_url_vars forum_id]"
Index: openacs-4/packages/sloan-bboard/www/message-new.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-new.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-new.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,86 @@
+ad_page_contract {
+    
+    A form for posting a new message to a bboard forum.
+
+    @author Anukul Kapoor (akk@arsdigita.com)
+    @creation-datee 2000-08-29
+    @cvs $Id: message-new.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+    @param forum_id    The forum to post in
+    @param category_id The default category for the message
+    @param reply_to    The message this post should be in reply to
+
+} {
+    forum_id:integer,notnull,bboard_forum_id
+    {category_id:integer,bboard_category_id ""}
+    {reply_to:integer,acs_message_id ""}
+} -properties { 
+    context_bar:onevalue
+    forum_id:onevalue
+    forum_name:onevalue
+    categories:multirow
+    category_id:onevalue
+    reply_to:onevalue
+    quote:onerow
+    has_quote:onevalue
+    page_title:onevalue
+    target:onevalue
+    title:onevalue
+    content:onevalue
+    submit_label:onevalue
+    message_id:onevalue
+}
+
+ad_require_permission $forum_id bboard_create_message
+
+db_1row forum_short_name {
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+}
+
+set page_title "Post a New Message to $forum_name"
+
+set target "message-new-2"
+set submit_label "Post Message"
+
+set title ""
+set content ""
+
+set context_bar \
+	[list [list "forum?[export_url_vars forum_id]" $forum_name] \
+              "Post"]
+
+set user_id [ad_verify_and_get_user_id]
+
+set category_pulldown_list ""
+
+db_0or1row quote_info {
+    select reply_to, title, sent_date,
+           mime_type, content, 
+           first_names||' '||last_name as full_name
+      from acs_messages_all m, persons p
+      where message_id = :reply_to
+        and person_id = sender
+} -column_array quote
+
+if ![empty_string_p $reply_to] {
+    if [string equal -length 4 -nocase "Re: " $quote(title)] {
+        set title $quote(title)
+    } else {
+        set title "Re: $quote(title)"
+    }
+}
+
+db_0or1row quote_first_category {
+    select min(category_id) as category_id from bboard_category_message_map
+      where message_id = :reply_to
+      group by message_id
+}
+
+db_multirow categories category_list {
+    select category_id, short_name
+      from bboard_categories
+      where forum_id = :forum_id
+}
+
+ad_return_template "message-entry"
Index: openacs-4/packages/sloan-bboard/www/message-new.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-new.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-new.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="forum_short_name">      
+      <querytext>
+      
+    select short_name as forum_name from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="quote_info">      
+      <querytext>
+      
+    select reply_to, title, sent_date,
+           mime_type, content, 
+           first_names||' '||last_name as full_name
+      from acs_messages_all m, persons p
+      where message_id = :reply_to
+        and person_id = sender
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="quote_first_category">      
+      <querytext>
+      
+    select min(category_id) as category_id from bboard_category_message_map
+      where message_id = :reply_to
+      group by message_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="category_list">      
+      <querytext>
+      
+    select category_id, short_name
+      from bboard_categories
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-oracle.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="forum_short_name">      
+      <querytext>
+      
+    select short_name as forum_name,
+       acs_permission.permission_p(:forum_id, :user_id, 'admin') as admin_p,
+       acs_permission.permission_p(:forum_id, :user_id, 'bboard_moderate_forum') 
+         as moderate_p
+      from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+<fullquery name="message_info">      
+      <querytext>
+      
+  select message_id, reply_to, title, 
+      to_char(sent_date, 'Month DD, YYYY HH:Mi am') as pretty_date, sender as user_id,
+      mime_type, content, first_names||' '||last_name as full_name,
+      acs_permission.permission_p(message_id, :user_id,
+                                  'bboard_write_message') as write_p
+    from acs_messages_all m, persons p
+    where message_id = :message_id
+      and person_id = sender
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="message_replies">      
+      <querytext>
+      
+    select m.message_id, m.reply_to, m.title, m.mime_type, m.content, 
+         to_char(m.sent_date,'Month DD, YYYY HH:Mi am') as pretty_date, sender as user_id,
+         p.first_names||' '||p.last_name as full_name, 
+         mt.depth - 1 as thread_depth, rownum,
+         acs_permission.permission_p(m.message_id, :user_id,
+                                  'bboard_write_message') as write_p
+        from acs_messages_all m, persons p,
+            (select message_id, level as depth, rownum as seqnum
+                from acs_messages
+                connect by prior message_id = reply_to
+                start with message_id = :message_id) mt
+        where m.message_id <> :message_id
+            and p.person_id = m.sender
+            and m.message_id = mt.message_id
+            and m.message_id in (select bfmm.message_id 
+                                     from bboard_forum_message_map bfmm
+                                     where bfmm.forum_id = :forum_id)
+    order by mt.seqnum
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-postgresql.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="forum_short_name">      
+      <querytext>
+      
+    select short_name as forum_name,
+       acs_permission__permission_p(:forum_id, :user_id, 'admin') as admin_p,
+       acs_permission__permission_p(:forum_id, :user_id, 'bboard_moderate_forum') 
+         as moderate_p
+      from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+
+<fullquery name="message_info">      
+      <querytext>
+      
+  select message_id, reply_to, title, 
+      to_char(sent_date, 'Month DD, YYYY HH:MI am') as pretty_date, sender as user_id,
+      mime_type, content, first_names||' '||last_name as full_name,
+      acs_permission__permission_p(message_id, :user_id,
+                                  'bboard_write_message') as write_p
+    from acs_messages_all m, persons p
+    where message_id = :message_id
+      and person_id = sender
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="message_replies">      
+      <querytext>
+
+    select m.message_id, m.reply_to, m.title, m.mime_type, m.content, 
+           to_char(m.sent_date,'Month DD, YYYY HH:MI am') as pretty_date, m.sender as user_id,
+           p.first_names||' '||p.last_name as full_name, 
+           tree_level(m.tree_sortkey) - 1 as thread_depth, 
+           acs_permission__permission_p(m.message_id, :user_id,
+                                       'bboard_write_message') as write_p
+      from acs_messages_all m, acs_messages m2, persons p, bboard_forum_message_map bfmm
+     where m2.message_id = :message_id
+       and m.message_id <> :message_id
+       and bfmm.forum_id = :forum_id
+       and m.tree_sortkey between m2.tree_sortkey and tree_right(m2.tree_sortkey) 
+       and p.person_id = m.sender
+       and m.message_id = bfmm.message_id 
+     order by m.sent_date
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-preview.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-preview.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-preview.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,14 @@
+<master src="master">
+<property name="title">@page_title@</property>
+<property name="context_bar">@context_bar@</property>
+
+<form action="@target@" method="POST">
+ @form_vars@
+ <include src="simple-message" title="@title@" headings_p="t"
+          content="@content@" mime_type="@msg_mime_type@">
+ <br>
+ <blockquote><input type="submit" value="Confirm">
+ <if @subscribe_p@ not nil and @subscribe_p@ eq 1>
+  &nbsp; <input type="checkbox" name="subscribe_p"> Subscribe to replies
+ </if></blockquote>
+</form>
Index: openacs-4/packages/sloan-bboard/www/message-reject.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-reject.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-reject.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,19 @@
+ad_page_contract {
+    
+    Marks a message as rejected for display in a moderated forum.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-09-10
+    @cvs-id $Id: message-reject.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    message_id:integer,notnull,acs_message_id
+    forum_id:integer,notnull,bboard_forum_id
+}
+
+ad_require_permission $forum_id bboard_moderate_forum
+
+bboard_message_set_status \
+        -message_id $message_id -forum_id $forum_id -status "rejected"
+
+ad_returnredirect "forum?forum_id=$forum_id"
Index: openacs-4/packages/sloan-bboard/www/message-subscribe.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-subscribe.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-subscribe.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,22 @@
+ad_page_contract {
+
+    Subscribe the current user to a given message thread.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-10-28
+    @cvs-id $Id: message-subscribe.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    forum_id:integer,notnull,bboard_forum_id
+    message_id:integer,notnull,acs_message_id
+}
+
+# Not strictly right
+ad_require_permission $forum_id bboard_create_message
+
+catch {
+    bboard_subscribe_thread \
+	-thread_id $message_id -subscriber_id [ad_verify_and_get_user_id]
+}
+
+ad_returnredirect "[bboard_message_page]?forum_id=$forum_id&message_id=$message_id"
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/message-threaded-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-threaded-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-threaded-oracle.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="forum_short_name">      
+      <querytext>
+      
+    select short_name as forum_name,
+       acs_permission.permission_p(:forum_id, :user_id, 'admin') as admin_p,
+       acs_permission.permission_p(:forum_id, :user_id, 'bboard_moderate_forum') 
+         as moderate_p
+      from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="messages_and_replies">      
+      <querytext>
+      
+  select m.message_id, m.reply_to, m.title, m.sent_date, m.mime_type,
+         to_char(m.sent_date, 'Month DD, YYYY HH:Mi am') as pretty_date,
+         m.content, p.first_names||' '||p.last_name as full_name, 
+         p.person_id as user_id,
+         mt.depth - 1 as thread_depth,
+      acs_permission.permission_p(m.message_id, :user_id,
+                                  'bboard_write_message') as write_p
+    from acs_messages_all m, persons p, 
+      (select message_id, level as depth, rownum as seqnum
+         from acs_messages im
+         connect by prior message_id = reply_to
+         start with message_id = :message_id) mt
+    where p.person_id = m.sender
+      and m.message_id = mt.message_id
+      and m.message_id in (select bfmm.message_id 
+                               from bboard_forum_message_map bfmm
+                               where bfmm.forum_id = :forum_id)
+      order by seqnum
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-threaded-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-threaded-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-threaded-postgresql.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="forum_short_name">      
+      <querytext>
+      
+    select short_name as forum_name,
+       acs_permission__permission_p(:forum_id, :user_id, 'admin') as admin_p,
+       acs_permission__permission_p(:forum_id, :user_id, 'bboard_moderate_forum') 
+         as moderate_p
+      from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+ 
+
+<fullquery name="messages_and_replies">      
+      <querytext>
+
+  select m.message_id, m.reply_to, m.title, m.sent_date, m.mime_type,
+         to_char(m.sent_date, 'Month DD, YYYY HH:MI am') as pretty_date,
+         m.content, p.first_names||' '||p.last_name as full_name, 
+         p.person_id as user_id,
+         tree_level(m.tree_sortkey) - 1 as thread_depth, 
+      acs_permission__permission_p(m.message_id, :user_id,
+                                  'bboard_write_message') as write_p
+    from acs_messages_all m, persons p, acs_messages m2, bboard_forum_message_map bfmm
+   where m2.message_id = :message_id
+     and bfmm.forum_id = :forum_id
+     and m.tree_sortkey between m2.tree_sortkey and tree_right(m2.tree_sortkey)
+     and p.person_id = m.sender
+     and m.message_id = bfmm.message_id 
+   order by m.tree_sortkey
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-threaded.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-threaded.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-threaded.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,33 @@
+<master src="master">
+<property name="context_bar">@context_bar@</property>
+<property name="title">@forum_name@: @title@</property>
+
+<table width="100%"><tr><td>
+<if @moderate_p@ not nil and @moderate_p@ ne "f">
+  [<a href="message-move?forum_id=@forum_id@&message_id=@message_id@">Move Thread</a>]
+</if></td>
+
+<td align="right"> 
+<if @subscribed_p@ eq 0>
+  [<a href="message-subscribe?forum_id=@forum_id@&message_id=@message_id@">Subscribe to replies</a>]
+ </if>
+ <else>
+  You're subscribed to replies [<a href="message-unsubscribe?forum_id=@forum_id@&message_id=@message_id@">Unsubscribe</a>]
+ </else>
+</td></tr></table><p>
+
+<table width="100%">
+ <multiple name=messages>
+  <tr><td><img src="spacer.gif" width="<%= [expr 25*@messages.thread_depth@]%>" 
+               align="left">
+  <a name="@messages.message_id@">
+  <include src="simple-message" title="@messages.title@" author="@messages.full_name@"
+           mime_type="@messages.mime_type@" content="@messages.content@"
+	   date="@messages.pretty_date@" id="@messages.message_id@" link_p="t"
+ 	   write_p="@messages.write_p@"
+           reply_p="t" forum_id="@forum_id@"
+	   admin_p="@admin_p@" user_id="@messages.user_id@">
+  </tr></td>
+ </multiple>
+</table>
+
Index: openacs-4/packages/sloan-bboard/www/message-threaded.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-threaded.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-threaded.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,70 @@
+ad_page_contract {
+
+    Displays a single message, and all replies in a threaded fashion.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-09-01
+    @cvs-id $Id: message-threaded.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+} {
+    message_id:integer,notnull,acs_message_id
+    forum_id:integer,notnull,bboard_forum_id
+} -properties {
+    context_bar:onevalue
+    forum_name:onevalue
+    forum_id:onevalue
+    message:onerow
+    replies:multirow
+    title:onevalue
+    subscribed_p:onevalue
+}
+
+ad_require_permission $message_id bboard_read_forum
+
+set user_id [ad_verify_and_get_user_id]
+
+if [string equal [bboard_message_subscribed_p -direct $user_id $message_id] "t"] {
+    set subscribed_p 1
+} else {
+    set subscribed_p 0
+}
+
+db_1row forum_short_name {
+    select short_name as forum_name,
+       acs_permission.permission_p(:forum_id, :user_id, 'admin') as admin_p,
+       acs_permission.permission_p(:forum_id, :user_id, 'bboard_moderate_forum') 
+         as moderate_p
+      from bboard_forums
+      where forum_id = :forum_id
+}
+
+db_1row thread_title {
+    select title
+      from acs_messages_all
+      where message_id = :message_id
+}
+
+set context_bar [list [list "forum?[export_url_vars forum_id]" $forum_name] \
+		      "One Message"]
+                   
+db_multirow messages messages_and_replies {
+  select m.message_id, m.reply_to, m.title, m.sent_date, m.mime_type,
+         to_char(m.sent_date, 'Month DD, YYYY HH:Mi am') as pretty_date,
+         m.content, p.first_names||' '||p.last_name as full_name, 
+         p.person_id as user_id,
+         mt.depth - 1 as thread_depth,
+      acs_permission.permission_p(m.message_id, :user_id,
+                                  'bboard_write_message') as write_p
+    from acs_messages_all m, persons p, 
+      (select message_id, level as depth, rownum as seqnum
+         from acs_messages
+         connect by prior message_id = reply_to
+         start with message_id = :message_id) mt
+    where p.person_id = m.sender
+      and m.message_id = mt.message_id
+      and m.message_id in (select bfmm.message_id 
+                               from bboard_forum_message_map bfmm
+                               where bfmm.forum_id = :forum_id)
+      order by seqnum
+}
+
+ad_return_template
Index: openacs-4/packages/sloan-bboard/www/message-threaded.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-threaded.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-threaded.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="thread_title">      
+      <querytext>
+      
+    select title
+      from acs_messages_all
+      where message_id = :message_id
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/message-unsubscribe.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message-unsubscribe.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message-unsubscribe.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,24 @@
+ad_page_contract {
+
+    Unsubscribe the current user from a given mesage thread.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-10-28
+    @cvs-id $Id: message-unsubscribe.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    forum_id:integer,notnull,bboard_forum_id
+    message_id:integer,notnull,acs_message_id
+    {sub_page ""}
+}
+
+catch {
+    bboard_unsubscribe_thread \
+	-thread_id $message_id -subscriber_id [ad_verify_and_get_user_id]
+}
+
+if [empty_string_p $sub_page] {
+    ad_returnredirect "[bboard_message_page]?forum_id=$forum_id&message_id=$message_id"
+} else {
+    ad_returnredirect "subscriptions"
+}
Index: openacs-4/packages/sloan-bboard/www/message.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,62 @@
+<master src="master">
+<property name="context_bar">@context_bar@</property>
+<property name="title">@forum_name@: @message.title@</property>
+
+<table width="100%"><tr><td>
+<if @admin_p@ not nil and @admin_p@ ne "f">
+  [<a href="message-delete?forum_id=@forum_id@&message_id=@message_id@&replies=t">Delete Thread</a>]
+</if>
+
+<if @moderate_p@ not nil and @moderate_p@ ne "f">
+  [<a href="message-move?forum_id=@forum_id@&message_id=@message_id@">Move Thread</a>]
+</if></td>
+<td align="right"> <if @subscribed_p@ eq 0>
+  [<a href="message-subscribe?forum_id=@forum_id@&message_id=@message_id@">Subscribe to replies</a>]
+ </if>
+ <else>
+  You're subscribed to replies [<a href="message-unsubscribe?forum_id=@forum_id@&message_id=@message_id@">Unsubscribe</a>]
+ </else>
+</td></tr></table>
+
+
+<h3>Message:</h3>
+<blockquote>
+<include src="simple-message" title="@message.title@" author="@message.full_name@"
+         mime_type="@message.mime_type@" content="@message.content@"
+         date="@message.pretty_date@" id="@message.message_id@"
+	 write_p="@message.write_p@" admin_p="@admin_p@"
+         forum_id="@forum_id@" user_id="@message.user_id@" reply_p="1">
+</blockquote>
+<if @replies:rowcount@ gt 0>
+ <h3>Replies:</h3>
+<% set prev_depth 0 %>
+ <multiple name=replies>
+<%
+if {$replies(thread_depth) > $prev_depth} {
+        template::adp_puts "<blockquote>"
+}
+if {$replies(thread_depth) < $prev_depth} {
+        template::adp_puts "</blockquote>"
+}
+set prev_depth $replies(thread_depth)
+%>
+  <blockquote>
+  <a name="@replies.message_id@">
+  <include src="simple-message-summary" title="@replies.title@" author="@replies.full_name@"
+           mime_type="@replies.mime_type@" content="@replies.content@"
+	   date="@replies.pretty_date@" id="@replies.message_id@" 
+ 	   write_p="@replies.write_p@" admin_p="@admin_p@"
+           forum_id="@forum_id@" user_id=@replies.user_id@ reply_p=1>
+  </blockquote>
+  <if @replies:rowcount@ ne @replies.rownum@>
+   <hr width="60%"/>
+  </if>
+ </multiple>
+</if>
+
+ <center><form action="message-new">
+  <input type="hidden" name="forum_id" value="@forum_id@">
+  <input type="hidden" name="reply_to" value="@message_id@">
+  <input type="submit" value="Post a reply">
+ </form></center>
+
Index: openacs-4/packages/sloan-bboard/www/message.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/message.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/message.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,76 @@
+ad_page_contract {
+
+    Displays a single message, and all replies.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @creation-date 2000-09-01
+    @cvs-id $Id: message.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+} {
+    message_id:integer,notnull,acs_message_id
+    forum_id:integer,notnull,bboard_forum_id
+} -properties {
+    message_create_p:onevalue
+    context_bar:onevalue
+    forum_name:onevalue
+    forum_id:onevalue
+    message:onerow
+    replies:multirow
+    subscribed_p:onevalue
+    moderate_p:onevalue
+}
+
+ad_require_permission $message_id bboard_read_forum
+
+set user_id [ad_verify_and_get_user_id]
+
+if [string equal [bboard_message_subscribed_p -direct $user_id $message_id] "t"] {
+    set subscribed_p 1
+} else {
+    set subscribed_p 0
+}
+
+db_1row forum_short_name {
+    select short_name as forum_name,
+       acs_permission.permission_p(:forum_id, :user_id, 'admin') as admin_p,
+       acs_permission.permission_p(:forum_id, :user_id, 'bboard_moderate_forum') 
+         as moderate_p
+      from bboard_forums
+      where forum_id = :forum_id
+}
+
+db_1row message_info {
+  select message_id, reply_to, title, 
+      to_char(sent_date, 'Month DD, YYYY HH:Mi am') as pretty_date, sender as user_id,
+      mime_type, content, first_names||' '||last_name as full_name,
+      acs_permission.permission_p(message_id, :user_id,
+                                  'bboard_write_message') as write_p
+    from acs_messages_all m, persons p
+    where message_id = :message_id
+      and person_id = sender
+} -column_array message
+
+set context_bar [list [list "forum?[export_url_vars forum_id]" $forum_name] \
+		      "One Message"]
+                   
+db_multirow replies message_replies {
+    select m.message_id, m.reply_to, m.title, m.mime_type, m.content, 
+         to_char(m.sent_date,'Month DD, YYYY HH:Mi am') as pretty_date, sender as user_id,
+         p.first_names||' '||p.last_name as full_name, 
+         mt.depth - 1 as thread_depth, rownum,
+         acs_permission.permission_p(m.message_id, :user_id,
+                                  'bboard_write_message') as write_p
+        from acs_messages_all m, persons p,
+            (select message_id, level as depth, rownum as seqnum
+                from acs_messages im
+                connect by prior message_id = reply_to
+                start with message_id = :message_id) mt
+        where m.message_id <> :message_id
+            and p.person_id = m.sender
+            and m.message_id = mt.message_id
+            and m.message_id in (select bfmm.message_id 
+                                     from bboard_forum_message_map bfmm
+                                     where bfmm.forum_id = :forum_id)
+order by mt.seqnum
+}
+
+ad_return_template
Index: openacs-4/packages/sloan-bboard/www/messages-by-user.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/messages-by-user.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/messages-by-user.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,21 @@
+<master src="master">
+<property name="context_bar">@context_bar@</property>
+<property name="title">@title@</property>
+
+
+<if @messages:rowcount@ eq 0>
+  <i>There are no messages for this user this forum.</i><p>
+</if>
+
+<else>
+ <include src="message-list" &=messages forum_id="@forum_id@" author_p="0" />
+</else>
+
+<p>
+
+Posting History in Other Forums:
+<ul>
+ <multiple name="alt_forums">
+  <li><a href="messages-by-user?forum_id=@alt_forums.forum_id@&user_id=@user_id@">@alt_forums.short_name@</a>
+ </multiple>
+</ul>
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/messages-by-user.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/messages-by-user.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/messages-by-user.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,79 @@
+ad_page_contract {
+
+    Displays a given user's posting history.
+
+    @author Anukul Kapoor
+    @creation-date 2000-11-22
+    @cvs-id $Id: messages-by-user.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+
+} {
+    user_id:integer,notnull
+    forum_id:integer,notnull,bboard_forum_id
+} -properties {
+    context_bar:onevalue
+    title:onevalue
+    forum_name:onevalue
+    forum_id:onevalue
+    messages:multirow
+}
+
+set current_user_id [ad_verify_and_get_user_id]
+
+ad_require_permission $forum_id bboard_read_forum
+
+db_1row user_info {
+    select first_names||' '||last_name as full_name
+      from persons
+      where person_id = :user_id
+}
+
+db_1row forum_info {
+    select short_name as forum_name, moderated_p from bboard_forums
+      where forum_id = :forum_id
+}
+
+if [string equal $moderated_p f] {
+
+    db_multirow messages messages_select {
+        select title, num_replies, message_id,
+               first_names||' '||last_name as full_name
+        from bboard_messages_all, persons
+        where sender = :user_id
+              and forum_id = :forum_id
+              and person_id = sender
+    }
+} else {
+    db_multirow messages messages_select {
+        select title, num_replies, message_id,
+               first_names||' '||last_name as full_name
+        from bboard_messages_all, persons
+        where sender = :user_id
+              and forum_id = :forum_id
+              and person_id = sender
+              and status = 'approved'
+    }
+}
+
+
+set package_id [ad_conn package_id]
+
+db_multirow alt_forums alt_forums_select {
+    select forum_id, short_name
+    from bboard_forums bf
+    where not forum_id = :forum_id
+          and bboard_id = :package_id
+          and exists (select 1
+                      from bboard_messages_all bma
+                      where sender = :user_id 
+                            and bma.forum_id = bf.forum_id)
+          and exists (select 1 from acs_object_party_privilege_map
+                          where object_id = bf.forum_id
+                            and party_id in (:current_user_id, -1)
+                            and privilege = 'bboard_read_forum')
+}
+
+set title "Posting History for $full_name in $forum_name"
+
+set context_bar [list $forum_name]
+ 
+ad_return_template
Index: openacs-4/packages/sloan-bboard/www/messages-by-user.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/messages-by-user.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/messages-by-user.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,73 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="user_info">      
+      <querytext>
+      
+    select first_names||' '||last_name as full_name
+      from persons
+      where person_id = :user_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="forum_info">      
+      <querytext>
+      
+    select short_name as forum_name, moderated_p from bboard_forums
+      where forum_id = :forum_id
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="messages_select">      
+      <querytext>
+      
+        select title, num_replies, message_id,
+               first_names||' '||last_name as full_name
+        from bboard_messages_all, persons
+        where sender = :user_id
+              and forum_id = :forum_id
+              and person_id = sender
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="messages_select">      
+      <querytext>
+      
+        select title, num_replies, message_id,
+               first_names||' '||last_name as full_name
+        from bboard_messages_all, persons
+        where sender = :user_id
+              and forum_id = :forum_id
+              and person_id = sender
+    
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="alt_forums_select">      
+      <querytext>
+      
+    select forum_id, short_name
+    from bboard_forums bf
+    where not forum_id = :forum_id
+          and bboard_id = :package_id
+          and exists (select 1
+                      from bboard_messages_all bma
+                      where sender = :user_id 
+                            and bma.forum_id = bf.forum_id)
+          and exists (select 1 from all_object_party_privilege_map
+                          where object_id = bf.forum_id
+                            and party_id = :current_user_id
+                            and privilege = 'bboard_read_forum')
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/search-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/search-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/search-oracle.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="im_convert_query">      
+      <querytext>
+      
+    select bboard_im_convert(:query) as query from dual
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_search">      
+      <querytext>
+      
+	select score(10) as the_score, message_id,
+            m.title, m.num_replies, to_char(m.sent_date,'MM/DD/YYYY') as sent_date,
+	    p.first_names||' '||p.last_name as full_name
+	  from bboard_messages_all m, persons p, bboard_forums f
+	  where contains(content, :query, 10) > 0
+	    and m.sender = p.person_id
+	    and m.forum_id = :forum_id
+	    and f.forum_id = m.forum_id
+	    and f.bboard_id = :package_id
+	  order by score(10) desc
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/search-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/search-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/search-postgresql.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="im_convert_query">      
+      <querytext>
+      
+    select :query as query 
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="bboard_search">      
+      <querytext>
+      
+	select 10 as the_score, message_id,
+            m.title, m.num_replies, to_char(m.sent_date,'MM/DD/YYYY') as sent_date,
+	    p.first_names||' '||p.last_name as full_name
+	  from bboard_messages_all m, persons p, bboard_forums f
+          where content like '%' || :query || '%'
+	    and m.sender = p.person_id
+	    and m.forum_id = :forum_id
+	    and f.forum_id = m.forum_id
+	    and f.bboard_id = :package_id
+
+      </querytext>
+</fullquery>
+
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/search.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/search.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/search.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,7 @@
+<master src="master">
+<property name="context_bar">@context_bar@</property>
+<property name="title">@title@</property>
+
+<include src="message-list" &messages="results" forum_id="@forum_id@" 
+         score_p="1" sent_date_p="1" />
+
Index: openacs-4/packages/sloan-bboard/www/search.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/search.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/search.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,50 @@
+ad_page_contract {
+    
+    Displays search results from a user query.
+
+    @author Anukul Kapoor <akk@arsdigita.com>
+    @creation-date 2000-10-26
+    @cvs-id $Id: search.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+} {
+    query:notnull
+    forum_id:integer,notnull,bboard_forum_id
+} -properties { 
+    query:onevalue
+    results:multirow
+    forum_id:onevalue
+    context_bard:onevalue
+    title:onevalue
+}
+
+set user_id [ad_verify_and_get_user_id]
+
+set title "Search Results for \"$query\""
+set context_bar [list "Search"]
+
+set package_id [ad_conn package_id] 
+
+ad_require_permission $forum_id bboard_read_forum
+
+# convert query string to im happy query string
+
+db_1row im_convert_query {
+    select bboard_im_convert(:query) as query from dual
+}
+
+# if you're not running context, you'll need to run this by hand
+# alter index cr_rev_content_index rebuild online parameters('sync memory 45M');
+
+db_multirow results bboard_search {
+	select score(10) as the_score, message_id,
+        m.title, m.num_replies, to_char(m.sent_date,'MM/DD/YYYY') as sent_date,
+	    p.first_names||' '||p.last_name as full_name
+	  from bboard_messages_all m, persons p, bboard_forums f
+	  where contains(content, :query, 10) > 0
+	    and m.sender = p.person_id
+	    and m.forum_id = :forum_id
+	    and f.forum_id = m.forum_id
+	    and f.bboard_id = :package_id
+	  order by score(10) desc
+}
+
+ad_return_template
Index: openacs-4/packages/sloan-bboard/www/simple-message-oracle.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/Attic/simple-message-oracle.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/simple-message-oracle.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>oracle</type><version>8.1.6</version></rdbms>
+
+<fullquery name="get_attachments">      
+      <querytext>
+      
+	select object_id as file_id, cr.title, ci.name
+            from acs_objects ao, cr_items ci, cr_revisions cr
+            where object_id = ci.item_id and
+                  live_revision = revision_id and
+	          object_type = 'content_item' and
+                  context_id = :id
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/simple-message-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/Attic/simple-message-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/simple-message-postgresql.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.1</version></rdbms>
+
+<fullquery name="get_attachments">      
+      <querytext>
+      
+	select object_id as file_id, cr.title, ci.name
+            from acs_objects ao, cr_items ci, cr_revisions cr
+            where object_id = ci.item_id and
+                  live_revision = revision_id and
+	          object_type = 'content_item' and
+                  context_id = :id
+    
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/simple-message-summary.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/simple-message-summary.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/simple-message-summary.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,5 @@
+<% # A simple single message summary
+   # This should, in the future, use a row variable rather than many
+   # single values, but row variables are not yet supported. %>
+
+<a href=message?message_id=@id@>@title@</a> by <A href=>@author@</a> on @date@
Index: openacs-4/packages/sloan-bboard/www/simple-message.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/Attic/simple-message.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/simple-message.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,75 @@
+<% # A simple single message
+   # This should, in the future, use a row variable rather than many
+   # single values, but row variables are not yet supported. %>
+
+<table cellspacing="0" cellpadding="3" border="0" width="90%">
+ <tr bgcolor="#ECECEC">
+  <if @headings_p@ not nil and @headings_p@ ne "f">
+   <th width="15%" align="left" valign="top">Subject:</th>
+  </if>
+  <td align="left">
+   <if @id@ not nil and @link_p@ not nil and @link_p@ ne "f">
+    <b><i><a href="<%=[bboard_message_url @id@ @forum_id@]%>">@title@</a></i></b>
+   </if>
+   <else>
+    <b><i>@title@</i></b>
+   </else>
+   &nbsp;
+  </td>
+   <if @id@ not nil>
+    <td align="right">
+     <if @write_p@ not nil and @write_p@ ne "f">
+      [<a href="message-edit?forum_id=@forum_id@&message_id=@id@">edit</a>]
+      <if @attachments_p@ not nil and @attachments_p@ ne "f">
+       [<a href="message-attach?forum_id=@forum_id@&message_id=@id@">attach file</a>]
+      </if>
+     </if>
+     <if @delete_p@ not nil and @delete_p@ ne "f">
+      [<a href="message-delete?forum_id=@forum_id@&message_id=@id@">delete</a>]
+     </if>
+     <if @mail_friend_p@ not nil and @mail_friend_p@ ne "f">
+      [<a href="message-mail?forum_id=@forum_id@&message_id=@id@">email</a>]
+     </if>
+     <if @reply_p@ not nil and @reply_p@ ne "f">
+      [<a href="message-new?forum_id=@forum_id@&reply_to=@id@">reply</a>]
+     </if>
+    </td>
+   </if>
+  </tr>
+<tr>
+ <if @headings_p@ not nil and @headings_p@ ne "f">
+  <th width="15%" align="left" valign="top">Message:</th>
+ </if>
+ <td colspan="2" align="left"><br /><%= @formatted_content@ %></td>
+</tr>
+
+<if @author@ not nil and @date@ not nil>
+ <tr><td colspan="2">&nbsp;</td></tr>
+ <tr>
+  <if @headings_p@ not nil and @headings_p@ ne "f">
+   <td></td>
+  </if>
+  <td colspan="2" align="right">
+   <if @user_id@ not nil and @id@ not nil>
+   -- <a href="messages-by-user?forum_id=@forum_id@&user_id=@user_id@">@author@</a>, @date@
+   </if>
+   <else>
+   -- @author@, @date@
+   </else>
+  </td></tr>
+</if>
+
+<if @display_attach_p@ nil or @display_attach_p@ ne "f">
+ <if @id@ not nil and @attachments_p@ not nil and @attachments_p@ ne "f"> 
+  <if @attachments:rowcount@ gt 0>
+  <tr><td><i>Attachment:</i> 
+   <multiple name="attachments">
+    <a href="attachment?file_id=@attachments.file_id@">@attachments.name@</a> - @attachments.title@
+    <if @write_p@ not nil and @write_p@ ne "f">
+     [<a href="attachment-delete?file_id=@attachments.file_id@&message_id=@id@">delete</a>] 
+    </if><br />
+   </multiple></td></tr>
+  </if>
+ </if>
+</if>
+</table>
Index: openacs-4/packages/sloan-bboard/www/simple-message.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/Attic/simple-message.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/simple-message.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,43 @@
+ad_page_contract {
+    Display a single message in a reasonable way.
+
+    @author John Prevost <jmp@arsdigita.com>
+    @author Anukul Kapoor <akk@arsdigita.com>
+    @creation-date 2000-11-30
+    @cvs-id $Id: simple-message.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+} {
+} -properties {
+    mail_friend_p:onevalue
+    attachments_p:onevalue
+    attachments:multirow
+    formatted_content:onevalue
+}
+
+set mail_friend_p [ad_parameter "MailFriendEnabledP"]
+set attachments_p [ad_parameter "AttachmentsEnabledP"]
+
+if {[ad_parameter "UserPostsDeletableP"] == "t"} {
+    if [info exists write_p] {
+	set delete_p $write_p
+    }
+} else {
+    if [info exists admin_p] {
+	set delete_p $admin_p
+    }
+}
+ 
+set formatted_content [acs_messaging_format_as_html $mime_type $content] 
+
+# we don't want to stomp on the 
+set current_user_id [ad_conn user_id]
+
+if {[string equal $attachments_p "t"] && [info exists id]} {
+    db_multirow attachments get_attachments {
+	select object_id as file_id, cr.title, ci.name
+            from acs_objects ao, cr_items ci, cr_revisions cr
+            where object_id = ci.item_id and
+                  live_revision = revision_id and
+	          object_type = 'content_item' and
+                  context_id = :id
+    }
+}
Index: openacs-4/packages/sloan-bboard/www/spacer.gif
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/spacer.gif,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/spacer.gif	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1 @@
+GIF89a�����������!�����,�������D�;
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/subscriptions.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/subscriptions.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/subscriptions.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,39 @@
+<master src="master">
+<property name="context_bar">Subscriptions</property>
+<property name="title">Manage Subscriptions</property>
+
+You have the follow subscriptions:<br>
+
+<h4>Forums</h4>
+
+<ul>
+
+<multiple name="forum_subs">
+ <li><a href="forum?forum_id=@forum_subs.forum_id@">@forum_subs.name@</a> [<a href="forum-unsubscribe?forum_id=@forum_subs.forum_id@&sub_page=t">Unsubscribe</a>]
+</multiple>
+
+</ul>
+
+<h4>Categories</h4>
+
+<ul>
+
+<multiple name="category_subs">
+ <li><a href="forum-by-category?forum_id=@category_subs.forum_id@&category_id=@category_subs.category_id@">@category_subs.name@</a> [<a href="category-unsubscribe?category_id=@category_subs.category_id@&sub_page=t">Unsubscribe</a>]
+</multiple>
+
+</ul>
+
+<h4>Individual Threads</h4>
+
+<ul>
+
+<multiple name="thread_subs">
+ <li><a href="<%= [bboard_message_url @thread_subs.thread_id@ @thread_subs.forum_id@]%>">@thread_subs.name@</a> [<a href="message-unsubscribe?forum_id=@thread_subs.forum_id@&message_id=@thread_subs.thread_id@&sub_page=t">Unsubscribe</a>]
+</multiple>
+
+</ul>
+
+<p />
+
+Add subscriptions from within particular <a href="">forums</a>.
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/subscriptions.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/subscriptions.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/subscriptions.tcl	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,47 @@
+ad_page_contract {
+    This is the central interface for managing a user's subscriptions.
+
+    @author Anukul Kapoor <akk@arsdigita.com>
+    @creation-date 2001-03-27
+    @cvs-id $Id: subscriptions.tcl,v 1.1 2002/02/15 21:27:07 ben Exp $
+} {
+} -properties {
+    forum_subs:multirow
+    category_subs:multirow
+    thread_subs:multirow
+}
+
+ad_maybe_redirect_for_registration
+
+set user_id [ad_verify_and_get_user_id]
+
+# three sorts of subscriptions:
+#  forums
+
+db_multirow forum_subs get_forum_subs {
+    select bfs.forum_id, short_name as name
+      from bboard_forum_subscribers bfs, bboard_forums bf
+      where bfs.forum_id = bf.forum_id
+            and bfs.subscriber_id = :user_id
+      order by forum_id asc
+}
+
+#  categories
+db_multirow category_subs get_category_subs {
+    select bcs.category_id, short_name as name, forum_id
+      from bboard_category_subscribers bcs, bboard_categories bc
+      where bcs.category_id = bc.category_id
+            and bcs.subscriber_id = :user_id
+      order by category_id asc
+}
+
+
+#  threads
+
+db_multirow thread_subs get_thread_subs {
+    select thread_id, title as name, forum_id
+      from bboard_thread_subscribers bts, bboard_messages_all bma
+      where bts.thread_id = bma.message_id
+            and bts.subscriber_id = :user_id
+      order by thread_id asc
+}
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/subscriptions.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/subscriptions.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/subscriptions.xql	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<queryset>
+
+<fullquery name="get_forum_subs">      
+      <querytext>
+      
+    select bfs.forum_id, short_name as name
+      from bboard_forum_subscribers bfs, bboard_forums bf
+      where bfs.forum_id = bf.forum_id
+            and bfs.subscriber_id = :user_id
+      order by forum_id asc
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="get_category_subs">      
+      <querytext>
+      
+    select bcs.category_id, short_name as name, forum_id
+      from bboard_category_subscribers bcs, bboard_categories bc
+      where bcs.category_id = bc.category_id
+            and bcs.subscriber_id = :user_id
+      order by category_id asc
+
+      </querytext>
+</fullquery>
+
+ 
+<fullquery name="get_thread_subs">      
+      <querytext>
+      
+    select thread_id, title as name, forum_id
+      from bboard_thread_subscribers bts, bboard_messages_all bma
+      where bts.thread_id = bma.message_id
+            and bts.subscriber_id = :user_id
+      order by thread_id asc
+
+      </querytext>
+</fullquery>
+
+ 
+</queryset>
Index: openacs-4/packages/sloan-bboard/www/test.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/test.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/test.adp	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,15 @@
+<master src="master">
+<property name="context_bar"></property>
+<property name="title">test</property>
+
+<pre><%=[ns_quotehtml "{}{}{}<><><><foo>bar</bar>"]%></pre>
+
+<pre><%=[ad_conn location] [ad_conn package_url] %></pre>
+<pre><%= [bboard_message_url 8035 1592]%></pre>
+<pre><%= [bboard_message_url -absolute 8035 1592]%></pre>
+<pre><%= %></pre>
+<pre><%= %></pre>
+<pre><%= %></pre>
+
+
+<% bboard_garbage_collect %>
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/doc/acs-messaging-and-bboard-dm.gif
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/acs-messaging-and-bboard-dm.gif,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/acs-messaging-and-bboard-dm.gif	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,197 @@
+GIF89a����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������)��R��z������"3�1J�@`�Ow�^��n��}�������������"��D��f���������3�M�"f�+��3��<��D��M��U��h�|�:��W��u����������3��P��m�����������������3�3M�Mf�f�������������3�M�f"��+��3��<��D��M��U�h:�|W��u������������3"�J1�`@�wO��^��n��}�Ҍ�����"��D��f�̈�ת������33�MM�ff��������������������:��W��u������������3�(P�7m�E��T��b��q������3��M��f����������������3��U��w�������������--�DD�[[�qq��������������3&�M3�f@��M��Y��f��s�������:��W��u�Ȓ�ׯ����3�3M�Mf�f���������������������:��W��u����������3�M�&f�3��@��M��Y��f��s������:��W��u����������!����G�,���������H����*\Ȱ�Ç#J�H��ŋ3j�ȱ�Ǐ C�I��ɓ(S�\ɲ�˗0cʜI��͛8s��ɳ�ϟ@�
+J��ѣH�*]ʴ�ӧP�J�J��իX�j�ʵ�ׯ`ÊKV��h�:8 �Z�D�5@����]y7�ځ}����v0K�����˸���㺥[P1�ʅ
+Z~�P�ܺ"-l��Ⱦp�&}״�֬�B.���\�l�������Z�����sN�Zal��9�&�<��ꮫ��|�k�χ��Ľ����[�5/[�����j�<t}��v��q3A��I�Wv~Y6tn%�^
+�yA�^���`{�]H��q8�z�P��E([��Qxa�&B�`�~u�"n-�W�m,:��5f�b|@�e�H���نdb�-yx?��cyl��\H�F$i��VZCw�r�]/J9�?��"�k�h�BV���)��ځ���$�jRIc�6��h�)ᅬA�梆*䣐26
+(s.�e�Lڦg��m��v�Z����N�i|��_z0������X�>�Wk�x�yky,&�������;���"+l�g�����f�|F�(�8�*��:�k���֦�����teƒ�픡�Q~�v�ն�/�����5��n����o��N�]m�����.�J-�h����:,[���+��]���[�h�ɫꨕ��+kjt'��'����\�������ZiDC�zt€"�[�('͠�T�K���/Z���m�d�p�b�l��Rņ��Q����_b
+����4F�:���(�7�ˍ��ML���}8��
+k��Ҍ�1�9��,��.��V��(��v�])�h��:Rjs�2�n
+��_/���Z;�sH�%�i�W���ʝK۸��,�Ҍ�|�L��z�d��/��	g�A{.;鯛>wȫ�o�O���)�ys��Z��L��A���G�z3��`�+��w:��qj*���u:�E.O��������O~=�U�����lz�:�GX'q�@�C�edBcI~TT�<��Ygv�9ᕠ����_��� w��U0l������<-��`��P�ʀ�S˫��.�-1�F$�Ǩ���'�8�}Ш.6ίy�J��2�;'Ug5jli(�Eeun��k�9G*.|wÍ�����90�LL�s7H0�'.���e98�񓠤�~ʓ%�eF��D�v\v;MR�;���G�}�f-�c�7��M{J��^FQFw���L+��� t�	F���62c�3���Nr1��'2�D�ȤҜd�-�㼻��g⌧<�I�z���̧>��υ�����<�0�…:|1�ĉ+Z��1�ƍ;z�2�ȑ$K�<�2�ʕ,[�|	3�̙4kڼ�3�Ν<{��	4�СD�=�4�ҥL�:}
+5�ԩT�Z��5�֭\�z�
+6�رd˚=�6�ڵlۺ}7�ܹt�ڽ�7�޽|���8����>�8��Ō;~9��ɔ+[��9��͜;{�:��ѤK�>�:��լ[�~
+;��ٴk۾�;��ݼ{��
+<���ċ?�<���̛�@�@�
+D�P�B�
+>�Q�D�-^ĘQ�F�=~R�H�%M�D�R�J�-]��S�L�5m�ęS�N�=}�T�P�E�E�T�R�M�>�U�T�U�^ŚU�V�]�~V�X�e͞E�V�Z�mݾ�W�\�u��śW�^�}��X�`…
+F�X�bƍ?�Y�dʕ-_ƜY�fΝ=Z�hҥM�F�Z�j֭]��[�lڵm�Ɲ[�n޽}�\�p�ōG�\�r�Ϳ� p ��"L�p!ÆB�(q"Ŋ/b̨q#ǎ?�)r$ɒ&O�L�r%˖._Œ)s&͚6o�̩s'Ϟ>
+*t(ѢF�"M�t)ӦN�B�*u*ժV�bͪu+׮^��
++v,ٲfϢM�v-۶n�+w.ݺv��ͫw/߾~�,x0�†#N�x1��r@�,y2�ʖ/cάy3�Ξ?�-z4�ҦO�N�z5�Ύ_�. 6��(g�έ[*�ݾS�
+|8q�‹#O~<9��-�;�^����9R���p��޿/�X~�^���{7�~}\���3w�Y�Z�O6�� ��6�Se�G�qG���5t�	� 
+�U�C�7ax�Yx��Ye8����'Ђ�A�V�?U8 \��8�`A�T��aC�!F�8�bE�1fԸ�cG�A��PdI���P%˔�0�L�6k�DH��ʘ:G�4�SfJ�@[�L���R�
+m&�s*ʧA�"�*ըΨX���U�U�\O�U;tm[�o�ƕ;�n]�0��EYv/C�x���;X�ࢄ%�teY����	X��ƅ1_μ�2�˝���x��Ħ�J���ſ�aǖ=�vm�_�	z�A�l��;u��'�F<Zyr�˝�;�9t�џ[�\<s��Կ����W�x��ѧW�^9{��%���<�o�^�k�Nڸ������!�l�sZ�8������c��)���1�h���
+2܀S�@�j����;�A�L[,8I�
+��������;��ۊ��bB�ڐ�#�LR�֌\�;� ��**��T��Dt1�*C�rH��oL�^4���t��&݌S�"�$k*�V\s-8��3I.T����2;*��F��2MDѬn��p|�6��2O��$?=
+UԎ�T��|5NU9���SE�C�A5i�̳GA���GymQ1//
+S�[Ӕ�K�Tq�W]�u�O��VړJU�S-�b�Im1t��au6V]���Nd��,��z����T��ޮb��A���s+<ݝ1AC���ۂ.���&\ݜL�8�D�W��>��E3�8ci=�Xd7՝�!����X`y�����]2f�h�Yg0w�Y�;|-�N�R\a}�f�q��a�e�\����W53"����hzYԺP�������-�$��(�|�m���hu�n�l������H�<�F
+���Ѽr�����!�:��i�J�]<|��=���)]����t���wsՋ�һ\/�t�O��"��1܏8���5�o�k/~�;�:X��m��{-�bЍ���������'�������Iv�O�'��1�H����P{��G�~
+s�|�ꯍ(��E7�n'�SV�@y�ejߣ����T]�����.^�b	�ѿ���j���	������{��ʲ��,n���������ly	�ղDhCB��3�j�
++�<��V�#@��H��A�*\Ȱ�Ç#J�H��ŋ3j�ȱ�Ǐ CL(��I�$�D�� ɕ#�|�%B�3m�d�s'L�?JteQ�7���ɴiϠI��i��Ҩ<�N}Z��Ϝ[O����ٳhӪ]˶�۷]��
+��kP�#�R��u�U�~���ugԥ�J�k�`�|{��U����Gv,��fϠC�M��鏜O����hʢ��T���벗%��
+6Ļ�#�M��Q��K�}[��ş6Gy�jѩ�k�ν���
+���'���B��-����ip����o�<s��\{c6�����WB�WR�&���6�����}�	g!o���_z2I��|��Wu�9�Zy��8���ih��E(�2�h�8�F#��5�����vb�C�T䑇=Vbr>2�d^��]J*d�����U
+�S�,��oc�i�h�%��=�5r��f�^�Cp�)g�_
+�ڞx6�ow�f��t2Ih�?��焔�S�r��b�K�I���v���Zښ��*�ܡ�������:���������ʩ����믵{֢�����:"����6�쳟A+��v�l��f����v��Z�~+��K��>kn��;����{���kﭯ2�j���K���[������!L�����3��nWl��g���C�l� �,��$��Y��rD+{Բ�&A��(`��8���<����@-��/{��H'���L7�t����Q:*剘"�&�S%
+r�bz^��*�օ�䵛.�-���vL`����Vs�硹l��o�j�ݯ[G?m��3-u��7���u�����pX���Vr^g[
+�獍�e�+n�9�]B���\n�{G�	�ԅG���J/�]�/��<O>�d�ї�S*����j���;G=��G	i��N���Kߟ��o���'|���Cn|�wO�b�V):�.b��.b���,#N}^��/F`;��������$�…
+0 �ĉ+Z��1�ƍ;vL�0�ȑ$K�4ѣʕ,[�|	�"ȓ&gҼ�3�Ùz>�	��P��l�Dt�ͤKAEZ*S�
+�*%���ЬP�&��p+O�U�~��T�^��-*�+\�G�u���S�|�����dʘ�ni5��ł;~9��Č)3����ۄu����Vj۽A�&��0[ժ5�������^M;�g�L[��]�5��Q/�q�D��fT.1���Σ�=�u��t_~<�����-2_�]�y�b��D~����۫�^�:y�鱋7.^�U��l���Wm���kk	'���F i�=��nʅhJ\��}�!��
+��)*u_sѽ(�Lн�z1�(�0ָ^��$N��#u.�؜t6¨cyMIޒDN�^�����An��kGY�`�Sי�&����Uj���md�9���	W����o��e���%D�����UR��O���R2z���y葉.jݕ�iz����e��2ʞ��j����j��Y�D�	gX�f�ՃT��YڊЮ����z�\r�z�m�⊬��5��>�+�Ś�j���X��~%��6�i��*����>W��������j�/�5i�d��Kp�Bzk�_	Lp�?-��)c�/�^w�e������q�����7Y���1ʡ���}�j������#��ز��se;M4��<1���������Y��EYr��Y���T׷����u���h����|5�G�4T�}�-w�v��vf1��G��6̯�5w\6�w8��}|3�L�8�}�:���z���o�y�ߝ��3	���z=����8�%~Y��S�x�i��4��~��*��{���|�po�j�0�,���>��JOo��:�����/�.V�G��~�ė�����#��S��%ٲ����+�%���;ёM����Ol���w�6���w4� �����p���5Ɉp�.���
+G����&I=���p�2�aMV������ѡ�.D�xK���$~K@(\��("®��Y�DJqP4���nхW,�a��9*�q�?D��7�Tk.��"G��юtcV��j5Ŏa,���C6*҉�D�"�HD.q�uB�f���YiROh��%���_5r�ȓd� ���4R��l�5HI1��7��"D�[j���<!�\	����,&#�GC�Ph��Ն�)�l�r�����L�Gc��v#�6��Jd�P���U�c'��ŏ���3���vZs���fm�	I{�͛��g�YCY�0���&�)���s�����	4H0�A�6`@D�)V�xcF�9v��aH�#I�4i�G�+Y�t��E�'MΤygN�3m�����N�C�Th��ÂA�"E�jT�S�V�z�U�Y���lX�cɖ5{mZ�k��u�pm\�s�ֵ{��ۤz����t�A���L4�ӽ��f��odɓ)W�y�֜�/O��t�ЂGg���tۿ�����֬
+�\ԵWڬe���x𫨳�)\�q�n��^^���Ӻk?�
+�:��E�ގ{;X��	{R��5�t��٧n^�����緇Z?��������߿��/�����LP(�����"d�£b��5���	/���
+C�oC	�+œ�K���$at��͐�Q:����}��>Qk��A��Í4 cDϫ"�;���
+I�F��%���Ku���2�<M�:R���-�䐾3���sN��d�+-!jsK.%����Q5�K�H%�t$<j�I&ݜ������@��tP@�`S�
+mP���T��)���Z���Q3��MV����R(4KE����Q�4ˁ�̎XX���S[��tWj.>	*������E�mv�`�]��gc}Wk块^���lTo�C7�n�
+VЈՍO�{U�8!Zuؔ�TN�w�UO��
+�S#��8\�8�c{�T�T?�6\���
+�{�}���Js�|��S���7C�� d��h]:�Z+���7q�nE�q��Z�w��j����Ge��i��n��k��X������=�h|g��Q$?��So�5��2�l��ƪe�_�����Z�?��8��VFu�ʯn��)�6��X�K
+�|s��9k��m��erM�5xr�U��&�a?�=e���n���\g�	�|S�E�3`ܣ����)�ٽ��{�?�{ڌ�|�d�U�Y��=�y��J��;����?[�U����W6���t��m�t�b����@~M|�Og�73k�M�Io��~����&���!�*��`���0G%j���^iX�I��7%��\Ȩ���8,�}5�h�hpd�
+��D������$�…
+L�0�A�X��1�ƍ;z�� Ŋ%�<�2�J�#W�49�̙41�t��fÜ:{��	4�СD�=�4�ҥ+y2u�*Ӥ17N��R*փZ�N���ױd˚=�6�ڵ/�u���P�!�b���ݶK���8����7%�7bb�5;~9�E��
+/�ײ�͜;{��1Q̃%�>�2e�|��f
+;��ٴ���[[$�Լ{�~}8g�8s?�<���U�~�7I��w��>14��ܻ{��<e����[R�^���
+٣?������W˳d��������|H`����}iA5�~�u� B2h�HZG�n�ih�D��^��i�Ї!��І)v�a���h�e*��a~��a�J8{:��Տ�	��r	idi,q���]>�d���H��7%�9q�ez`�%�[vSvV�Ȣ�a&9 �f%�UuZv�Dy�|	}�d�szȕ�����j�)U����(���ɣ�8.�%��F���;�� ��}:�Z{��$�6y������)��J飶��&�NqY+���Z���j�k��"�������* Eiv�j��kl�a��-�eJz�{k��
+)��nˬQɎ�챧z��~f	���}��mZ�+�P�8����o�ڮ)��*.�
+��o���x�q�� w��7q��v���n��b���(2�ކ�0�0����"B|��OF��z��/�=׬����W����Y�Hg�W����4�+�K�U�*��׶l�a����m�rF�7f�S��uӏ�
+�xgR���t��������Kœv�E���d���vk?+���:	7��ZNy�*�
+l���y��[xġW��犫�xO��>y����'۶R����y5��y˦˺2���.߃�|��\�QMS^���I����y�n�����ߑ��̮y(�o��9<b�È��[���ū������$�…
+L�0�A�R�x��ƅ7z�2�Î"Kr4��d��*�Dɰ%L�3kڼ�3�N�2w��	�'СD+
+�y�cDŽYRd���@�N������֍Y�N58��� ��,K�N!�Zk�,۪۞`֥�Q��I�����ol8qQĊ�d\2��W���sf�_5��xqh���״鴧+�=�Zo�-_�^-������<:�L�m�7N����̑��r�͖�ʴ�y'��6�c���u���ˋ7_;�n���_�������ۿ�_�w��'�OKWu_]7]'�wXs�-�m
+�^y��W��M�n�a�~葁J��tj�|�}�s�1�R�2JhՌ��_v%"|-�d�B9X�\��_vRG��&"I�p
+�Z�����yW�V����Z�Y��BIZ�j��f�n>� N%Ze݊=���vo��fd`��_��_c�H�:����ہ�y���U�{I�	�ybԩt)%���R����%�)�z�g�i���*)�y�zj�+yF��AiԮ��
+"�&;S�5>�&9��$��d��b�kfT���E۔�p����f���*�i�Ȋ��b�>+�>�6����8�\��׬��2	m������Km�wn
+.�	�Y�M�v6-�%�'��k5q��VLn�}�W#㷲����|,�!cL��$�����n�s�B��s���g���q�97�-���Tt�Tu�A�l4Ojr]��������-�(M�����>��������S���6�vv�~M����E��C�-㵒MsͲ�
+����}��};���S���ҿN�θ�n�g/���!s��"'^���b�e߮q�Z�z���ǚ��*Шw}rV��Wl��
+��ꙷ��ִ[\�ټ�=��y���
+|��r�2����n?���7�-;��O2��{��ը���MFJ ��'4��n�����V?�i�r���.6�����	����?���,t�`�>ם�W��N�����p{�,��;n�zCԞ�����ψ4�	�C�eK�Md�ڈ8�)�K�������JP*�jX��C�LIt�m�V�6��|[�8Bsy0v]�����<��qx�3�5��Dr0jD[����,?ϐ�w����=�W˗;
+j�p��������R�l�*W�I�+t���K�*��ʖ�;�R`��P����B�����F�S�$�NyCENl��,���Q�oR�b�&u�pvș�!4��������f9���u	�����B�w���'@��H��A�*\Ȱ���#��"Ł-b|8Q�G�?�I��Ȑ&S:�2#Ǘ.�D�2%͚q��ɳ�O��
+
+���ѣH�*]�t�M�OU��`&U�0�"�ʵgԮY^��eU��vt���۷p�ʝK�.үI�)!Q�@�V��ga�]�m)xp̳�S�ܸ�b��3k�̹���u/�-�4�ɧ��n�:���"a��M���۸c���3wC޾Wr^����ȓ+_�\�q��Q7�>}x��P��γ�֊C'�����P�0ϗLX}����w��(}����ǹ�:[����C	�%�wҽ� d~��XF� ������wan��!b~�M"���Tk��Z6X��,�%�ָ؀�ih����8�v>���E
+9�Fz�cO��Y¨��-N���+�䖪�����H���iav\.x%e��	�c©b�Ry\����"��柬y��T楓��!�'�!�c�n�eg��>ڠ�N�ۓ�F����I�y��
+�e�)�]��:*����	蜔y:Y��Z*��j)�y��૪�ĩ���j�������IXd��lX�f���v����+�:��ҙ+�N�Z+��јe�/jɫ���{��vɬ�W,/Vl�k����s2�j����.����U�q�X��Ǻ��e�{ֱ�c���-�ٚo��Nܱ���ꢨ��q���̲k�r�gF�!���J?KVMB-uw�N��Cm�jY[٫�
+�
+��8�lp�������*�(�K��>����a�zd�pE6v.�JV�7���/�NJ'�z��w��hc�d�x����_[$��o啇���X�N��^>�yWk.�~O�������\���u��yu���+�����~��̙����?/��H�@�@�
+pP�B�
+&t� D�\�H��Ɗ9~R�H�%M�D�R�A�+]��S�L�5m�ęS�ŝ[���3fP�E�E��!Q�M�>�U�T��Ҽ*2kՈ[�~V�W�e͞E�V-L�/�n|{6�Z�u�ε�W�^�}o�E	xiȖ�g��XqMċ?�9m㑔'&i��dΝ{Z�觚A����2NԤ]'n�Z�lڞcwt��bꇽw�~�;8D�k�}�r���* E�W@x�팝���x��Y�]�2p��ݻWo��|����ǟ.z�Ӆ�p��ֳ�>�L�@dp>J�!�೮;��A
+�zpC?|�CU��B�*|o�	3�ű\�1�E��?��ˮ���	Gs�OF!��H#��!3�*�#t�I)�l*J�I*���K/���?�ñ40�d	M5�4������┳N;!s%:����=�TN7����@E3�PE�tL�]�3H#��<���H��A�*\Ȱ���#�(��ŋf�ȱ�Ǐ C�I��E�&S�\ɲ�˗0cʜI��C�7M���r'ϟ@�
+��'ѣH�*]ʴ�ӆFc�J��իX�j�ʵ�ׯ`�>K��O�fӪ]˶�ۗh�W�ݻx9��˷�߿�Y��;5h��������ǐ�2�Kh�Ș3�����ϠIrv[���ШS�����יY��ʓ6�۸��ͻ�o���^�9������+_�nc�6�7��89��سG���̬��/�O��y�ܟj����{����Ϟ�i{����Z������W2���!����	���pA���:Qh�}9��W0q��i�$�$"S�Ֆb�,Vtb�0�xы�(�i2�X��:��#�G���>�d�H�x$K.�c�06	�Ji��I�Xn��o��8�`A�T��aC�!�0bE�)ZԸ�cG�A�9�dI�3�T��eK�/aƔ9�fM�(o朘s F�?�:�eJ�G�&U��iS��>��O�W�f�*qkW�_���2�X�TyZ5��mێe�ƕ;�n]�p�թ�n_�[��<�pᬁ���pc�7?�<�r婃�dl�sg��=�=�0h��in&���i֯a�>��5Kղq;���wo�2w�E=��o�y�'W�\e�ÁCg>0u�ױ+tV:����/ݒ�|y��v��|�������������o���Ҵ�bϿE���<�@���!<+�	)|
+�1�P�
+9���AQ�I,��QLQ�Yl��a���
+i�Q�����y����t4I��,��#=��!�l��'�lKɻ����+�
+� �,h� „
+2l�a��'RQbŌ7r���#Ȑ"G�,i�$ʔ*W�l��%̘2g�����8w����'РB�-j�(ҤJ	�ĩs)ԨR�R�j�*֬Z��lZ�)װbǒ-k�,ڴj_z�	v-ܸr�ҭk�.ފmg����/���.�q�̾�3n��1��E�T,�2�̚7s�L��΢G�.m�t��lU�n��5�ز'�nz6�ܺw�n\����‡/n����3o��9t��&�n�:��ث�\��;��A�csG�}<����/.�<�����/���������3?I��7 ���N� �
+:h�#)� �Z8@��$X��A�	.d��!��N� �Ċ5n����G�!E�$Y��I�)U�d���K�1eΤ2bM�q�����O�A�%Z��Q�I���S�R�Q�N�Z��U�Y�n5ٴ�S�aŎ%[��Y�iվ�J�Z�q�Υ[��]���|���_��&\��^�}
+/f���cȑ�"��X�e̙5o�|�2L˝E�&]��騟�^d���kرeϦ]��mܹu�����o��y�&^�8\�.�/g���s�ѥO����u�ٕZ��0w���e�g	��y��ѯg�"F��Ӫ�_߾x���'Ϳ�����p��$�@
+30A[Z�A#��A	+�	>3Ԑ.
+7�p�?qD�B$�D�0DqE�S�E21F�����<�0�…:d �É+Z��1�ƍ;z�2dȈ"K�<�2�ʕ,[�|	3�̙$gڼ�3�Ν4%��	4�СD�=ڲ&ҥL�:E���ԩT�Z���eԬ\�zͺ��رd˚=;�'ڵl۞�6�ܹt��k7�^�x���8p޾������Ō#v9�M’+[��y"�̜;7��9���A�>��4�լ[�M�:veղk۾��6��ru��
+<8G�‹{%n<�r�ȗ;w����魣S��:���%k��9�����o>�H��ۻ���|���ۿϴ>������d�H`F��`�%��{6a[��8�`A�&T��aC�x8�bE�1fԸ�cG�A�QdI�'Q�T��eK�/aƔ9��L�7q�Թ��D�?�:�hQ�G[�D��iS�H�>�:�jU�W�����kW�Y�~;�lY�#�U��m[�o�ƕ;�n]�w��ջ�o_�<�paÇ'V��YǏA��re˗3RƼ��dΟ?{v�tiӏI�V�Q�j�_[�M��vm��m�>[w良���=��K��kG�<�r�ǙG������խgG��+t������2w��1��}{���ˎ?�#�����w�_�����*��,�<
+0�B�*�6%l��
+���)1��A
+=$
+���6ILq(U
+�m{�(a��'ml.G�d4
+����� c���<RI�\r;'�krE)��Ң!clK<-E�r!/�$
+� �,h�`��
+2l��!ăF�h�"ƌ7r���#Ȑ"G��H�$ʔ)"���ɗ*%άi�&Μ:-�ܹӤϠB�-j��B�H���	��S��ڤ��*֬Z�n�i�+ذbǒ]���֨պT�ViB�&Ϧ���.޼0�bt��/���+���'K�-�.f��eb�1
+S�|�2�˜7s�lT�g�G�%=��c�PQs
+*94��
+_-�6�܄i�j0����:.n\t��ʏ{���9t�Σ��z��ȫ�s7���h��.�<�����齵����fo�/y������s�
+�5 v�m'_}*�U~y� �Nՠ�1�p�X܃#Q(!�M��a�%�(ч��Vڊ��E|.�%T�'�؞l$޸��:��܏A�T#Y>
+ydzF"I�K�ؤXJ:9�rRR�ߕY>eXVj�eg^�Y�cBX&�h��&^b�	��o�gVn�y'�t�I��{��'Sv�9h���ݡN����:�碏���9�Hi���Ԩ��vz#��~:*���ʑ��.���	4H0�A�6t����	#V�xcF�9v��dH�#EN$yeJ�+ORd�fL�3i*tY��I�;y���hP�:�5z��M�K�6
+�ԩG�Q�V�z�T�[�J��lX�b-j%{mZ�fն�
+�m\�/��e;o^�2���۳�_���ۗpbŋ"f�8�aȓ�Jn�rf�a1o����g�VC��<u꟧U�.�6��gYǶ}{dmܓg��Ͳ�ƉÉ7~yr�˙7w�zt�өW�n��u�۹w��<u����'I>c��ٷw�~|��'η~������@��[-�
+<��\����1͛�#	+R��5ܐ�=4�0���M<q�S��#b4e���=�q�mܑ�S�� ��IG�<Iq�+�&�|��%��R�*�R"(�ܒ�����0�$�K�ʴ��3��6�T�"ݜ�N���<A�S�:��3�;���BR�D�#�=��s4���+���OR�"���M�$�S-mT�>1��APU5�I3M����L%5�>�̮�X-��Yk]�UYyeuWV)}p�R�-�XbyE��`Q]��Gs%�>Dݶ,F[��Xh�EV�p˵o�c?���Q�}�]xӝO�T�e�pɭ6^[]͵�s�͖+}�V`k>�v�\Z�ݵTJO�Ub~�3bL-x`]�ے_��aw��T��Y�x�u]��7e�#�7���f��yߞ���e�}�ya��}��o��cau�9c�v�˪�~�TmM�&��V:j��Fcek�����y��:n�a�)�_����Q��^9������޸���aR�<Y��>{R���
+� �,h�`��
+2,`�D�&R�H��Ĉ7f���F�9��(�》O�d��ˍ.[�|	R�D�9[�Ir�D�%e5IfˆJ�2m��E�Q���z4&K�)���H�+֚��-��jO�%�"��u�ظF}M��.޼z�*L��/���.l�0`�����J�%[�*���+�(P�;!}��kٰ��MY��ѠE_:Z���YW?�;w+��ugrƍlj���ת����n������ұ�Sg
+�:��ڷs�n�����t��̮Qfn�Ι7m��j����O�=�n�V�d���[i�%G�|
+7�k��>x�}�I�����!�!�8bv"�~��F�yRӂW���T�Zq
+Hc�5ޘQ�>�H"^(B�c�I�X�m>.����d�G�袄��8$�]6d��a�9f�`f$��E��mX�f��cW�Y(W{B��e�wZś�ґ��0����g�t>��s�V�(�2�i��4(�fr�)���Y"T�����b]z=������V߁~��[�:�[�6�g��n**B��Z�rpꆬ�kE��o��ք�%7ծ��*�p	�!�$z.������.���.���;/���f���/�������K��|�0�
+;�0�Kn�[|1���0w
+s�1��y�W�W�1�'�̮���Ld��l��+߸�/�̗�;������<4�E=q�1�4�D��SOC=5��	�4�Yk=�� *�5�a��u��]6�h�m��m����"�=7��Ɲ�@w��w�zZ7����v_~�ۄ��8ߍ���w�K>���L9�[��{j�yg>:�,�[:�����:�g�>;��~;��;���;��S����<��+�|�����{]��K/.��_/�� w�=�����]�/r���ϩ���>��R�~�@�O������w���������O���w��,�bJ A�L�l��+xA�����$�…&l1�ą'Z��1�ƍ;r��1$F�"K$i2�ʕ,%�l	3f×2kڼ�3�N�4W��訓���s�E��*}Z2)T��*�)��U�f-��QR�Nݨ��ٝe׺U���ܹt�B����W��
+{�ܴ~�>y�nU�|�:%+!�ǀ [V�\�[5'���s�ТK�>�6���L�F�I�.g�Pc�ի���ʫ%�|u�C�<m�z����̛^��S�}q��{d�b/������!k�^|�y��5�W��u��M'��:V�̪ڵ��jf��'�x��7_E�Q�`����S�EHa�1M��o�9f�k2]�e��Zp	5���=f�衆-
+g�O�ŇbgAŨ�d;�F!���'��a���b�E�X،�6e�<Y�e�SU	WWB�,�7�Cev�"��x�~m�&�Z�u����V�)o�]�a�|��U���'_�p
+��9
+��NꨤMI�Qr�D&�{�#v\5����2�(�Qթ!��&�������^�Z䏤
+��W��J����Jl��֪�~^��! Sξ����fym��F����	k��z���N��L��-�ƾo��m�_�H5�(d����	e��/ګ����+/q�jh/�����r믓���o�/6�1�C<i�X��pɇ��0��~��F+^x*jw������'��l�@�Y�=�,3�8�� �/�����\#�<_�ʟY]0�:q�*G|1{��^#wvti�m�։��Ւ��M�q�:��r���0�=�
+��,����x�iv�h۽u�x��)��)�7喋���>F�y�z�A].�G�G�誯κ語���N����^����{ֽ��{�O���C�{���|�"���ԓ�m�%����'���:z����@����}�{���>|�ՉX_�3�d�]&!��N~Ta�����!�3#b��~�T���g��
+�5]�
+��?q��x��ӧA�|p[%J�TR��1�4�ֽZU��/V�IQĆS7���G�ZP�*�B�dC+��N�7�䰇���շ�ԕ/�h�����9�]3��	��,h�`��
+2,���F	`� 
+^���!C�%�HqTF�7��K�.����dŘ8qj|8�fàB�-j�hE�J���8rb΋9����ԅUY��y�%؛Uj��(Ӵj����-ܸ�ҭk�.޼z�����#Ũ3{vbпK�
+��1�ǑW�<y�*d�{7o��9�ߋ�'O��0��]���trf��g{�m[���jk��
+�7��‡w���nj�.��\qC�M��ݑr��9���^��P���5"�j����ܛ"��=��̱�^���������[ҵ�Z{�&�qj'Y{���T
+9��~�V�d·YK:]�k�G�#R8��'ꖢ�-���Q,�����T�`���\A]A5�d3U�WbM��J��&�0~&�~4Bv#}푥!{9��$V�!�P:�ۘĉY&�i�w&R���s�I`��-fJ6bTd`5�)�KH~��Te�(�j�9��Ƅ��I^b�*e%(�֦�Lu*�觹%*���5jQ�J����Ț����ꛪ��+��嚗����+�����_uy�ZC��]�������ڬ�IU{-�m'k]Iݠ�Q���N�׹e]G.\��.����\��'.���/���+�R��%��V�{0����G�0�Q
+ko��>L��Je\1[��1�!s�0ȩ�|m�k�<��'��2�0���k��k�|�w��<s�3�*��sЦ�0�Ew4�J;=��?�&��J=5�OW���Q��5�[ǘ4�+j]6�O�|a��)��m��4�r��5�v�XK7�d���������=x�n_��\�S�8���mx���w��9�1�0衋>:饛~:ꩧ��ꭻ�:��N��s
+���	4H0�A�L�bD�N�xcF�9v�X�cH� E�H�dJ�+YJD�f̆/eִygN�i��S�O�C�=i�#ҙJ�6�(�iT�P�V�z�)U�Z�r���רbw�{֤Y�5ծu�nЛm�Ƶ{��Ѽl��M��^��	����‹��U��1c��%/�|s׺X)g��y3^ϣA�X�tjϨ&V�z�cװ�^Mwn�6m{�{�o��7�x��˗O����%�7f8`����
+s�X�{x���g��
+�w��?�on~�{��}��*�����y��~��k���`�<-!̯8���¸������N=̎@��ML�����p7�rF�xS/��6�NFdp��q�D�F�nܯ�$��0G%�:Һ&I<0�I���H'[�J/+d�>1��
+Â~�2H6C,p�7͜��0�̪̏��2Ջ�GO��B	��+��3,>�L?�}ԠI'�2N�PK.C��+�rNK��Վ�4ճL�+7�V!S�Z9�1V[Y�k�W��uW]��S�^�
+.c����e����\�
+�S��5F`��
+� �,h�`��
+2,��!Ĉ>�h�"ƌ7r�ȱ�ǐA�,9��ɔ*W����%̘
+_ʬi�&Μ:�\�s�Ÿ@�-z��G�3�2mjQ�Ө��J�j�jS�"���+X�Q��$��I�hk�]��-ܠ7�΍k�*]�y����oѽ�*���Å?����c�h#K^Z�2�sp���3�ТG�.m�4�ԪW�n��5lώcӮm�6�ܺ[g�I�7�����L�8r�Ɠ3o���莥w\N�:v���s��;x��߃[o�|���%�_�������ǹ�>������_�~�	��}(ށ	�e�)��aB8!_ZX��^��Jr��_ ����i8"�y�"����{/2v"�5���9"���2.F#�5���>����yd�C2�b�O:%`KJ	��W�H���qٗ�]^���~Yfog�&����j��^�r�	ܛw&h��H�@�@�
+pP�B�
+>�Q"„-^ĘQ�F�=~�1�Ȑ%M�D�R�ʕY��S�L�
+]��)�fN�=}�:p�ΠE�E��hR�M��\�(I�U�^�9�V�]=F�VlW�cYR5�VmX�kݾ}Z�\�g붔{W�ޓm��\2o`…6�mbƍ�u92bɕ�R�,sfΗw]wsh�NG[�\Z�Zȫ]�}���ʩe߮��n��y�F�{�p��U�6�'q��-2gl����ȩ_�]{H艥o�тzx����~��w��!�wߦ|��f__?�������6��/���3�\mA�
+d�<#�A
+A�P//�nB�����~�P��J4Q�SllE�Pd19c4�E�#���qG�t�q/ ݂1H�z4R�!�D
+� �,h�`��
+2l��!Ĉ&�h�"ƌ7r���#ȏF�,i�$ʔ*W����%̘2g�T�&N�7s����'Ё#w-j�(ҌD�2m���ҧ@IJ�j�*͡X�r��1�װb��˒�ٴj�j]���Ӳp��=[��ܻz��l��/��y.\p��h3n�Я�ȑK����e��3s���3躛C�v:���Ҫ�B^����WOWN-�v�ָw3���7Jߓ�/�R���8�+on�9c�Χ�DN�z_��CBO,};����Ó�ؽ<�󅿣oq���6��?��0�����/���X~�ן��
+��j�U ��!!xR��n
+�!�^X\�!f�af#�(������ۭ�b���bl/z8#n6���w<^�cZ6��ދC�h�s@�U$��1٤�PF���	4H0�A�6t�bD�(V�(cF�9v��dH�#
+Z4IeJ�+Y�t�2�K�3iִysaL�;?���hP�C��I�hR�K��l�jT�:�=ZkV�4�n���G�aɖ5;֬L�iٶ
+��m\�Q�ε{�f]�"O�����E��	��[q✊{�d�2C��)W6j3�Ù:��y�gУ�n&}Z�i�HQ����u첪e�&J{4nۻ�����o��[
+�xyr�˙7w�zt�ˉk�~{v������|x��6�W7�wf��ٷw�~|���׷~���W���������\�A����$�.�-��勐�5�D9���M�p��&\�*��e4�E�`��k�+��1# Yr !���$����Ӑ\JC��J��#K��,��.��27/�$̤��2R3K�*DN��,�:�cs�3��#���#<K��A�ܳ�A
+]oQ�*J�����P��{�RL'e�PN55P�.E��O'5��Cm�@VI-���T#���L��3(=]��Sc�5R^M�@\K
+و�AZi�p�M��UZg!�V=�ݐZg�VZ$�5Ym�w�Yӝv�k���x�v>cyҵ�s�mwS~�[w��L�`�ޜ�]}��[Y^�Z��݈V�↭,�℩5�Y�5�]�Mvx^�ϴw'|��Xᆳ��ߘ�ݏ�"޹��G��c��X�ZA��k��b��$�苙�9b��v�pm��[����&�I�Zj�EV9i����Z6�W;m��g�~o���.4�Q�i�U�{Վ�F�D��ꄻ���z�T[XM�>��g#p��6� �,h�`��
+2,`�D�#�81�E�1r���ǎ"5V$)��Ƒ/�̨�bK�)MbDi2aÜ:w����'P�$m��h��L�1UU9��ҧH3�IcЬZ�
+lzu�K�U�����iȯj%r݊�-ܸr�ҭk�nܷx��])V�ԘEQ��U0a�7��5:r��z�R�,�h��S#&�42c�2?o�x���
+����2̨�]�n}S��ɸw����7W�w3;͹obڵ7+~z�8��_Kn�7��Ƶ���{����SR%ߗ���vY���z����
+<������׊�.q�I�]Xɉ��hM�ǚ�:}����s�Ⴇ=d`��=��I!
+�VX�bz�\��Hb}�U&��5�x#n4���Y�񘖄%��R{@*���5�d�.u�H�8%O��h��q4d��֥r`�W���Q��C]I�J`����愿�x&�y�Zj���'��
+:(�l�y���*�(�1�S��J:i��=z)����V��z�)�km�i~��z*�f��Z��2:j�]��:+��ɚ���2Y����Xk������޺���{l^�:��}}*;-�t2-e�V�����-��^˩�嚻��᪫��Z�.���K%��N:���oP��T���˯u�̭�7|0�	�0�k�.�
+��UZ�q��.̱��f<r�+�1�)WD��*ol2�(�,��,��.��<s�9�������A����?+}]�|���K�U4ԯ�Ku�+�)5׵6
+�ba�=6�e�}6�i��6�]�6�q�=7�-]]7�y��iQ�n��h��}���67]�~�o�ċ��x�_�ɔ7;#��[�8��k9�
+�y蟗�/��zΛɫ_���3=z�����ป�z���;�xM�������v<������	4H0�A�L�bD�%V�xcƌ5v��dH�E*$YeJ�*Y�<)�eK�#gF�YgN�;y��xS%��C��8�h�?}�D��̨M��J4�ё�.�Hr@Q�ON�h�jP�D�N䪔�I�IY΅j��Ĵz����0U�N����(�L3hkU�`��W�X��V���~-<6�Lʖ/^�����C�|3o콣I׶};-m��5����F�R���}�#�ԾW��7�d�.??E�b�u)��=|x��8�����k���f]��R���s&۾sQ�pۛ�h����� �SJ=�8�ϰ��Ũ��?��C0��p���{�5�l�C�*<m���S�?���6���Mډ7԰jN"���l��$�3�Tj��~T��&�됳$��q���I�0[�+�;p�
+��-�1a���-�*��
+�J���� Do�2a{HO7���@�	P-�b+��x4�9���CH���) ����
+����J�6�mH�J�tOL��4�C�����DT�ԁ”�TID�O�X�XuR�,�F#�A8Qe��I�jqWU5
+�6d'\���u�[3���ڕ:��XYkv��Z�5�Y���p坷�MGu�X�m�[]��[��Pڱ�
+����u�V]���\�S�������!�}�(a�dqķ7h�4q����ȋU2L&m���#k��ђ�3��U�y9:m�p]�?��琩4��q������\�j���*�_Ι�^�j��i$[���Z��;�į���������-���pl�����E�q���`o��#�5%�ՠe[l�P�<A%WC�]]�[.���l�3�<�����w����]G���}Zt�u?8v�Q�KH2����}�;�|6�S���F�+ߝ�`{�}A�ߞ�������o|��WM���/ܧ���:Wן���͟v����~X������	9�A�dT���4�!�W��`��G�	f�����׿r����x��0<T
+�B���Q[�aXC��pb��y�B�Ͱf�N��n(�N-�vEġt���!>a?<"HE%�w	L⎦G�&a�������`����=�}5jc�XG2��A�#��("���#�F��9�юe���	4H0�A��bD�)V�xcF�9v�X�aH�#I�4y��Ð	Q�d�fL�gִ�r!N�u��9��ϕB�5ziR�1�m*��R�G�N�z�`՝Z�.�ڕ�W�`�uJmZ�kך��&\�l�ε[��ػ^���p`����{qb��M2&�XqRȑ�NJ*暖ij�Y�shѣgrnh�3鶪U�V�2쾰e[�-�6kݻ�V��w����(���Zڼ�g�z��śG�%u츷;�tw���N�K�*����#l�|�u����g�[�����j�/�+�t�'��L%����������J@�&���AR)�2l	��"�/D���?��"�L<k��b|�;ի���fܑ*��2��x�i��F!�ȦtJ���zJP:�E�4I(;��I״t�˛ރ�4�~�Q�4��p����"�`�$���0S�D<
+�R΁��5?߄�/��F2O,��3՜t36Q�E�Ē�Q25����L����3�N?�I�O�r����ƬѧD�B��\��0S�<�S�Q��� Lr�!G92�f@ٜ^�4Iu�5T.�� a��r�T�w�g���dZ6�g]���X�l�Vc�,PK�Xz�P+��2!y!k�k
+Ӡօ(�l�=��A�5WSg}���X�]k.�a+ѥ8dP���uS�8�`��8�v�Xc�i��̶�w�Mn����gYS�ii},�ץ�Xm���ٞ����D����A3".1�dV����8g����=M��ߠ��{n��×`����6o=5�d����C���ŵN����L�I��X��\ 9a��r�!w0gS�~Xo���֍�[������$<����|tǥ=��'�s��w�}'�m��~kV�!-Zh��:u��Ux]g����s�e܇��e��8�߷�੻����˯�|�SU���'f�X�����@��Gn�S��T纽=�{�aF��,h�`��
+2,��C��
+0��‰�D��@�=Z��I�UV$��%̘
+5ʬi�&Μ:jT��`˟{�5�c��#?.-�rbK�F����άZ_b�j�cD�G�&R%Z�cmv�
+��۸r�ҭk�.X�w�u�w����W.l��`��+^|�1N�o��\�2�̚7k��51��lE�~�t`Ϩk�����eǯ��^m�6o�fm8/��3�w}3p�u{�h�yp�̳Non�z��W�=t������G\����ǫo�wr���
+�����y�7�?�s��7���I�G�|���j
+�:��zƤ��֗�����T�f"g!���������/�%#a(�x[|�H"�<�6�R�xc�2�#C@��a�"G$��w؋-…��%`3����mIY�>�%�\VI��rR5�I�T��D$��&S'�'U}R��#�t�~
+
+�Yv救S{�)��1
+��tn�d��z�)���:*�gz��kz���K�ZJi�:~k��޺�C-y�)w���I���T���zH����E�>;���;����-�[MY(��A�(�Ś�RX]�;��{�c�I�d��T�沘/�w�����u;0^�v�m;�D$1�.��fi��������f^p�o�Ζ[q��>��)G�2�����3�n� �;��5�Lf�����\b��&o�"�t~�26��=k���J������2�2����q��^�/�Z���؞-�u�p��4�Q{yh���Jr���bMq�F���r�m7���}�J~�m��[sM8ʆ����-��Wι��{.�裳���=��j��nzs��n�w���s�'���S�����̻�����>w^|���H<�RFOp�5�@�@�
+pP�B�6��C�-^Ę1#E�=~R G�
+I�D��J�-]��3�I�5m��y3�Α<uڤ�2hN�%�E��(ʥIc6uU�ԚP�^Ś�N�\qZ
+	��P�
+����V�Z�US��	w+[�u�2T{W�ު]�>��d\��6�iށFI�k�1bʕ7ZƜ������\1��њ����6td��Q��]�ulڵ[�nK�aB��{r��{�ȉ9�����嶅z�9`���4�Np�u�ۭ�9���c�׻
+�~}����xl��s�W��ǟ�}��ċ�.��{��?��@���>�<rp%����:���P=��C��������=;$�,���O�_�
+Fg�?�H"P@]L��s�G�h$
+:\��#�\� �8l2J֔�,B"��J,�,LK�ot���~R��T0��,�K�D�J8�R�GDr�8[��L6�D�K@]�H�p��/��GGL�P7�MNK�<)�9��4&y�4T0E%�9A��Q4ud��F����R5r�=��ÇL�D<w��=�E�fE��d���TC�,8��KTS��5*A	Eu�N+Ԏ;��+��
+o��\�J�=�Z�Yy%��޽���PͶ�[ۦ\�^���!�}nR��������`�#�X^�.�J��~z����b��Xb�K�LdhN�?�Of�aaF6�kFLe�XVIf{o�����9䢗��]��`������>lj���x闯�d�c�����T|����y87��.{-���7�M�;ލ�
+�L����� p ��	8�p!ÂB�(q"Ŋ/b̨q#ǎ+6)r$ɒ&O�t��dB�&|	S&��g���s%O�=
+*t(ѢFsM�t)ӦN�6D
+u*ժV�b�*U�Ԝ-e~�)�رc�^E�u-۶kպ�+w.]�p��ͫwoֻC���,�;�NE�w1㶊C�,��ɖ/c�[�'`��#�
+�0�͙O�i:5�֥]Î-;�ꔝ���,n��gg�;8��,�#O{���a	}�z\�ʯ[��};՛P�s/�~)x�[�O�3�hݎ�ï�o�N��ϯ?�S�����B�
+X�z%f���D�B
+Ǡ��MXa� }g��B8�vn(�!��҈%��_ܝ�"r-��2҈�0օc���h!��$p7�(��F2hQ�H2��6�d��wߔWN���X�#��Uٔ�_�y��P��ߘi�$�l���Gs�Y��w^g|k�Y�K������'��z���2�c��٧��RZ���%z)W`��T��������#�@�@�
+pP�B�
+>�Q�D�-^ĘQ�F�=~R�H�%M�4��J�-]�3�K�/m�ęS�N�=}�ThƚC�EzP&ͤM�>�U�T�U���U�E�]g�ĺU�X�e͞E��aX�m�z�ʒ�[�u��śW���{����W�`…
+&�X����?�Y2�Ɠ-/���eΝ=�rh˙5�MZ�j֭
+�v-y��صm�ƝvnijQ��\�p⨋;6
+<�q�͝?Ǩ:Z�0�_Ǟݹt�w^T���̿�G�^����&��^�|�g��
+�6~����￟��N@Dp��"Х��0B����0C
+7�pC����CGL�C����$�…:|1�ĉ+Z��1�ƍ;z�2�ȑ$K�<i2!ʕ,[�|)0�̖*aڼ�3�Ν<{��	4�Ѕ5�=�t�̥4�:}
+5�ԩT�Z�Y��֭�z͚��رd˚=�6�A�j�>���%[�t�ڽ�7oݹz�„;S����>�X$�Č7^<r�ɔ+[�<U2�����9��ѤKw5�!঩[�~
+�2�ؓ��|�;��ݼ{��
+<���ċ?�<���̛;=���ԫå�:0��ܻ{�>�J���˛?�>����ۻ?�����ۿ�?�������`�H`��`�
+.�`�>a�NHa�^�a�n�a�F5��	4xaB�6t�bD�)V�xcF�9v��dH�#I�4yeJ�+YR�;
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/doc/design.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/design.html,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/design.html	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,273 @@
+<html>
+<head>
+<title>ACS Messaging & BBoard Design Document</title>
+</head>
+
+<body bgcolor=white>
+
+<h2>ACS Message & BBoard Design Document</h2>
+by Anukul Kapoor
+
+<hr>
+
+<h3>I.  Essentials</h3>
+
+<ul>
+<li>User directory: <a href="/bboard/">/bboard/</a>
+<li><a href="requirements">Requirements document</a>
+<li>Data model: <a href="/doc/sql/display-sql?url=bboard-create.sql&package_key=bboard">bboard-create.sql</a><br>
+<a href="/doc/sql/display-sql?url=acs-messaging-create.sql&package_key=acs-messaging">acs-messaging-create.sql</a>
+<li><a href="acs-messaging-and-bboard-dm.gif">Data-model diagram</a>
+</ul>
+
+
+<h3>II.  Introduction</h3>
+
+<p><code>bboard</code> is an ACS application package built to provide
+scalable discussion forums to a community of users. As in older
+versions, <code>bboard</code> provides:
+<ul>
+<li>posting, browsing, and reading of messages in discussion forums
+<li>tools for moderators to maintain editorial standards
+<li>categorization and retrieval for knowledge management
+</ul>
+
+The initial 4.0 implementation adds the following new features:
+
+<ul>
+<li>fully templated presentation layer for easy customization
+<li>improved access control on bboard operations to support a wide
+variety of publisher policies 
+<li>support for multiple distinct configurations of the bboard package
+(e.g. different forums and options at http://foo.com/bboard/ and
+http://foo.com/pittsburgh/bboard/)
+</ul>
+</p>
+
+<p>The ACS 4.0 version of <code>bboard</code> is a re-engineering of
+the data model and presentation layer without certain capabilities
+present in the ACS 3.4 bboard.  In future releases we intend to
+achieve the same level of maturity as the older <code>bboard</code>
+while building on the flexibility of the new design.</p>
+
+In particular this implementation (9/2000) does not include the
+following features found in prior versions:
+
+<ul>
+<li> support for expiring messages
+<li> facilities for spamming dynamic classes of bboard users
+<li> bboard messages with rich media attachments
+<li> email alert functionality
+<li> full text messages searching
+</ul>
+
+<p><code>bboard</code> is <em>not</em> intended to be the ultimate
+customizable web based discussion system.  It is intended to be a
+practical and useful system that supports forums much like the
+photo.net Q&A forum.  Publishers with special needs are encouraged to
+implement their solution as a module, much like bboard, built atop the
+framework <code>acs-messaging</code> provides.
+
+<p><code>acs-messaging</code> is a general purpose component that
+provides threaded messaging services to higher level applications such
+as <code>bboard</code>.  The motivation is to provide a base level
+data model and reusable presentation code that enables the rapid
+customization of messaging applications.  acs-messaging is intended to
+simplify modules like <code>general comments</code> and
+<code>webmail</code>, as well as specialized messaging applications
+such as <a href="http://www.scorecard.org/">scorecard</a>'s geospatial
+bboard.  Such a framework keeps custom organizational metadata,
+pageflow and navigation, and publishing and moderation policy separate
+from the basic tools needed for discussion.</p>
+
+<h3>III.  Historical Considerations</h3> 
+
+Over the course of ACS development, <code>bboard</code> has grown to
+encompass a wide variety of functionality.  Much of this functionality
+was developed first for <code>bboard</code> and only later adapted
+into more general mechanisms (e.g. alerts, security, group scoping,
+etc.,).  However <code>bboard</code> wasn't refactored to take
+advantage of the more general facilities, and its complexity
+challenged those in need of custom features.  Furthermore there was a
+lot of ad hoc mechanism in both the data model and page flow to
+support different presentation styles, navigation schemes, and access
+control models.  Although this <code>bboard</code> proved to be
+useful, scalable, and reliable, the ability to maintain and extend
+this code suffered.</p>
+
+The ACS 4.0 release of bboard mimics the basic functionality of older
+<code>bboard</code> versions but built atop new ACS 4.0 general
+mechanisms (objects, persmissions, templating, acs-messaging,
+etc.,). </p>.
+
+<h3>IV.  Competitive Analysis</h3>
+
+An analysis of the bboard feature space should be added here.
+
+<ul>
+<li> USENET a la gnus
+<li> slashdot
+<li> Userland
+<li> ????
+</ul>
+
+<h3>V.  Design Tradeoffs</h3> 
+
+<p>How does one reconcile all the possible discussion forums mentioned
+above into a single module?  One does not!  <code>bboard</code> is
+precisely one way to implement a discussion forum and should not be
+all things.  In time, there should be a toolkit of components (user
+interface, data model, and procedural) for developers to assemble
+their custom.</p>
+
+<p>Although many of the entities in the data model are implemented as
+subtyples of ACS object, we avoid using information from the ACS
+object table for anything but auditing purposes.  For example, we
+could store a message's author in the ACS object creation_user field,
+however to keep query performance in line we rather use the author field
+in acs_messages.</p>
+
+<h3>VI.  API</h3> 
+
+<p>As of the initial ACS 4.0 release, <code>acs-messaging</code> and
+<code>bboard</code> do not provide well defined programming
+interfaces.  </p>
+
+<p>Although convenience functions will be provided for basic
+transactions on the <code>acs-messaging</code> and <code>bboard</code>
+entities, it remains to be seen what sort of abstraction layer is most
+appropriate.</p>
+
+<h3>VII.  Data Model Discussion</h3>
+
+<p><code>acs-messaging</code> defines the view
+<code>acs_messages_all</code> for the storage and access of threaded
+text messages and assorted information relevant to their display,
+access, and creation.  Under the covers <code>acs-messaging</code> use the
+content repository for underlying storage.</p>
+
+<p><code>bboard</code> uses <code>acs-messaging</code> messages, and
+organizes them into forums and categories.  For the purposed of the
+ACS permissions system, forums contain messages, and so any
+permissions on a forum will default to being inherited for individual
+messages.</p>
+
+<p>A forum may be designated as moderated, in which case explicit
+approvals or denials are stored in the
+<code>bboard_message_moderation</code>.  Messages without entries in
+the moderation table are considered unseen, and will be displayed or
+hidden in moderated forums based on policy.</p>
+
+<p>Each forum may have some number of categories, tags denoting further
+specialization within a forum.  Messages of a forum may be tagged as being
+in any of the categories pertaining to that forum.</p>
+
+<h4>Permissions</h4>
+
+Permissions in ACS 4.0 involve 3 interrelated hierarchies: users &
+groups, objects, and privileges.  The user and group hiearchy is
+generally explained elsewhere.
+
+The short explanation:<p>
+
+The long explanation:<br>
+
+BBoard defines the following permissions:
+<ul>
+
+<li> nested under the create permission:
+<li>   bboard_create_forum
+<li>   bboard_create_category
+<li>   bboard_create_message
+<li>
+<li> nested under the write permission:
+<li>   bboard_write_forum
+<li>   bboard_write_category
+<li>   bboard_write_message
+<li>
+<li> nested under the read permission:
+<li>   bboard_read_forum
+<li>   bboard_read_category
+<li>   bboard_read_message
+<li>
+<li> nested under the delete permission:
+<li>   bboard_delete_forum
+<li>   bboard_delete_category
+<li>   bboard_delete_message
+<li>
+<li> nested under the moderate permission:
+<li>   bboard_moderate_forum
+</ul>
+
+<h3>VIII.  User Interface</h3>
+
+<h3>IX.  Configuration/Parameters</h3>
+
+<h3>X.  Acceptance Tests</h3>
+
+<h3>XI.  Future Improvements/Areas of Likely Change</h3>
+
+<p>Much of the functionality of the ACS content repository will
+eventually provide tangible benefits to <code>bboard</code> and any
+<code>acs-messaging</code> application.  Foremost among these features
+will be full text searching and rich media attachments.</p>
+
+<p>When ACS provides a general mechanism for an installation to send and
+receive email, <code>bboard</code> can provide email alerts and
+email based reply and post.</p>
+
+<h3>XII.  Authors</h3>
+
+<a href="mailto:akk@arsdigita.com">Anukul Kapoor</a>
+
+<h3>XIII.  Revision History</h3>
+
+<table cellpadding=2 cellspacing=2 width=90% bgcolor=#efefef>
+<tr bgcolor=#e0e0e0>
+    <th width=10%>Document Revision #</th>
+    <th width=50%>Action Taken, Notes</th>
+    <th>When?</th>
+    <th>By Whom?</th>
+</tr>
+
+<tr>
+   <td>0.1</td>
+   <td>Creation</td>
+   <td>09/01/2000</td>
+   <td>Anukul Kapoor</td>
+</tr>
+<tr>
+   <td>0.2</td>
+   <td>Revision</td>
+   <td>09/19/2000</td>
+   <td>Anukul Kapoor</td>
+</tr>
+
+
+</table>
+
+<!-- notes for writing
+
+different organizations of discussion messaging (general comments, webmail, different bboard implementations) -> acs messaging with bboard layer above
+
+inconsistent 'new' messages behavior -> read-thread-user-map
+
+inconsistent alert and email behavior -> centralized alerts and email processing
+
+fully templated for flexible presentation
+and simple interface for 
+
+acs-messaging aims to provide:
+ centralized storage, searching of message threads
+ generalized integration with email messaging
+-->
+
+<p>
+
+<hr>
+
+<a href="mailto:akk@arsdigita.com">akk@arsdigita.com</a>
+
+</body>
+</html>
+
Index: openacs-4/packages/sloan-bboard/www/doc/index.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/index.html,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/index.html	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,225 @@
+<html>
+<head><title>BBoard documentation</title></head>
+<body bgcolor=#ffffff>
+<h2>BBoard documentation</h2>
+<hr>
+<h3>Release Notes</h3>
+
+Version 4.0.2b6 of BBoard is Yet Another Attempt to get 4.0.2
+released.  This version requires ACS 4.0.1 but has been tested against
+4.1 as well.  A lot of bugs have been fixed and minor features implemented:
+
+<ul>
+<li> emailing a friend or email alerts should no longer leave persistent garbage around.
+<li> a link is now provided for uncategorized messages.
+<li> cleaner views
+<li> deletion of threads as well as just messages
+<li> email alerts show a link to the message and indicate which forum they came from
+</ul>
+
+For improved functionality you should upgrade to the latest version of
+ACS 4.1 and the latest version of ACS Messaging (as of 2/13/01 4.1.1
+NOT included in ACS 4.1). <p>
+
+For more details on bugfixes and improvements, visit the bboard
+section of the <a
+href="http://www.arsdigita.com/sdm/all-tickets?module_id=8566&package_id=8157&status=newopen">ArsDigita
+SDM</a>.<p>
+
+<strong>Note:</strong> This documentation has not been reviewed and is
+not considered up to standards.  More comprehensive and more refined
+documentation will be available in an upcoming point release.  If you
+have further questions, feel free to ask on the <a
+href="http://www.arsdigita.com/bboard/q-and-a?topic_id=935&topic=ACS%20Applications">applications
+bboard</a>.<p>
+
+
+<h3>Overview</h3>
+
+BBoard implements a system for persistent asynchronous web based
+discussions.  A BBoard instance as configured from ACS-Admin can
+contain some number for discussion forums.  Each forums provides a
+context for users with appropriate access to read and post messages.
+Messages may optionally be tagged in a list categories to facilitate
+sorting and searching.
+
+<h3>Installation</h3>
+
+Using bboard requires an operating ACS 4.0.1 installation.  If you
+haven't upgraded, do so first!  Installing and enabling the bboard
+package should be relatively painless: just go to your server's
+/acs-admin/apm/package-load page and enter
+"http://www.arsdigita.com/acs-repository/download/apm/bboard-4.0.2r1.apm".
+If you're reading this on your own server, you've already done
+this.<p>
+
+Once the package is installed and enabled, a subsite administrator can
+then mount instances on their subsite.  If you're the lone
+&uuml;ber-admin of your site, you can just go to your site's
+/admin/site-nodes/ page and create a new subfolder under the "/"
+directory.  Pick a creative label for your subfolder like "bboard" or
+"dg".  Select "new application" for that subfolder, and choose BBoard
+from the pulldown menu.  It is probably best to label the application
+instance the same as your subfolder; do otherwise if it helps you keep
+your site straight.<p>
+
+At this point you should have a BBoard instance mounted in the
+subfolder directory, let's say you chose "/bboard".  Before delving
+into configuration, let's run over BBoard's permissions model.
+
+<h3>Initial Configuration</h3>
+
+Once mounted, you can surf over to /bboard as an administrator, create
+some forums, and start discussing that crazy U.S. election!
+
+The following parameters are configurable on a package instance basic from the
+appropirate node in /admin/site-nodes/. 
+
+<dl>
+
+<dt><strong><code>ThreadingEnabledP</code></strong>
+
+<dd>This enables or disables threading indentation on a single thread
+basis.  "t" enables threading and "f" (the default) turns it off.
+
+<dt><strong><code>MailFriendEnabledP</code></strong>
+
+<dd>This enables the option for users to mail copies of a bboard
+posting to a friend (or themselves).  Since this functionality can be
+abused, consider disabling the functionality.
+
+<dt><strong><code>UserPostsEditableP</code></strong>
+
+<dd>This grants users privileges to edit their own message.  Note:
+toggling this parameter will not change the ability of user to edit
+existing messages.  This parameter only effects whether users are
+granted rights to edit at the message's posting time.  This must be
+enabled for attachments to work.
+
+<dt><strong><code>AttachmentsEnabledP</code></strong>
+
+<dd>This lets users who have edit capability on a message upload file
+or image attachments.
+
+<dt><strong><code>MaxAttachmentSize</code></strong>
+
+<dd>This specifies the maximum size in bytes to accept for binary
+attachments.  The default is 1 megabyte.
+
+<dt><strong><code>DisplayLastNDays</code></strong>
+
+<dd>This parameter controls how many days worth of recent messages are
+displayed on the forum overview page by default.  0 specifies
+that all messages should be displayed.
+
+</dl>
+
+<h3>Advanced Configuration and Permissions Overview</h3>
+
+The ACS 4.0 permissions system is about hierarchies and in particular
+hiearchical containment.  There are three important hiearchies: the
+user hierarchy (users, groups, and parties), the object hierarchy
+(objects nested in the contexts of others), and the privilege hiearchy
+(privileges can entail other entails).  This complexity of mechanism
+is designed to allow for simplicity of use for programmers and
+administrators.  Unfortunately, interfaces to facilitate this
+simplicity of use are not here yet.  Until then, sophisticated control
+and configuration of BBoard necessitates an understanding of these
+details.<p>
+
+The first hierarchy is straightforward.  There are users and groups
+(or together parties).  Privileges granted to groups inherit to their
+members.<p>
+
+Unless explicitly disabled (see below), privileges granted to parties
+are inherited down an object hierarchy.  The nature of the BBoard
+hierarchy is as follows: subsites contain bboard package instances;
+bboard package instances contain forums; forums contain both
+categories and messages.  Privileges granted to parties on the package
+instance are inherited to all the forums nested within and so on.<p>
+
+The third hiearchy is the least clear.  Privileges can be nested into
+other privileges.  This lets us group related privileges like those
+for reading a message and reading a forum together to allow us to
+easily grant "read access" on a hiearchy of objects to a party even
+though there are separate notions of "read a message" and "read a
+forum".  All the bboard privileges are nested in one of the following
+system level "super"-privileges: "read", "write", "create", "delete",
+and "admin".<p>
+
+The full set of self explanatory bboard privileges is listed here:
+<ul>
+ <li> bboard_create_forum
+ <li> bboard_create_category
+ <li> bboard_create_message
+ <li> bboard_write_forum
+ <li> bboard_write_category
+ <li> bboard_write_message
+ <li> bboard_read_forum
+ <li> bboard_read_category
+ <li> bboard_read_message
+ <li> bboard_delete_forum
+ <li> bboard_delete_category
+ <li> bboard_delete_message
+ <li> bboard_moderate_forum
+</ul>
+
+
+Permissions on package instances are controlled through the "set
+permissions" options on the appropriate folder in the admin site map
+(/admin/site-map/).  While in principal, the system should allow you
+to grant permissions on lower level objects like forums or even
+individual messages and categories, right now the UI is limited to
+granting permissions on the application instance.  SQL*Plus users or
+even URL hackers can probably figure out how to do this if they're so
+inclined. <p>
+
+The default set of permissions granted in a bboard system are those
+inherited from the main site:
+
+<ul>
+ <li> Registered Users have bboard_create_message 
+ <li> The Public has bboard_read_category 
+ <li> The Public has bboard_read_forum 
+ <li> The Public has bboard_read_message 
+ <li> The Public has read 
+ <li> [Admin user] admin 
+</ul>
+
+Granting additional privileges to parties is fairly straightforward.
+For moderated forums, creating a moderators group and granting them
+"bboard_moderate_forum" (or "admin" if you're feeling lucky) will let
+you delegate more of the discussion culling.<p>
+
+For significantly different configurations you might need to revoke
+privileges already granted by the defaults.  In this case you must
+configure the package instance not to inherit permissions from the
+main site and then add back any permissions needed.  Granting "read"
+to registered users and bboard_create_message to "Elite d00ds" will
+give you a pseudo-private forum.<p>
+
+Note: To facilitate usability in the common case, BBoard pages present
+the option to post or reply even if the user doesn't have the
+bboard_create_message privilege.  If you remove posting ability from
+registered users, you may wish to alter the templates to appropriately
+display options.<p>
+
+<h3>Miscellaneous Notes</h3>
+
+Text searching requires the maintaince of the content repository
+<code>cr_rev_content_index</code> index; either by hand or by
+context.</p>
+
+As usual, please file bugs and feature requests in the <a
+href="http://www.arsdigita.com/sdm/one-module?module_id=3701">bboard
+SDM</a>.
+
+<h3>Engineering Documentss</h3>
+<ul>
+<li><a href="requirements.html">Requirements</a>
+<li><a href="design.html">Design</a> <font color="red">[out of date]</font>
+</ul>
+
+<hr>
+<address>akk@arsdigita.com</address></body>
+</html>
Index: openacs-4/packages/sloan-bboard/www/doc/requirements.html
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/requirements.html,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/requirements.html	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,359 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+  <head>
+    <title>Bulletin Board Requirements</title>
+  </head>
+
+  <body bgcolor="#ffffff">
+    <h1>Bulletin Board Requirements</h1>
+    by <a href="mailto:akk@arsdigita.com">Anukul Kapoor</a>, <a href="mailto:psu@arsdigita.com">Pete Su</a>, and <a href="mailto:mthomas@arsdigita.com">Mark Thomas</a>
+    <hr>
+
+    <h3>I. Introduction</h3>
+
+    <p>This document outlines necessary functionality and behavior of
+      the new ACS 4.0 Bulletin Board system (herein referred to as bboard).
+
+    <p>Our intent (as of 8/2000) is to start with a simple
+      implementation that can accomodate future advanced functionality.
+      As a result, these requirements may not prescribe functionality
+      present in the ACS 3.4 bboard system.  We are using the
+      uslaw-bboard module as inspiration for a lightweight
+      implementation.
+
+    <p>Futhermore, this document is conservative in attempting to
+      describe the ultimate framework for modular web based messaging.
+      We hope such an architecture may well be born out of iterative
+      process when designing this system.  However, the scope is being
+      primarily limited to functional requirements.
+
+    <p>The future requirements (section VII) should inform the design
+      process if not initially implemented.
+      
+    <h3>II. Vision Statement</h3>
+
+    <p>An electronic bulletin board system is one of the simplest and
+      most effective forms of collaboration between people separated in
+      space and time.  Bboards provide a centralized and shared venue
+      for discussion that save communication costs over ad-hoc
+      mechanisms (like arbitrary email lists).  Since messages are
+      organized by topic as well as temporally, bboard can provide
+      lightweight interfaces for rapidly navigating to interesting
+      messages.  This low barrier to participation encourages
+      spontaneous collaboration between disperse parties in the
+      community.
+      
+    <p>The bboard system also serves as a useful archive and ad-hoc
+      knowledge management tool by virtue of its persistence, light
+      weight organizational structure, and flexible browse and search
+      facilities.  This sort of knowledge base can be easily leveraged
+      to provide long term pedagogical value as well as aid in future
+      problem solving.
+      
+    <p>When integrated with an email system, bboards radically improve
+      email based collaboration.  Email notifications can encourage
+      continuous awareness of community issues.  Email based reply
+      functionality further lowers the barrier to participation,
+      encouraging more Interaction around the Transaction<sup>TM</sup>.
+      
+    <h3>III. System/Application Overview</h3>
+
+    <p>The bboard system allows users to browse, read, and
+      post messages organized into forums.  Messages consist of short
+      text messages with optional attachments such as image files or
+      html documents.  Messages are organized into threads when users
+      reply to each other, maintaining the temporal flow of a particular
+      discussion.
+      
+    <p>Forums are contexts for discussion relating to a particular
+      domain of interest.  Examples include the photo.net Q&A forum, the
+      ArsDigita Web/DB forum, and the away.com discussion forum.
+      Messages within a particular forum can optionally be tagged as
+      being in certain categories to assist searching and navigation.
+      Forums are always created in the context of a subsite.
+
+    <h3>IV. Use-cases and User Scenarios</h3>
+    
+    <p><b>Administrator</b>: Phillis Goodsport is a world famous
+      lithographer who wants to share her knowledge about lithography
+      and encourage interaction between a community of lithographers on
+      her new site litho.net.  Although she likes the idea of a broad
+      forum for general lithography discussion, she wants browsing to be
+      tractable when traffic increases.  If quality goes down, she'd
+      like to dedicate one of her minions to moderating traffic to
+      maintain her high standards.
+      
+    <p><b>Casual browser and poster</b>: Joe Schmoe goes to photo.net
+      for the first time and wants to ask what zoom lens to buy.  He
+      needs to find the appropriate category/topic to post his message.
+      
+    <p><b>Compulsive reader and expert poster</b>: Jane Developer is a
+      web development guru and wants to keep up with as much of the
+      traffic on the web/db forum as possible.  She wants to become
+      aware of posts that might become relevant to her in the future
+      as well as help out folks who have problems she knows how to
+      solve.  Since Jane is on lots of developer mailing lists, her
+      preferred form of interaction is via email.
+
+    <p><b>Moderator</b>: Dave Balderdash is a chatter.net moderator and
+      wants to delete redundant or useless posts.  He's short
+      on time, so he wants a quick interface for rejecting and approving
+      posts.
+      
+   <p><b>Targeted researcher</b>: Ted Stetson is an ACS developer who
+      remembers someone mentioning something about his Oracle problem on
+      a bboard.  He wants to find records of similar problems and any
+      related solutions.
+
+    <h3>V. Related Links</h3>
+
+    <ul>
+      <li>Design Document (not available)
+      <li>Test Plan (not available)
+      <li><a href="http://www.arsdigita.com/general-comments/view-one?comment_id=28646&item=BBoard%20module">notes on USLaw-BBoard implementation</a>
+      <li><a href="/doc/acs-kernel/subsites/requirements">Subcommunities</a>
+      <li><a href="http://www.arsdigita.com/bboard/q-and-a-fetch-msg?msg_id=0003ye">Karl's thoughts on bboard redesign</a>
+      <li><a href="http://www.arsdigita.com/bboard/q-and-a-fetch-msg?msg_id=0007ew">Adam Farkas's web/db thread on bboard improvements</a>
+    </ul>
+
+
+    <h3>VI.A Requirements: User Interface</h3>
+    <h4>End User Basics</h4>
+
+    <p><strong>10.10.10</strong> The bboard system must provide
+      mechanism for users to effectively choose which messages to read
+      within a forum.  Bboard must provide an overview interface to
+      enable users to find messages of interest or relevant to them.
+      This overview should provide the user with cursory information to
+      facilitate quick scanning and meaningful evaluation of message
+      contents.
+      
+      <p><strong>10.10.15</strong> The full text of bboard messages
+            should be searchable by user queries.
+
+    <p><strong>10.10.20</strong> <font color="red"> [unimplemented] </font>Bboard should consistently provide
+      a mechanism to limit or sort displayed posts by categories, posters,
+      and date range as well as to perform a text search.
+      
+    <p><strong>10.10.30</strong> <font color="red"> [unimplemented] </font>Most users primarily want
+      to browse and read new posts or replies since their last visit.
+      The bboard interface must allow users to ignore messages they've
+      already read.
+
+    <p><strong>10.10.40</strong> <font color="red"> [unimplemented] </font>Users should be able to search within
+      and limit scope to messages they have already read as well as
+      messages they have not read at all.
+
+    <p><strong>10.10.50</strong> Users must be able to easily post new
+      messages to a bboard, or reply to existing messages they have come
+      across.  When replying, users must be presenting with enough
+      context to assist their composition.
+
+    <h4>Email Integration</h4>
+
+    <p><strong>10.20.10</strong> Users can register for email
+      notification of new messages in a particular forums.
+
+    <p><strong>10.20.13</strong> Users can register for email
+      notifications on a particular thread.
+
+    <p><strong>10.20.16</strong> Users can register for email
+      notifications on a particular category.
+
+    <p><strong>10.20.20</strong> <font color="red"> [unimplemented] </font>Notifications can be sent as each
+      message arrives or in an organized digest form over a configurable
+      time period.
+
+    <p><strong>10.20.30</strong> Individual messages will have appropriate RFC 822
+      headers to enable threading in the mail client.
+
+    <p><strong>10.20.40</strong> <font color="red"> [unimplemented]
+      </font>Email from the alert system should be tagged in the
+      header with the site and forum name to enable easy filtering in
+      mail clients.  Well, as easy as the mail clients make it anyway.
+
+    <p><strong>10.20.50</strong> <font color="red"> [unimplemented]
+      </font>If the user requests it, email generated should use MIME
+      encoding to deliver attachements and appropriately encode HTML.
+      Otherwise plain text emails should be augmented with URLs and
+      styling cues in place of rich content.
+
+    <h4>Administrative Requirements</h4>
+
+    <p><strong>10.30.10</strong> The bboard system must support a
+      flexible presentation layer that allows custom layout of bboard
+      content.
+
+    <p><strong>10.30.15</strong> Publishers should have the option of
+        displaying discussions in a flat linear fashion or in an indented
+	threaded view.
+
+    <p><strong>10.30.20</strong> Parties with administrative
+      privileges on a particular subsite can create, delete, and edit
+      forums scoped to that subsite.
+
+    <p><strong>10.30.30</strong> Forums can be designated moderated in
+      which case parties with sufficient privileges must approve
+      messages before they are displayed generally.
+
+    <h4>Access Control Requirements</h4>
+
+    Objects must be structured to allow the flexible configuration and
+    assignment of the following privileges:
+      
+    <p><strong>10.40.10</strong> Reading forums
+
+    <p><strong>10.40.20</strong> Reading messages
+
+    <p><strong>10.40.30</strong> Posting new messages
+
+    <p><strong>10.40.50</strong> Approving and rejecting posted messages
+      (for moderated groups)
+
+    <p><strong>10.40.60</strong> Managing the forum (editing title and
+      description, determining moderation and restriction policies,
+      granting approval privileges to others, banning users)
+
+    <p><strong>10.40.70</strong> Managing categories (editing, deleting,
+      combining categories)
+
+    <h3>VI.B Requirements: Datamodel</h3>
+    
+    <h4>Messages</h4> 
+
+    <p><strong>10.80.10</strong> Messages are the basic units of the
+      bboard module.  The bboard system will provide a repository to
+      store text messages.
+
+    <p><strong>10.80.20</strong> Messages will be tagged as having
+      HTML, plain text, or preformatted text in their body.
+
+    <p><strong>10.80.30</strong> Messages will have a brief plain text
+      subject line.
+      
+    <p><strong>10.80.40</strong> Messages will be related to their
+      creating user.
+
+    <p><strong>10.80.50</strong> Messages may optionally have 
+      binary attachments.
+
+    <p><strong>10.80.60</strong> The bboard system must store relations
+      between messages and their replies to enable threaded views.
+
+    <h4>Forums</h4> 
+
+    <p><strong>10.90.10</strong> Forums are the main administrative
+      units of the bboard system.  Forums are containers to which
+      messages uniquely belong.
+
+    <p><strong>10.90.20</strong> Forums must have a brief text
+      descriptions and optionally a longer description called a charter.
+
+    <h4>Categories</h4>
+
+    <p><strong>10.100.10</strong> There must be a mechanism for
+      intra-forum categorization to facilitate filter, searching, and
+      tractability.
+
+    <h3>VI.C Requirements: API</h3>
+
+    <font color="red">No requirements in this section are met by the
+      current implementation.</font>
+
+    <p>Since bboard is primarily an end user application any exposed
+      APIs will come out of the design rather than nailed down
+      requirements from the start.  Stay tuned.
+
+    <h3>VI.D Possible Future Requirements</h3>
+
+    <p><strong>10.255.10</strong> bboard should provide a framework
+      for extending the generic messaging repository with meta-data
+      and in tandem extending the user interface to take advantage of
+      this meta-data.  This would let developers properly layer
+      functionality such as geo-spatial messaging and slashdot style
+      scoring. This is actually provided via ACS messaging and the ACS
+      Object system.
+      
+    <p><strong>10.255.20</strong> bboard should support replying to
+      and initiating threads from email.  Administrative email list
+      functionality should be developed or integrated.
+
+    <p><strong>10.255.30</strong> Bboard should let users register
+      interests (categories, certain users, keywords) for the purpose of
+      filtering and sorting message displays.
+
+    <p><strong>10.255.40</strong> Users should have the option of
+      enabling spell checking on their posts. A framework for filtering
+      (removing bad words, promoting text URLs to html links, auto
+      detecting HTML vs. plain text, etc.,) should exist.
+
+    <p><strong>10.255.50</strong> Allow users to configure how big the
+      textareas editing widgets they get are.
+
+    <p><strong>10.255.60</strong> Moderators should be given the
+      <em>option</em> of making notes on a given discussion that appear
+      prominently in the discussion display.
+
+    <p><strong>10.255.70</strong> Moderators should be able to set
+      posts to expire at a configurable time in the future.
+
+    <p><strong>10.255.80</strong> Mega bonus points: an nntp gateway to
+      bboards for access from standard news clients.
+
+    <p><strong>10.255.90</strong> The bboard system should be able to
+      take advantage of a caching system that stores the results of
+      database queries for optimal scalability.
+
+    <p><strong>10.255.100</strong> Publishers should have the option
+      of allowing users to edit various parts of messages after they are
+      posted (e.g. the text body, the subject, the text presentaiton
+      style etc.,)
+
+    <p><strong>10.255.110</strong> A user interface should allow
+    administrators to easily categorize or recategorize existing
+    messages.
+
+    <p><strong>10.255.120</strong> Publishers should be able to
+    classify users based on their forum contributions and
+    appropriately target them for email, promotions, etc.,
+      
+    <p><strong>10.255.130</strong> Explicit permissions for posting
+    new messages vs. posting replies.
+
+    <p><strong>10.255.140</strong> Explicit permissions for posting
+    attachments.
+
+    <h4>Performance requirements</h4>
+
+    <h3>VII. Revision History</h3>
+    
+<table cellpadding=2 cellspacing=2 width=90% bgcolor=#efefef>
+<tr bgcolor=#e0e0e0>
+    <th width=10%>Document Revision #</th>
+    <th width=50%>Action Taken, Notes</th>
+    <th>When?</th>
+    <th>By Whom?</th>
+</tr>
+
+<tr>
+   <td>0.1</td>
+   <td>Creation</td>
+   <td>08/23/2000</td>
+   <td>Anukul Kapoor</td>
+</tr>
+
+<tr>
+   <td>0.2</td>
+   <td>Revision: More standard style, more detailed requirements.</td>
+   <td>08/24/2000</td>
+   <td>Anukul Kapoor</td>
+</tr>
+
+
+</table>
+
+    <hr>
+    <address><a href="mailto:kapoor@maya.com"></a></address>
+Last modified: $Id: requirements.html,v 1.1 2002/02/15 21:27:07 ben Exp $
+  </body>
+</html>
Index: openacs-4/packages/sloan-bboard/www/doc/xml/configuration.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/xml/configuration.xml,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/xml/configuration.xml	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,116 @@
+<sect1 id="configuration" xreflabel="Advanced Configuration">
+<title>Advanced Configuration</title>
+
+<para>
+The ACS 4.0 permissions system is about hierarchies and in particular
+hiearchical containment. There are three important hiearchies: 
+</para>
+
+<orderedlist>
+<listitem><para>
+the user hierarchy (users, groups, and parties)
+</para></listitem>
+
+<listitem><para>
+the object hierarchy (objects nested in the contexts of others)
+</para></listitem>
+
+<listitem><para>
+the privilege hiearchy (privileges can entail other entails). 
+</para></listitem>
+</orderedlist>
+
+<para>
+This complexity of mechanism is designed to allow for
+simplicity of use for programmers and administrators. Unfortunately,
+interfaces to facilitate this simplicity of use are not here yet. Until then,
+sophisticated control and configuration of BBoard necessitates an
+understanding of these details.
+</para>
+
+<para>The first hierarchy is straightforward. There are users and groups (or
+together parties). Privileges granted to groups inherit to their members.</para>
+
+<para>Unless explicitly disabled (see below), privileges granted to parties are
+inherited down an object hierarchy. The nature of the BBoard hierarchy is as
+follows: subsites contain bboard package instances; bboard package instances
+contain forums; forums contain both categories and messages. Privileges
+granted to parties on the package instance are inherited to all the forums
+nested within and so on.</para>
+
+<para>The third hiearchy is the least clear. Privileges can be nested into other
+privileges. This lets us group related privileges like those for reading a
+message and reading a forum together to allow us to easily grant &quot;read
+access&quot; on a hiearchy of objects to a party even though there are
+separate notions of &quot;read a message&quot; and &quot;read a forum&quot;.
+All the bboard privileges are nested in one of the following system level
+&quot;super&quot;-privileges: &quot;read&quot;, &quot;write&quot;,
+&quot;create&quot;, &quot;delete&quot;, and &quot;admin&quot;.</para>
+
+<para>The full set of self explanatory bboard privileges is listed here:</para>
+
+<itemizedlist>
+<listitem><para>bboard_create_forum</para></listitem>
+<listitem><para>bboard_create_category</para></listitem>
+<listitem><para>bboard_create_message</para></listitem>
+<listitem><para>bboard_write_forum</para></listitem>
+<listitem><para>bboard_write_category</para></listitem>
+<listitem><para>bboard_write_message</para></listitem>
+<listitem><para>bboard_read_forum</para></listitem>
+<listitem><para>bboard_read_category</para></listitem>
+<listitem><para>bboard_read_message</para></listitem>
+<listitem><para>bboard_delete_forum</para></listitem>
+<listitem><para>bboard_delete_category</para></listitem>
+<listitem><para>bboard_delete_message</para></listitem>
+<listitem><para>bboard_moderate_forum</para></listitem>
+</itemizedlist>
+
+
+<para>
+Permissions on package instances are controlled through the &quot;set
+permissions&quot; options on the appropriate folder in the admin site map
+(/admin/site-map/). While in principal, the system should allow you to grant
+permissions on lower level objects like forums or even individual messages
+and categories, right now the UI is limited to granting permissions on the
+application instance. SQL*Plus users or even URL hackers can probably figure
+out how to do this if they&#39;re so inclined. 
+</para>
+
+<para>The default set of permissions granted in a bboard system are those
+inherited from the main site:</para>
+
+<itemizedlist>
+<listitem><para>Registered Users have bboard_create_message</para></listitem>
+
+<listitem><para>The Public has bboard_read_category</para></listitem>
+
+<listitem><para>The Public has bboard_read_forum</para></listitem>
+
+<listitem><para>The Public has bboard_read_message</para></listitem>
+
+<listitem><para>The Public has read</para></listitem>
+
+<listitem><para>[Admin user] admin</para></listitem>
+</itemizedlist>
+
+<para>
+Granting additional privileges to parties is fairly straightforward. For
+moderated forums, creating a moderators group and granting them
+&quot;bboard_moderate_forum&quot; (or &quot;admin&quot; if you&#39;re feeling
+lucky) will let you delegate more of the discussion culling.
+</para>
+
+<para>For significantly different configurations you might need to revoke
+privileges already granted by the defaults. In this case you must configure
+the package instance not to inherit permissions from the main site and then
+add back any permissions needed. Granting &quot;read&quot; to registered
+users and bboard_create_message to &quot;Elite d00ds&quot; will give you a
+pseudo-private forum.</para>
+
+<para>Note: To facilitate usability in the common case, BBoard pages present the
+option to post or reply even if the user doesn&#39;t have the
+bboard_create_message privilege. If you remove posting ability from
+registered users, you may wish to alter the templates to appropriately
+display options.</para>
+
+</sect1>
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/doc/xml/design.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/xml/design.xml,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/xml/design.xml	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,352 @@
+<sect1 id="design" xreflabel="Bboard Design Document">
+<title>ACS Messaging &amp; BBoard Design Document</title>
+
+
+<sect2 id="design-essentials">
+<title>Essentials</title>
+
+
+<itemizedlist>
+<listitem><para>User directory: <ulink url="/bboard/">/bboard/</ulink></para></listitem>
+
+<listitem><para><xref linkend="requirements"/></para></listitem>
+
+<listitem><para>Data model: <ulink url="/doc/sql/display-sql?url=bboard-create.sql&amp;package_key=bboard">bboard-create.sql</ulink>
+
+<ulink url="/doc/sql/display-sql?url=acs-messaging-create.sql&amp;package_key=acs-messaging">
+acs-messaging-create.sql</ulink></para></listitem>
+
+<listitem><para><ulink url="acs-messaging-and-bboard-dm.gif">Data-model diagram</ulink></para></listitem>
+</itemizedlist>
+
+</sect2>
+
+<sect2 id="design-intro">
+<title>Introduction</title>
+
+
+<para><computeroutput>bboard</computeroutput> is an ACS application package built to provide
+scalable discussion forums to a community of users. As in older versions,
+<computeroutput>bboard</computeroutput> provides:</para>
+
+<itemizedlist>
+<listitem><para>posting, browsing, and reading of messages in discussion forums</para></listitem>
+
+<listitem><para>tools for moderators to maintain editorial standards</para></listitem>
+
+<listitem><para>categorization and retrieval for knowledge management</para></listitem>
+</itemizedlist>
+
+<para>
+The initial 4.0 implementation adds the following new features: 
+</para>
+
+<itemizedlist>
+<listitem><para>fully templated presentation layer for easy customization</para></listitem>
+
+<listitem><para>improved access control on bboard operations to support a wide variety of
+publisher policies</para></listitem>
+
+<listitem><para>support for multiple distinct configurations of the bboard package (e.g.
+different forums and options at http://foo.com/bboard/ and
+http://foo.com/pittsburgh/bboard/)</para></listitem>
+</itemizedlist>
+
+
+
+ 
+
+<para>The ACS 4.0 version of <computeroutput>bboard</computeroutput> is a re-engineering of the data
+model and presentation layer without certain capabilities present in the ACS
+3.4 bboard. In future releases we intend to achieve the same level of
+maturity as the older <computeroutput>bboard</computeroutput> while building on the flexibility
+of the new design.</para>
+
+<para>
+In particular this implementation (9/2000) does not include the following
+features found in prior versions: 
+</para>
+
+<itemizedlist>
+<listitem><para>support for expiring messages</para></listitem>
+
+<listitem><para>facilities for spamming dynamic classes of bboard users</para></listitem>
+
+<listitem><para>bboard messages with rich media attachments</para></listitem>
+
+<listitem><para>email alert functionality</para></listitem>
+
+<listitem><para>full text messages searching</para></listitem>
+</itemizedlist>
+
+<para><computeroutput>bboard</computeroutput> is <emphasis>not</emphasis> intended to be the ultimate
+customizable web based discussion system. It is intended to be a practical
+and useful system that supports forums much like the photo.net Q&amp;A forum.
+Publishers with special needs are encouraged to implement their solution as a
+module, much like bboard, built atop the framework <computeroutput>acs-messaging</computeroutput>
+provides.</para>
+
+<para><computeroutput>acs-messaging</computeroutput> is a general purpose component that provides
+threaded messaging services to higher level applications such as
+<computeroutput>bboard</computeroutput>. The motivation is to provide a base level data model and
+reusable presentation code that enables the rapid customization of messaging
+applications. acs-messaging is intended to simplify modules like
+<computeroutput>general comments</computeroutput> and <computeroutput>webmail</computeroutput>, as well as
+specialized messaging applications such as <ulink url="http://www.scorecard.org/">scorecard</ulink>&#39;s geospatial bboard. Such
+a framework keeps custom organizational metadata, pageflow and navigation,
+and publishing and moderation policy separate from the basic tools needed for
+discussion.</para>
+
+</sect2>
+
+<sect2 id="design-history">
+<title>Historical Considerations</title>
+
+<para>
+Over the course of ACS development, <computeroutput>bboard</computeroutput> has grown to
+encompass a wide variety of functionality. Much of this functionality was
+developed first for <computeroutput>bboard</computeroutput> and only later adapted into more
+general mechanisms (e.g. alerts, security, group scoping, etc.,). However
+<computeroutput>bboard</computeroutput> wasn&#39;t refactored to take advantage of the more
+general facilities, and its complexity challenged those in need of custom
+features. Furthermore there was a lot of ad hoc mechanism in both the data
+model and page flow to support different presentation styles, navigation
+schemes, and access control models. Although this <computeroutput>bboard</computeroutput> proved
+to be useful, scalable, and reliable, the ability to maintain and extend this
+code suffered.
+</para>
+
+<para>
+The ACS 4.0 release of bboard mimics the basic functionality of older
+<computeroutput>bboard</computeroutput> versions but built atop new ACS 4.0 general mechanisms
+(objects, persmissions, templating, acs-messaging, etc.,). 
+</para>
+
+</sect2>
+
+<sect2 id="design-competitors">
+<title>Competitive Analysis</title>
+
+<para>
+An analysis of the bboard feature space should be added here. 
+</para>
+
+<itemizedlist>
+<listitem><para>USENET a la gnus</para></listitem>
+
+<listitem><para>slashdot</para></listitem>
+
+<listitem><para>Userland</para></listitem>
+
+<listitem><para>????</para></listitem>
+</itemizedlist>
+
+</sect2>
+
+<sect2 id="design-tradeoffs">
+<title>Design Tradeoffs</title>
+
+
+<para>How does one reconcile all the possible discussion forums mentioned above
+into a single module? One does not! <computeroutput>bboard</computeroutput> is precisely one way
+to implement a discussion forum and should not be all things. In time, there
+should be a toolkit of components (user interface, data model, and
+procedural) for developers to assemble their custom.</para>
+
+<para>Although many of the entities in the data model are implemented as
+subtyples of ACS object, we avoid using information from the ACS object table
+for anything but auditing purposes. For example, we could store a
+message&#39;s author in the ACS object creation_user field, however to keep
+query performance in line we rather use the author field in acs_messages.</para>
+
+</sect2>
+
+<sect2 id="design-api">
+<title>API</title>
+
+
+<para>As of the initial ACS 4.0 release, <computeroutput>acs-messaging</computeroutput> and
+<computeroutput>bboard</computeroutput> do not provide well defined programming interfaces.</para>
+
+<para>Although convenience functions will be provided for basic transactions on
+the <computeroutput>acs-messaging</computeroutput> and <computeroutput>bboard</computeroutput> entities, it remains
+to be seen what sort of abstraction layer is most appropriate.</para>
+
+</sect2>
+
+<sect2 id="design-data-model">
+<title>Data Model Discussion</title>
+
+
+<para><computeroutput>acs-messaging</computeroutput> defines the view <computeroutput>acs_messages_all</computeroutput>
+for the storage and access of threaded text messages and assorted information
+relevant to their display, access, and creation. Under the covers
+<computeroutput>acs-messaging</computeroutput> use the content repository for underlying
+storage.</para>
+
+<para><computeroutput>bboard</computeroutput> uses <computeroutput>acs-messaging</computeroutput> messages, and
+organizes them into forums and categories. For the purposed of the ACS
+permissions system, forums contain messages, and so any permissions on a
+forum will default to being inherited for individual messages.</para>
+
+<para>A forum may be designated as moderated, in which case explicit approvals
+or denials are stored in the <computeroutput>bboard_message_moderation</computeroutput>. Messages
+without entries in the moderation table are considered unseen, and will be
+displayed or hidden in moderated forums based on policy.</para>
+
+<para>Each forum may have some number of categories, tags denoting further
+specialization within a forum. Messages of a forum may be tagged as being in
+any of the categories pertaining to that forum.</para>
+
+<para><emphasis role="strong">Permissions</emphasis></para>
+
+<para>
+Permissions in ACS 4.0 involve 3 interrelated hierarchies: users &amp;
+groups, objects, and privileges. The user and group hiearchy is generally
+explained elsewhere. The short explanation:
+</para>
+
+<para>The long explanation: BBoard defines the following permissions:</para>
+
+<itemizedlist>
+<listitem><para>nested under the create permission:</para></listitem>
+
+<listitem><para>bboard_create_forum</para></listitem>
+
+<listitem><para>bboard_create_category</para></listitem>
+
+<listitem><para>bboard_create_message</para></listitem>
+
+<listitem><para>nested under the write permission:</para></listitem>
+
+<listitem><para>bboard_write_forum</para></listitem>
+
+<listitem><para>bboard_write_category</para></listitem>
+
+<listitem><para>bboard_write_message</para></listitem>
+
+<listitem><para>nested under the read permission:</para></listitem>
+
+<listitem><para>bboard_read_forum</para></listitem>
+
+<listitem><para>bboard_read_category</para></listitem>
+
+<listitem><para>bboard_read_message</para></listitem>
+
+<listitem><para>nested under the delete permission:</para></listitem>
+
+<listitem><para>bboard_delete_forum</para></listitem>
+
+<listitem><para>bboard_delete_category</para></listitem>
+
+<listitem><para>bboard_delete_message</para></listitem>
+
+<listitem><para>nested under the moderate permission:</para></listitem>
+
+<listitem><para>bboard_moderate_forum</para></listitem>
+</itemizedlist>
+
+</sect2>
+
+<sect2 id="design-ui">
+<title>User Interface</title>
+
+<para>...</para>
+
+</sect2>
+
+<sect2 id="design-config">
+<title>Configuration/Parameters</title>
+
+<para>...</para>
+
+</sect2>
+
+<sect2 id="design-accept-tests">
+<title>Acceptance Tests</title>
+
+<para>...</para>
+
+</sect2>
+
+<sect2 id="design-future">
+<title>Future Improvements/Areas of Likely Change</title>
+
+
+<para>Much of the functionality of the ACS content repository will eventually
+provide tangible benefits to <computeroutput>bboard</computeroutput> and any
+<computeroutput>acs-messaging</computeroutput> application. Foremost among these features will be
+full text searching and rich media attachments.</para>
+
+<para>When ACS provides a general mechanism for an installation to send and
+receive email, <computeroutput>bboard</computeroutput> can provide email alerts and email based
+reply and post.</para>
+
+</sect2>
+
+<sect2 id="design-authors">
+<title>Authors</title>
+
+<para>
+<ulink url="mailto:akk@arsdigita.com">Anukul Kapoor</ulink> 
+</para>
+
+</sect2>
+
+<sect2 id="design-rev-history">
+<title>Revision History</title>
+
+<informaltable>
+<tgroup cols="4">
+<thead>
+<row>
+<entry>Document Revision #</entry>
+<entry>Action Taken, Notes</entry>
+<entry>When?</entry>
+<entry>By Whom?</entry>
+</row>
+</thead>
+
+<tbody>
+
+<row>
+<entry>0.2</entry>
+<entry>Revision</entry>
+<entry>09/19/2000</entry>
+<entry>Anukul Kapoor</entry>
+</row>
+
+
+<row>
+<entry>0.1</entry>
+<entry>Creation</entry>
+<entry>09/01/2000</entry>
+<entry>Anukul Kapoor</entry>
+</row>
+
+
+</tbody></tgroup></informaltable>
+
+<!-- notes for writing
+
+different organizations of discussion messaging (general comments, webmail, different bboard implementations) -> acs messaging with bboard layer above
+
+inconsistent 'new' messages behavior -> read-thread-user-map
+
+inconsistent alert and email behavior -> centralized alerts and email processing
+
+fully templated for flexible presentation
+and simple interface for 
+
+acs-messaging aims to provide:
+ centralized storage, searching of message threads
+ generalized integration with email messaging
+-->
+
+
+
+
+</sect2>
+
+</sect1>
+
Index: openacs-4/packages/sloan-bboard/www/doc/xml/index.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/xml/index.xml,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/xml/index.xml	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,66 @@
+<?xml version='1.0' ?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" 
+	       "http://developer.arsdigita.com/docbook/dtd/4.1.2/docbookx.dtd" [
+
+<!-- For Everyone -->
+<!ENTITY introduction SYSTEM "intro.xml">
+<!ENTITY support SYSTEM "support.xml">
+<!ENTITY notes SYSTEM "notes.xml"> 
+
+<!-- For Admins -->
+<!ENTITY installation SYSTEM "installation.xml"> 
+<!ENTITY configuration SYSTEM "configuration.xml">
+
+<!-- For Developers -->
+<!ENTITY design SYSTEM "design.xml">
+<!ENTITY requirements SYSTEM "requirements.xml">
+
+
+]>
+
+<book>
+<title>Bboard Documentation</title>
+
+
+        <chapter id="for-everyone">
+        <title>For Everyone</title>
+
+            <sect1>
+            <title>Overview</title>
+                <para>Brief introduction, support possibilities and release notes</para>
+            </sect1>
+
+            &introduction;
+            &support;
+<!--            &notes;
+-->
+        </chapter>
+
+   
+        <chapter id="for-admins" xreflabel="For Admins">
+        <title>For Admins</title>
+
+            <sect1>
+            <title>Overview</title>
+            <para>Installation, maintenance</para>
+            </sect1>
+
+            &installation;
+            &configuration;
+
+        </chapter>
+
+       <chapter id="for-developers" xreflabel="For Developers">
+       <title>For Developers</title>
+
+            <sect1>
+            <title>Overview</title>
+            <para>Requirements, design</para>
+            </sect1>
+
+            &requirements;
+            &design;
+
+        </chapter>
+
+</book>
Index: openacs-4/packages/sloan-bboard/www/doc/xml/installation.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/xml/installation.xml,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/xml/installation.xml	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,185 @@
+<sect1 id="installation" xreflabel="Installation and Configuration of Bboard">
+<title>Installation and Configuration of Bboard</title>
+
+<sect2 id="installation-installation">
+<title>Installation</title>
+
+<para>
+Using bboard requires an operating ACS 4.0.1 installation. If you haven&#39;t
+upgraded, do so first.
+</para>
+
+<para>
+Installing and enabling the bboard package should be
+relatively painless, just: 
+</para>
+
+<orderedlist>
+<listitem><para>
+go to your server&#39;s 
+<ulink url="/acs-admin/apm/package-load">/acs-admin/apm/package-load</ulink>
+page, enter
+&quot;www.arsdigita.com/acs-repository/download/apm/bboard-4.0.2.apm&quot;
+in the first text box
+</para>
+</listitem>
+
+<listitem>
+<para>
+click the button and follow the instructions
+</para>
+</listitem>
+</orderedlist>
+
+<para>
+If you&#39;re reading this on your own server, you&#39;ve 
+probably already done this.
+</para>
+
+<para>
+Once the package is installed and enabled, a subsite administrator can
+<emphasis>mount</emphasis> instances on their subsite. If you&#39;re the 
+lone &amp;uuml;ber-admin
+of your site, you can just go to your site&#39;s 
+<ulink url="/admin/site-map/">/admin/site-map/</ulink> page and:
+</para>
+
+<orderedlist>
+
+<listitem><para>
+create a new subfolder under the &quot;/&quot; directory
+</para></listitem>
+
+<listitem><para>
+Pick a creative
+label for your subfolder like &quot;bboard&quot; or &quot;dgroup&quot;
+</para></listitem>
+
+<listitem><para>
+Select
+&quot;new application&quot; for that subfolder, and choose BBoard from the
+pulldown menu. 
+</para></listitem>
+</orderedlist>
+
+<para>
+It is probably best to label the application instance the same
+as your subfolder; do otherwise if it helps you keep your site straight.</para>
+
+<para>At this point you should have a BBoard instance mounted in the subfolder
+directory - for the rest of this document I assume that you've choosen &quot;/bboard&quot;. 
+</para>
+
+</sect2>
+
+<sect2 id="installation-config">
+<title>Initial Configuration</title>
+
+<para>
+Before you can start using the Bboard you have to create some forums:
+</para>
+
+<orderedlist>
+<listitem><para>
+log in as an administrator
+</para></listitem>
+
+<listitem><para>
+surf to <computeroutput>/bboard</computeroutput> and click &quot;Create a forum&quot;
+</para>
+</listitem>
+</orderedlist>
+
+<para>
+After you've created one or more forums you can specify the settings for your instance
+of Bboard from the <ulink url="/admin/site-map/">Site Map</ulink> 
+(click <computeroutput>set parameters</computeroutput>). 
+</para>
+
+<para>
+Most of the setting you see require a &quot;t&quot; (for true) or &quot;f&quot; (for false).
+The rest should be self-explanatory.
+</para>
+
+<variablelist>
+<varlistentry>
+<term><emphasis role="strong"><computeroutput>ThreadingEnabledP</computeroutput></emphasis>
+
+</term>
+ 
+<listitem><para>This enables or disables threading indentation on a single thread basis.
+&quot;t&quot; enables threading and &quot;f&quot; (the default) turns it
+off.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><emphasis role="strong"><computeroutput>MailFriendEnabledP</computeroutput></emphasis>
+
+</term>
+ 
+<listitem><para>This enables the option for users to mail copies of a bboard posting to a
+friend (or themselves). Since this functionality can be abused, consider
+disabling the functionality.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><emphasis role="strong"><computeroutput>UserPostsEditableP</computeroutput></emphasis>
+
+</term>
+ 
+<listitem><para>This grants users privileges to edit their own message. Note: toggling
+this parameter will not change the ability of user to edit existing messages.
+This parameter only effects whether users are granted rights to edit at the
+message&#39;s posting time. This must be enabled for attachments to
+work.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><emphasis role="strong"><computeroutput>UserPostsDeletableP</computeroutput></emphasis>
+
+</term>
+ 
+<listitem><para>This grants users privileges to delete their own
+message. Note: This parameter only effects whether users are granted
+rights to edit their message&#39;s with the
+<computeroutput>UserPostsEditableP<computeroutput>.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><emphasis role="strong"><computeroutput>AttachmentsEnabledP</computeroutput></emphasis>
+
+</term>
+ 
+<listitem><para>This lets users who have edit capability on a message upload file or
+image attachments.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+<emphasis role="strong"><computeroutput>MaxAttachmentSize</computeroutput></emphasis>
+</term>
+ 
+<listitem><para>This specifies the maximum size in bytes to accept for binary
+attachments. The default is 1 megabyte.</para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term>
+<emphasis role="strong"><computeroutput>DisplayLastNDays</computeroutput></emphasis>
+</term>
+ 
+<listitem><para>This parameter controls how many days worth of recent messages are
+displayed on the forum overview page by default. 0 specifies that all
+messages should be displayed.</para></listitem>
+</varlistentry>
+</variablelist>
+
+<para>
+If you want to learn how to set more advanced parameters of your Bboard instance,
+read <xref linkend="configuration"/>.
+</para>
+
+</sect2>
+
+</sect1>
+
Index: openacs-4/packages/sloan-bboard/www/doc/xml/intro.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/xml/intro.xml,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/xml/intro.xml	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,21 @@
+<sect1 id="introduction" xreflabel="Bboard Introduction">
+<title>Bboard Introduction</title>
+
+<sect2 id="whatisbboard" xreflabel="What is Bboard?">
+<title>What is Bboard?</title>
+
+<para>
+BBoard is a web based discussion system for the ArsDigita Community
+System.  Once installed and mounted, bboard instances provide
+locations on the site that contain discussion forums
+(e.g. http://developer.arsdigita.com/bboard/).  Users can post and
+read messages within individual forums, which are generally geared
+towards specific topics or audiences.  This basic functionality is
+supplemented with a variety of additional features including image and
+file message attachments, email notification, categorization, and
+moderation facilities.
+</para>
+
+</sect2>
+
+</sect1>
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/doc/xml/notes.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/xml/notes.xml,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/xml/notes.xml	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,42 @@
+<sect1 id="misc" xreflabel="Release Notes and Miscellaneous Stuff">
+<title>Release Notes and Miscellaneous Stuff</title>
+
+<sect2 id="release-notes">
+<title>Release Notes</title>
+
+<para>
+This is the final release of BBoard 4.0.2.  This release requires ACS
+Core 4.0.1, available from the <ulink
+url="http://www.arsdigita.com/acs-repository/">ACS Repository</ulink>.
+</para>
+
+<para>This version offers a working drop script, numerous bugfixes, and some
+notable improvements such as:</para>
+
+<itemizedlist>
+<listitem><para>support for binary attachments</para></listitem>
+
+<listitem><para>letting users email postings to others</para></listitem>
+
+<listitem><para>more informative displays</para></listitem>
+
+<listitem><para>performance improvements</para></listitem>
+<listitem><para></para></listitem>
+<listitem><para></para></listitem>
+<listitem><para></para></listitem>
+</itemizedlist>
+
+
+</sect2>
+
+<sect2 id="misc-notes">
+<title>Miscellaneous Notes</title>
+
+<para>
+Text searching requires the maintaince of the content repository
+<computeroutput>cr_rev_content_index</computeroutput> index; either by hand or by context.
+</para>
+
+</sect2>
+
+</sect1>
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/doc/xml/requirements.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/xml/requirements.xml,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/xml/requirements.xml	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,427 @@
+<sect1 id="requirements" xreflabel="Bulletin Board Requirements">
+<title>Bulletin Board Requirements</title>
+
+<authorblurb><para>
+By <ulink url="mailto:akk@arsdigita.com">Anukul Kapoor</ulink>, <ulink url="mailto:psu@arsdigita.com">Pete Su</ulink> and <ulink url="mailto:mthomas@arsdigita.com">Mark Thomas</ulink> 
+</para></authorblurb>
+
+<sect2 id="requirements-intro">
+<title>Introduction</title>
+
+
+<para>This document outlines necessary functionality and behavior of the new ACS
+4.0 Bulletin Board system (herein referred to as bboard).</para>
+
+<para>Our intent (as of 8/2000) is to start with a simple implementation that
+can accomodate future advanced functionality. As a result, these requirements
+may not prescribe functionality present in the ACS 3.4 bboard system. We are
+using the uslaw-bboard module as inspiration for a lightweight
+implementation.</para>
+
+<para>Futhermore, this document is conservative in attempting to describe the
+ultimate framework for modular web based messaging. We hope such an
+architecture may well be born out of iterative process when designing this
+system. However, the scope is being primarily limited to functional
+requirements.</para>
+
+<para>The <link linkend="requirements-future">future requirements</link> should inform the design process if
+not initially implemented.</para>
+
+</sect2>
+
+<sect2 id="requirements-vision">
+<title>Vision Statement</title>
+
+
+<para>An electronic bulletin board system is one of the simplest and most
+effective forms of collaboration between people separated in space and time.
+Bboards provide a centralized and shared venue for discussion that save
+communication costs over ad-hoc mechanisms (like arbitrary email lists).
+Since messages are organized by topic as well as temporally, bboard can
+provide lightweight interfaces for rapidly navigating to interesting
+messages. This low barrier to participation encourages spontaneous
+collaboration between disperse parties in the community.</para>
+
+<para>The bboard system also serves as a useful archive and ad-hoc knowledge
+management tool by virtue of its persistence, light weight organizational
+structure, and flexible browse and search facilities. This sort of knowledge
+base can be easily leveraged to provide long term pedagogical value as well
+as aid in future problem solving.</para>
+
+<para>When integrated with an email system, bboards radically improve email
+based collaboration. Email notifications can encourage continuous awareness
+of community issues. Email based reply functionality further lowers the
+barrier to participation, encouraging more Interaction around the
+Transaction&trade;.</para>
+
+</sect2>
+
+<sect2 id="requirements-system-overview">
+<title>System/Application Overview</title>
+
+
+<para>The bboard system allows users to browse, read, and post messages
+organized into forums. Messages consist of short text messages with optional
+attachments such as image files or html documents. Messages are organized
+into threads when users reply to each other, maintaining the temporal flow of
+a particular discussion.</para>
+
+<para>Forums are contexts for discussion relating to a particular domain of
+interest. Examples include the photo.net Q&amp;A forum, the ArsDigita Web/DB
+forum, and the away.com discussion forum. Messages within a particular forum
+can optionally be tagged as being in certain categories to assist searching
+and navigation. Forums are always created in the context of a subsite.</para>
+
+</sect2>
+
+<sect2 id="requirements-use-cases">
+<title>IV. Use-cases and User Scenarios</title>
+
+
+<para><emphasis role="strong">Administrator</emphasis>: Phillis Goodsport is a world famous
+lithographer who wants to share her knowledge about lithography and encourage
+interaction between a community of lithographers on her new site litho.net.
+Although she likes the idea of a broad forum for general lithography
+discussion, she wants browsing to be tractable when traffic increases. If
+quality goes down, she&#39;d like to dedicate one of her minions to
+moderating traffic to maintain her high standards.</para>
+
+<para><emphasis role="strong">Casual browser and poster</emphasis>: Joe Schmoe goes to photo.net
+for the first time and wants to ask what zoom lens to buy. He needs to find
+the appropriate category/topic to post his message.</para>
+
+<para><emphasis role="strong">Compulsive reader and expert poster</emphasis>: Jane Developer is a
+web development guru and wants to keep up with as much of the traffic on the
+web/db forum as possible. She wants to become aware of posts that might
+become relevant to her in the future as well as help out folks who have
+problems she knows how to solve. Since Jane is on lots of developer mailing
+lists, her preferred form of interaction is via email.</para>
+
+<para><emphasis role="strong">Moderator</emphasis>: Dave Balderdash is a chatter.net moderator and
+wants to delete redundant or useless posts. He&#39;s short on time, so he
+wants a quick interface for rejecting and approving posts.</para>
+
+<para><emphasis role="strong">Targeted researcher</emphasis>: Ted Stetson is an ACS developer who
+remembers someone mentioning something about his Oracle problem on a bboard.
+He wants to find records of similar problems and any related solutions.</para>
+
+</sect2>
+
+<sect2 id="requirements-links">
+<title>Related Links</title>
+
+
+<itemizedlist>
+<listitem><para><xref linkend="design"/></para></listitem>
+
+<listitem><para>Test Plan (not available)</para></listitem>
+
+<listitem><para><ulink url="http://www.arsdigita.com/general-comments/view-one?comment_id=28646&amp;item=BBoard%20module">
+notes on USLaw-BBoard implementation</ulink></para></listitem>
+
+<listitem><para><ulink url="/doc/subsites-requirements.html">Subcommunities</ulink></para></listitem>
+
+<listitem><para><ulink url="http://www.arsdigita.com/bboard/q-and-a-fetch-msg?msg_id=0003ye">Karl&#39;s
+thoughts on bboard redesign</ulink></para></listitem>
+
+<listitem><para><ulink url="http://www.arsdigita.com/bboard/q-and-a-fetch-msg?msg_id=0007ew">Adam
+Farkas&#39;s web/db thread on bboard improvements</ulink></para></listitem>
+</itemizedlist>
+
+</sect2>
+
+<sect2 id="requirements-ui">
+<title>Requirements: User Interface</title>
+
+<itemizedlist>
+<listitem>
+<para><emphasis role="strong">10.10 End User Basics</emphasis></para>
+
+<blockquote>
+<para><emphasis role="strong">10.10.10</emphasis> The bboard system must provide mechanism for
+users to effectively choose which messages to read within a forum. Bboard
+must provide an overview interface to enable users to find messages of
+interest or relevant to them. This overview should provide the user with
+cursory information to facilitate quick scanning and meaningful evaluation of
+message contents.</para>
+
+<para><emphasis role="strong">10.10.15</emphasis> The full text of bboard messages should be
+searchable by user queries.</para>
+
+<para><emphasis role="strong">10.10.20</emphasis> <emphasis role="strong">[unimplemented]</emphasis> Bboard
+should consistently provide a mechanism to limit or sort displayed posts by
+categories, posters, and date range as well as to perform a text search.</para>
+
+<para><emphasis role="strong">10.10.30</emphasis> <emphasis role="strong">[unimplemented]</emphasis> Most
+users primarily want to browse and read new posts or replies since their last
+visit. The bboard interface must allow users to ignore messages they&#39;ve
+already read.</para>
+
+<para><emphasis role="strong">10.10.40</emphasis> <emphasis role="strong">[unimplemented]</emphasis> Users
+should be able to search within and limit scope to messages they have already
+read as well as messages they have not read at all.</para>
+
+<para><emphasis role="strong">10.10.50</emphasis> Users must be able to easily post new messages
+to a bboard, or reply to existing messages they have come across. When
+replying, users must be presenting with enough context to assist their
+composition.</para>
+</blockquote>
+</listitem>
+
+<listitem>
+<para><emphasis role="strong">10.20 Email Integration</emphasis></para>
+
+<blockquote>
+<para><emphasis role="strong">10.20.10</emphasis> Users can register for email notification of new
+messages in a particular forums.</para>
+
+<para><emphasis role="strong">10.20.13</emphasis> Users can register for email notifications on a
+particular thread.</para>
+
+<para><emphasis role="strong">10.20.16</emphasis> Users can register for email notifications on a
+particular category.</para>
+
+<para><emphasis role="strong">10.20.20</emphasis> <emphasis role="strong">[unimplemented]</emphasis>
+Notifications can be sent as each message arrives or in an organized digest
+form over a configurable time period.</para>
+
+<para><emphasis role="strong">10.20.30</emphasis> Individual messages will have appropriate RFC
+822 headers to enable threading in the mail client.</para>
+
+<para><emphasis role="strong">10.20.40</emphasis> <emphasis role="strong">[unimplemented]</emphasis> Email
+from the alert system should be tagged in the header with the site and forum
+name to enable easy filtering in mail clients. Well, as easy as the mail
+clients make it anyway.</para>
+
+<para><emphasis role="strong">10.20.50</emphasis> <emphasis role="strong">[unimplemented]</emphasis> If the
+user requests it, email generated should use MIME encoding to deliver
+attachements and appropriately encode HTML. Otherwise plain text emails
+should be augmented with URLs and styling cues in place of rich content.</para>
+</blockquote>
+</listitem>
+
+<listitem>
+<para><emphasis role="strong">10.30 Administrative Requirements</emphasis></para>
+
+<blockquote>
+<para><emphasis role="strong">10.30.10</emphasis> The bboard system must support a flexible
+presentation layer that allows custom layout of bboard content.</para>
+
+<para><emphasis role="strong">10.30.15</emphasis> Publishers should have the option of displaying
+discussions in a flat linear fashion or in an indented threaded view.</para>
+
+<para><emphasis role="strong">10.30.20</emphasis> Parties with administrative privileges on a
+particular subsite can create, delete, and edit forums scoped to that
+subsite.</para>
+
+<para><emphasis role="strong">10.30.30</emphasis> Forums can be designated moderated in which case
+parties with sufficient privileges must approve messages before they are
+displayed generally.</para>
+</blockquote>
+</listitem>
+
+<listitem>
+<para><emphasis role="strong">10.40 Access Control Requirements</emphasis></para>
+
+<blockquote>
+<para>Objects must be structured to allow the flexible configuration and assignment
+of the following privileges: </para>
+
+<para><emphasis role="strong">10.40.10</emphasis> Reading forums</para>
+
+<para><emphasis role="strong">10.40.20</emphasis> Reading messages</para>
+
+<para><emphasis role="strong">10.40.30</emphasis> Posting new messages</para>
+
+<para><emphasis role="strong">10.40.50</emphasis> Approving and rejecting posted messages (for
+moderated groups)</para>
+
+<para><emphasis role="strong">10.40.60</emphasis> Managing the forum (editing title and
+description, determining moderation and restriction policies, granting
+approval privileges to others, banning users)</para>
+
+<para><emphasis role="strong">10.40.70</emphasis> Managing categories (editing, deleting,
+combining categories)</para>
+</blockquote>
+</listitem>
+</itemizedlist>
+
+</sect2>
+
+<sect2 id="requirements-datamodel">
+<title>Requirements: Data-model</title>
+
+<itemizedlist>
+<listitem>
+<para><emphasis role="strong">20.10 Messages</emphasis></para>
+
+<blockquote>
+<para><emphasis role="strong">20.10.10</emphasis> Messages are the basic units of the bboard
+module. The bboard system will provide a repository to store text
+messages.</para>
+
+<para><emphasis role="strong">20.10.20</emphasis> Messages will be tagged as having HTML, plain
+text, or preformatted text in their body.</para>
+
+<para><emphasis role="strong">20.10.30</emphasis> Messages will have a brief plain text subject
+line.</para>
+
+<para><emphasis role="strong">20.10.40</emphasis> Messages will be related to their creating
+user.</para>
+
+<para><emphasis role="strong">20.10.50</emphasis> Messages may optionally have binary
+attachments.</para>
+
+<para><emphasis role="strong">20.10.60</emphasis> The bboard system must store relations between
+messages and their replies to enable threaded views.</para>
+</blockquote>
+</listitem>
+
+<listitem>
+<para><emphasis role="strong">20.20 Forums</emphasis></para>
+
+<blockquote>
+<para><emphasis role="strong">20.20.10</emphasis> Forums are the main administrative units of the
+bboard system. Forums are containers to which messages uniquely belong.</para>
+
+<para><emphasis role="strong">20.20.20</emphasis> Forums must have a brief text descriptions and
+optionally a longer description called a charter.</para>
+</blockquote>
+</listitem>
+
+<listitem>
+<para><emphasis role="strong">20.30 Categories</emphasis></para>
+
+<blockquote>
+<para><emphasis role="strong">20.30.10</emphasis> There must be a mechanism for intra-forum
+categorization to facilitate filter, searching, and tractability.</para>
+</blockquote>
+</listitem>
+</itemizedlist>
+</sect2>
+
+<sect2 id="requirements-api">
+<title>Requirements: API</title>
+
+
+<para><emphasis>No requirements in this section are met by the current
+implementation.</emphasis></para> 
+
+<para>Since bboard is primarily an end user application any exposed APIs will
+come out of the design rather than nailed down requirements from the start.
+Stay tuned.</para>
+
+</sect2>
+
+<sect2 id="requirements-future">
+<title>Possible Future Requirements</title>
+
+<itemizedlist>
+<listitem>
+<para><emphasis role="strong">40.10 In no particular order</emphasis></para>
+
+<blockquote>
+<para><emphasis role="strong">40.10.10</emphasis> bboard should provide a framework for extending
+the generic messaging repository with meta-data and in tandem extending the
+user interface to take advantage of this meta-data. This would let developers
+properly layer functionality such as geo-spatial messaging and slashdot style
+scoring. This is actually provided via ACS messaging and the ACS Object
+system.</para>
+
+<para><emphasis role="strong">40.10.20</emphasis> bboard should support replying to and
+initiating threads from email. Administrative email list functionality should
+be developed or integrated.</para>
+
+<para><emphasis role="strong">40.10.30</emphasis> Bboard should let users register interests
+(categories, certain users, keywords) for the purpose of filtering and
+sorting message displays.</para>
+
+<para><emphasis role="strong">40.10.40</emphasis> Users should have the option of enabling spell
+checking on their posts. A framework for filtering (removing bad words,
+promoting text URLs to html links, auto detecting HTML vs. plain text, etc.,)
+should exist.</para>
+
+<para><emphasis role="strong">40.10.50</emphasis> Allow users to configure how big the textareas
+editing widgets they get are.</para>
+
+<para><emphasis role="strong">40.10.60</emphasis> Moderators should be given the <emphasis>option</emphasis>
+of making notes on a given discussion that appear prominently in the
+discussion display.</para>
+
+<para><emphasis role="strong">40.10.70</emphasis> Moderators should be able to set posts to
+expire at a configurable time in the future.</para>
+
+<para><emphasis role="strong">40.10.80</emphasis> Mega bonus points: an nntp gateway to bboards
+for access from standard news clients.</para>
+
+<para><emphasis role="strong">40.10.90</emphasis> The bboard system should be able to take
+advantage of a caching system that stores the results of database queries for
+optimal scalability.</para>
+
+<para><emphasis role="strong">40.10.100</emphasis> Publishers should have the option of allowing
+users to edit various parts of messages after they are posted (e.g. the text
+body, the subject, the text presentaiton style etc.,)</para>
+
+<para><emphasis role="strong">40.10.110</emphasis> A user interface should allow administrators
+to easily categorize or recategorize existing messages.</para>
+
+<para><emphasis role="strong">40.10.120</emphasis> Publishers should be able to classify users
+based on their forum contributions and appropriately target them for email,
+promotions, etc.,</para>
+
+<para><emphasis role="strong">40.10.130</emphasis> Explicit permissions for posting new messages
+vs. posting replies.</para>
+
+<para><emphasis role="strong">40.10.140</emphasis> Explicit permissions for posting
+attachments.</para>
+</blockquote>
+</listitem>
+
+<listitem>
+<para><emphasis role="strong">40.20 Performance requirements</emphasis></para>
+</listitem>
+</itemizedlist>
+
+</sect2>
+
+<sect2 id="requirements-rev-history">
+<title>Revision History</title>
+
+
+ 
+<informaltable>
+<tgroup cols="4">
+
+<thead>
+<row role="revisiontop">
+<entry>Document Revision #</entry>
+<entry>Action Taken, Notes</entry>
+<entry>When?</entry>
+<entry>By Whom?</entry>
+</row>
+</thead>
+<tbody>
+
+<row role="revisionbody">
+<entry>0.2</entry>
+<entry>Revision: More standard style, more detailed requirements.</entry>
+<entry>08/24/2000</entry>
+<entry>Anukul Kapoor</entry>
+</row>
+
+
+<row>
+<entry>0.1</entry>
+<entry>Creation</entry>
+<entry>08/23/2000</entry>
+<entry>Anukul Kapoor</entry>
+</row>
+
+</tbody>
+</tgroup>
+</informaltable>
+
+</sect2>
+
+</sect1>
+
Index: openacs-4/packages/sloan-bboard/www/doc/xml/support.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/xml/support.xml,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/xml/support.xml	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,57 @@
+<sect1 id="support" xreflabel="Bboard Support">
+<title>Support</title>
+
+<para>
+There's a couple of different places you can turn to if this documentation 
+comes short of answers to your questions or if you want to give us 
+feedback:
+</para>
+
+<itemizedlist>
+<listitem><para>
+<emphasis role="strong">
+If you have a general question about usage of the application
+</emphasis></para>
+
+<para> 
+Ask on the <ulink url="http://www.arsdigita.com/bboard/q-and-a?topic_id=935&amp;topic=ACS%20Applications">
+applications bboard at arsdigita.com</ulink>.
+</para>
+</listitem>
+
+<listitem><para>
+<emphasis role="strong">
+If you want to report a bug or keep up-to-date on bug fixes
+</emphasis></para>
+
+<para>
+Visit the <ulink url="http://www.arsdigita.com/sdm/all-tickets?module_id=8566&amp;package_id=8157&amp;status=newopen">
+ArsDigita SDM</ulink>.
+</para>
+</listitem>
+
+<listitem><para>
+<emphasis role="strong">
+If you are interested in the general status of the Bboard application
+</emphasis></para>
+
+<para>
+Up to date info on BBoard is available from the <ulink url="http://acs40.arsdigita.com/acs40-project-central/bboard/">BBoard status
+page</ulink>.
+</para>
+</listitem>
+
+<listitem><para>
+<emphasis role="strong">
+If you have questions, comments or suggestions to this documentation
+</emphasis></para>
+
+<para>
+Visit the <ulink url="http://developer.arsdigita.com/docbook/">Documentation Central</ulink>
+or fire directly at <ulink url="mailto:acs-docs@arsdigita.com">acs-docs@ardigita.com</ulink>.
+</para>
+</listitem>
+</itemizedlist>
+
+
+</sect1>
\ No newline at end of file
Index: openacs-4/packages/sloan-bboard/www/doc/xml/top.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/sloan-bboard/www/doc/xml/top.xml,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/sloan-bboard/www/doc/xml/top.xml	15 Feb 2002 21:27:07 -0000	1.1
@@ -0,0 +1,66 @@
+<?xml version='1.0' ?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" 
+	       "http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd" [
+
+<!-- For Everyone -->
+<!ENTITY introduction SYSTEM "intro.xml">
+<!ENTITY support SYSTEM "support.xml">
+<!ENTITY notes SYSTEM "notes.xml">
+
+<!-- For Admins -->
+<!ENTITY installation SYSTEM "installation.xml">
+<!ENTITY configuration SYSTEM "configuration.xml">
+
+<!-- For Developers -->
+<!ENTITY design SYSTEM "design.xml">
+<!ENTITY requirements SYSTEM "requirements.xml">
+
+
+]>
+
+<book>
+<title>Bboard Documentation</title>
+
+
+        <chapter id="for-everyone">
+        <title>For Everyone</title>
+
+            <sect1>
+            <title>Overview</title>
+                <para>Brief introduction, support possibilities and release notes</para>
+            </sect1>
+
+            &introduction;
+            &support;
+            &notes;
+
+        </chapter>
+
+   
+        <chapter id="for-admins" xreflabel="For Admins">
+        <title>For Admins</title>
+
+            <sect1>
+            <title>Overview</title>
+            <para>Installation, maintenance</para>
+            </sect1>
+
+            &installation;
+            &configuration;
+
+        </chapter>
+
+       <chapter id="for-developers" xreflabel="For Developers">
+       <title>For Developers</title>
+
+            <sect1>
+            <title>Overview</title>
+            <para>Requirements, design</para>
+            </sect1>
+
+            &requirements;
+            &design;
+
+        </chapter>
+
+</book>