* landed support for reading topics and posting followup messages to a topic -
the basis of the conferencing engine is now firmly in place * tweaks to the HTML Checker to make it better at breaking lines without leaving stranded punctuation at the beginning or end of a line * also modified dictionary to better handle possessives and hyphenates * as always, miscellaneous tweaks and bugfizes as I spot them
| 
		 Before Width: | Height: | Size: 4.4 KiB  | 
| 
		 Before Width: | Height: | Size: 4.4 KiB  | 
| 
		 Before Width: | Height: | Size: 4.8 KiB  | 
| 
		 Before Width: | Height: | Size: 4.7 KiB  | 
| 
		 Before Width: | Height: | Size: 4.6 KiB  | 
@ -51,7 +51,7 @@
 | 
			
		||||
	  <LI>Output uses XML and gets formatted into [X]HTML via XSLT; "themeable"/"skinnable" interface</LI>
 | 
			
		||||
	  <LI>Conferencing/other functionality available via XML-RPC or SOAP calls</LI>
 | 
			
		||||
	  <LI>News page creation (see Slash, Squishdot, Scoop)</LI>
 | 
			
		||||
	  <LI>Member trust metrics (see Slashdot "karma," Scoop "mojo," Advogato distributed trust metric)</LI>
 | 
			
		||||
	  <LI>Member trust metrics (see Slashdot "karma," Scoop "mojo," Advogato distributed trust metric) <B><EM>(Feature indefinitely shelved at the request of the EMinds community)</EM></B></LI>
 | 
			
		||||
	  <LI>User diary pages (see Advogato, Kuro5hin)</LI>
 | 
			
		||||
	  <LI>Moderated discussions (see Slash, Scoop)</LI>
 | 
			
		||||
	  <LI>Collaborative database facility (see Wiki, Everything2)</LI>
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,105 @@
 | 
			
		||||
advogato
 | 
			
		||||
ain't
 | 
			
		||||
anla'shok
 | 
			
		||||
bajor
 | 
			
		||||
bios
 | 
			
		||||
boitano
 | 
			
		||||
boromax
 | 
			
		||||
can't
 | 
			
		||||
cartman
 | 
			
		||||
checkouts
 | 
			
		||||
couldn't
 | 
			
		||||
crewmember
 | 
			
		||||
crewmembers
 | 
			
		||||
deflector
 | 
			
		||||
deflectors
 | 
			
		||||
delenn
 | 
			
		||||
didn't
 | 
			
		||||
dilithium
 | 
			
		||||
docking
 | 
			
		||||
doesn't
 | 
			
		||||
don't
 | 
			
		||||
eminds
 | 
			
		||||
entil'zha
 | 
			
		||||
eps
 | 
			
		||||
erbo
 | 
			
		||||
fett
 | 
			
		||||
followup
 | 
			
		||||
franklin
 | 
			
		||||
fucking
 | 
			
		||||
hairstyle
 | 
			
		||||
hairstyles
 | 
			
		||||
hasn't
 | 
			
		||||
he'd
 | 
			
		||||
html
 | 
			
		||||
i'd
 | 
			
		||||
i'll
 | 
			
		||||
i'm
 | 
			
		||||
i've
 | 
			
		||||
inducers
 | 
			
		||||
it'd
 | 
			
		||||
khan
 | 
			
		||||
kubla
 | 
			
		||||
kyle
 | 
			
		||||
lafou
 | 
			
		||||
ma'am
 | 
			
		||||
maddog
 | 
			
		||||
marillion
 | 
			
		||||
minbar
 | 
			
		||||
minbari
 | 
			
		||||
mr
 | 
			
		||||
mustn't
 | 
			
		||||
nacelle
 | 
			
		||||
nacelles
 | 
			
		||||
navigational
 | 
			
		||||
ops
 | 
			
		||||
padd
 | 
			
		||||
peachy
 | 
			
		||||
planitia
 | 
			
		||||
planum
 | 
			
		||||
psi
 | 
			
		||||
refit
 | 
			
		||||
refitting
 | 
			
		||||
replicator
 | 
			
		||||
repost
 | 
			
		||||
reposted
 | 
			
		||||
rom
 | 
			
		||||
runabout
 | 
			
		||||
salchow
 | 
			
		||||
salchows
 | 
			
		||||
sarcastically
 | 
			
		||||
silverwrist
 | 
			
		||||
snarf
 | 
			
		||||
snarfage
 | 
			
		||||
snazzy
 | 
			
		||||
sourceforge
 | 
			
		||||
spaceport
 | 
			
		||||
spellchecker
 | 
			
		||||
spellchucker
 | 
			
		||||
spelunker
 | 
			
		||||
spelunkers
 | 
			
		||||
st
 | 
			
		||||
starbase
 | 
			
		||||
starfleet
 | 
			
		||||
starship
 | 
			
		||||
straightening
 | 
			
		||||
stunted
 | 
			
		||||
terrence
 | 
			
		||||
they're
 | 
			
		||||
turbolift
 | 
			
		||||
tuzanor
 | 
			
		||||
umbilical
 | 
			
		||||
umbilicals
 | 
			
		||||
url
 | 
			
		||||
utne
 | 
			
		||||
valen
 | 
			
		||||
veni
 | 
			
		||||
we'll
 | 
			
		||||
we're
 | 
			
		||||
webb
 | 
			
		||||
webbme
 | 
			
		||||
won't
 | 
			
		||||
wouldn't
 | 
			
		||||
you'd
 | 
			
		||||
you'll
 | 
			
		||||
you're
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										13
									
								
								etc/web.xml
									
									
									
									
									
								
							
							
						
						@ -142,6 +142,14 @@
 | 
			
		||||
    <servlet-class>com.silverwrist.venice.servlets.ConfDisplay</servlet-class>
 | 
			
		||||
  </servlet>
 | 
			
		||||
 | 
			
		||||
  <servlet>
 | 
			
		||||
    <servlet-name>postmessage</servlet-name>
 | 
			
		||||
    <description>
 | 
			
		||||
      Posting messages to a conference.
 | 
			
		||||
    </description>
 | 
			
		||||
    <servlet-class>com.silverwrist.venice.servlets.PostMessage</servlet-class>
 | 
			
		||||
  </servlet>
 | 
			
		||||
 | 
			
		||||
  <!-- the following are test servlets, they should go away -->
 | 
			
		||||
 | 
			
		||||
  <servlet>
 | 
			
		||||
@ -200,6 +208,11 @@
 | 
			
		||||
    <url-pattern>/confdisp</url-pattern>
 | 
			
		||||
  </servlet-mapping>
 | 
			
		||||
 | 
			
		||||
  <servlet-mapping>
 | 
			
		||||
    <servlet-name>postmessage</servlet-name>
 | 
			
		||||
    <url-pattern>/post</url-pattern>
 | 
			
		||||
  </servlet-mapping>
 | 
			
		||||
 | 
			
		||||
  <!-- the following are test servlets, they should go away -->
 | 
			
		||||
  <servlet-mapping>
 | 
			
		||||
    <servlet-name>testformdata</servlet-name>
 | 
			
		||||
 | 
			
		||||
@ -416,6 +416,10 @@ INSERT INTO refaudit (type, descr) VALUES
 | 
			
		||||
    (307,     'Delete Topic'),
 | 
			
		||||
    (308,     'Set Topic Frozen'),
 | 
			
		||||
    (309,     'Set Topic Archive'),
 | 
			
		||||
    (310,     'Post Message'),
 | 
			
		||||
    (311,     'Hide Message'),
 | 
			
		||||
    (312,     'Scribble Message'),
 | 
			
		||||
    (313,     'Nuke Message'),
 | 
			
		||||
    (9999999, 'DUMMY');
 | 
			
		||||
 | 
			
		||||
# The ISO 3166 two-letter country codes.  Source is
 | 
			
		||||
 | 
			
		||||
@ -64,4 +64,9 @@ public interface TopicContext
 | 
			
		||||
 | 
			
		||||
  public abstract void fixSeen() throws DataException;
 | 
			
		||||
 | 
			
		||||
  public abstract List getMessages(int low, int high) throws DataException, AccessError;
 | 
			
		||||
 | 
			
		||||
  public abstract TopicMessageContext postNewMessage(long parent, String pseud, String text)
 | 
			
		||||
      throws DataException, AccessError;
 | 
			
		||||
 | 
			
		||||
} // end interface TopicContext
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										64
									
								
								src/com/silverwrist/venice/core/TopicMessageContext.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,64 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 | 
			
		||||
 * (the "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 * 
 | 
			
		||||
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 | 
			
		||||
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 | 
			
		||||
 * language governing rights and limitations under the License.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Original Code is the Venice Web Community System.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
 * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 | 
			
		||||
 * 
 | 
			
		||||
 * Contributor(s): 
 | 
			
		||||
 */
 | 
			
		||||
package com.silverwrist.venice.core;
 | 
			
		||||
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
 | 
			
		||||
public interface TopicMessageContext
 | 
			
		||||
{
 | 
			
		||||
  public abstract long getPostID();
 | 
			
		||||
 | 
			
		||||
  public abstract long getParentPostID();
 | 
			
		||||
 | 
			
		||||
  public abstract int getPostNumber();
 | 
			
		||||
 | 
			
		||||
  public abstract int getNumLines();
 | 
			
		||||
 | 
			
		||||
  public abstract int getCreatorUID();
 | 
			
		||||
 | 
			
		||||
  public abstract String getCreatorName() throws DataException;
 | 
			
		||||
 | 
			
		||||
  public abstract Date getPostDate();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean isHidden();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean isScribbled();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean isNuked();
 | 
			
		||||
 | 
			
		||||
  public abstract Date getScribbleDate();
 | 
			
		||||
 | 
			
		||||
  public abstract String getPseud();
 | 
			
		||||
 | 
			
		||||
  public abstract String getBodyText() throws DataException;
 | 
			
		||||
 | 
			
		||||
  public abstract boolean hasAttachment();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean canHide();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean canScribble();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean canNuke();
 | 
			
		||||
 | 
			
		||||
  public abstract void setHidden(boolean flag) throws DataException, AccessError;
 | 
			
		||||
 | 
			
		||||
  public abstract void scribble() throws DataException, AccessError;
 | 
			
		||||
 | 
			
		||||
  public abstract void nuke() throws DataException, AccessError;
 | 
			
		||||
 | 
			
		||||
} // end interface TopicMessageContext
 | 
			
		||||
@ -17,8 +17,10 @@
 | 
			
		||||
 */
 | 
			
		||||
package com.silverwrist.venice.core.impl;
 | 
			
		||||
 | 
			
		||||
import java.sql.*;
 | 
			
		||||
import java.sql.Connection;
 | 
			
		||||
import java.sql.SQLException;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import com.silverwrist.venice.core.DataException;
 | 
			
		||||
 | 
			
		||||
public interface ConferenceBackend extends SIGBackend
 | 
			
		||||
{
 | 
			
		||||
@ -32,4 +34,14 @@ public interface ConferenceBackend extends SIGBackend
 | 
			
		||||
 | 
			
		||||
  public abstract String realConfAlias();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean userCanScribble();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean userCanNuke();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean userCanRead();
 | 
			
		||||
 | 
			
		||||
  public abstract boolean userCanPost();
 | 
			
		||||
 | 
			
		||||
  public abstract void touchUpdate(Connection conn, java.util.Date date) throws DataException;
 | 
			
		||||
 | 
			
		||||
} // end interface ConferenceBackend
 | 
			
		||||
 | 
			
		||||
@ -932,6 +932,37 @@ class ConferenceCoreData implements ConferenceData
 | 
			
		||||
 | 
			
		||||
  } // end createNewTopic
 | 
			
		||||
 | 
			
		||||
  public boolean canScribblePosts(int level)
 | 
			
		||||
  {
 | 
			
		||||
    return (level>=nuke_level);
 | 
			
		||||
 | 
			
		||||
  } // end canScribblePosts
 | 
			
		||||
 | 
			
		||||
  public boolean canNukePosts(int level)
 | 
			
		||||
  {
 | 
			
		||||
    return (level>=nuke_level);
 | 
			
		||||
 | 
			
		||||
  } // end canNukePosts
 | 
			
		||||
 | 
			
		||||
  public synchronized void touchUpdate(Connection conn, java.util.Date date) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    try
 | 
			
		||||
    { // update the last update date
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
      StringBuffer sql = new StringBuffer("UPDATE confs SET lastupdate = '");
 | 
			
		||||
      sql.append(SQLUtil.encodeDate(date)).append("' WHERE confid = ").append(confid).append(';');
 | 
			
		||||
      stmt.executeUpdate(sql.toString());
 | 
			
		||||
      last_update = date;
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // convert the SQLException
 | 
			
		||||
      throw new DataException("Database error updating conference: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end touchUpdate
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * External static operations (usable only from within package)
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@
 | 
			
		||||
 */
 | 
			
		||||
package com.silverwrist.venice.core.impl;
 | 
			
		||||
 | 
			
		||||
import java.sql.Connection;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import com.silverwrist.venice.core.DataException;
 | 
			
		||||
@ -79,4 +80,10 @@ public interface ConferenceData extends ReferencedData
 | 
			
		||||
  public abstract ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud, String body,
 | 
			
		||||
						 int body_lines) throws DataException;
 | 
			
		||||
 | 
			
		||||
  public abstract boolean canScribblePosts(int level);
 | 
			
		||||
 | 
			
		||||
  public abstract boolean canNukePosts(int level);
 | 
			
		||||
 | 
			
		||||
  public abstract void touchUpdate(Connection conn, Date date) throws DataException;
 | 
			
		||||
 | 
			
		||||
} // end interface ConferenceData
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@
 | 
			
		||||
 */
 | 
			
		||||
package com.silverwrist.venice.core.impl;
 | 
			
		||||
 | 
			
		||||
import java.sql.Connection;
 | 
			
		||||
import java.util.Date;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import com.silverwrist.venice.core.DataException;
 | 
			
		||||
@ -91,4 +92,10 @@ public interface ConferenceSIGContext extends ReferencedData
 | 
			
		||||
  public abstract ReturnTopicInfo createNewTopic(SIGBackend sig, String title, String pseud, String body,
 | 
			
		||||
						 int body_lines) throws DataException;
 | 
			
		||||
 | 
			
		||||
  public abstract boolean canScribblePosts(int level);
 | 
			
		||||
 | 
			
		||||
  public abstract boolean canNukePosts(int level);
 | 
			
		||||
 | 
			
		||||
  public abstract void touchUpdate(Connection conn, Date date) throws DataException;
 | 
			
		||||
 | 
			
		||||
} // end interface ConferenceSIGContext
 | 
			
		||||
 | 
			
		||||
@ -618,4 +618,34 @@ class ConferenceSIGContextImpl implements ConferenceSIGContext
 | 
			
		||||
 | 
			
		||||
  } // end createNewTopic
 | 
			
		||||
 | 
			
		||||
  public boolean canScribblePosts(int level)
 | 
			
		||||
  {
 | 
			
		||||
    ConferenceData c = getConferenceDataNE();
 | 
			
		||||
    if (c==null)
 | 
			
		||||
      return false;
 | 
			
		||||
    if (level<this.level)
 | 
			
		||||
      return c.canScribblePosts(this.level);
 | 
			
		||||
    else
 | 
			
		||||
      return c.canScribblePosts(level);
 | 
			
		||||
 | 
			
		||||
  } // end canScribblePosts
 | 
			
		||||
 | 
			
		||||
  public boolean canNukePosts(int level)
 | 
			
		||||
  {
 | 
			
		||||
    ConferenceData c = getConferenceDataNE();
 | 
			
		||||
    if (c==null)
 | 
			
		||||
      return false;
 | 
			
		||||
    if (level<this.level)
 | 
			
		||||
      return c.canNukePosts(this.level);
 | 
			
		||||
    else
 | 
			
		||||
      return c.canNukePosts(level);
 | 
			
		||||
 | 
			
		||||
  } // end canNukePosts
 | 
			
		||||
 | 
			
		||||
  public void touchUpdate(Connection conn, java.util.Date date) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    getConferenceData().touchUpdate(conn,date);
 | 
			
		||||
 | 
			
		||||
  } // end touchUpdate
 | 
			
		||||
 | 
			
		||||
} // end class ConferenceSIGContextImpl
 | 
			
		||||
 | 
			
		||||
@ -1047,6 +1047,42 @@ class ConferenceUserContextImpl implements ConferenceContext, ConferenceBackend
 | 
			
		||||
 | 
			
		||||
  } // end realConfAlias
 | 
			
		||||
 | 
			
		||||
  public boolean userCanScribble()
 | 
			
		||||
  {
 | 
			
		||||
    ConferenceSIGContext c = getConferenceDataNE();
 | 
			
		||||
    if (c==null)
 | 
			
		||||
      return false;
 | 
			
		||||
    return c.canScribblePosts(level);
 | 
			
		||||
 | 
			
		||||
  } // end userCanScribble
 | 
			
		||||
 | 
			
		||||
  public boolean userCanNuke()
 | 
			
		||||
  {
 | 
			
		||||
    ConferenceSIGContext c = getConferenceDataNE();
 | 
			
		||||
    if (c==null)
 | 
			
		||||
      return false;
 | 
			
		||||
    return c.canNukePosts(level);
 | 
			
		||||
 | 
			
		||||
  } // end userCanNuke
 | 
			
		||||
 | 
			
		||||
  public boolean userCanRead()
 | 
			
		||||
  {
 | 
			
		||||
    return canReadConference();
 | 
			
		||||
 | 
			
		||||
  } // end userCanRead
 | 
			
		||||
 | 
			
		||||
  public boolean userCanPost()
 | 
			
		||||
  {
 | 
			
		||||
    return canPostToConference();
 | 
			
		||||
 | 
			
		||||
  } // end userCanPost
 | 
			
		||||
 | 
			
		||||
  public void touchUpdate(Connection conn, java.util.Date date) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    getConferenceData().touchUpdate(conn,date);
 | 
			
		||||
 | 
			
		||||
  } // end getConferenceData
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static functions usable only from within the package
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,706 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 | 
			
		||||
 * (the "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 * 
 | 
			
		||||
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 | 
			
		||||
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 | 
			
		||||
 * language governing rights and limitations under the License.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Original Code is the Venice Web Community System.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
 * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 | 
			
		||||
 * 
 | 
			
		||||
 * Contributor(s): 
 | 
			
		||||
 */
 | 
			
		||||
package com.silverwrist.venice.core.impl;
 | 
			
		||||
 | 
			
		||||
import java.sql.*;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import org.apache.log4j.*;
 | 
			
		||||
import com.silverwrist.venice.db.*;
 | 
			
		||||
import com.silverwrist.venice.security.AuditRecord;
 | 
			
		||||
import com.silverwrist.venice.core.*;
 | 
			
		||||
 | 
			
		||||
class TopicMessageUserContextImpl implements TopicMessageContext
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static data members
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private static Category logger = Category.getInstance(TopicMessageUserContextImpl.class.getName());
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Attributes
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private EngineBackend engine;
 | 
			
		||||
  private ConferenceBackend conf;
 | 
			
		||||
  private DataPool datapool;
 | 
			
		||||
  private long postid;
 | 
			
		||||
  private long parent;
 | 
			
		||||
  private int num;
 | 
			
		||||
  private int linecount;
 | 
			
		||||
  private int creator_uid;
 | 
			
		||||
  private java.util.Date posted;
 | 
			
		||||
  private boolean hidden;
 | 
			
		||||
  private int scribble_uid;
 | 
			
		||||
  private java.util.Date scribble_date;
 | 
			
		||||
  private String pseud;
 | 
			
		||||
  private int datalen;
 | 
			
		||||
  private String filename;
 | 
			
		||||
  private String mimetype;
 | 
			
		||||
  private boolean nuked = false;
 | 
			
		||||
  private String creator_cache = null;
 | 
			
		||||
  private String text_cache = null;
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Constructors
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  protected TopicMessageUserContextImpl(EngineBackend engine, ConferenceBackend conf, DataPool datapool,
 | 
			
		||||
					long postid, long parent, int num, int linecount, int creator_uid,
 | 
			
		||||
					java.util.Date posted, boolean hidden, int scribble_uid,
 | 
			
		||||
					java.util.Date scribble_date, String pseud, int datalen,
 | 
			
		||||
					String filename, String mimetype)
 | 
			
		||||
  {
 | 
			
		||||
    this.engine = engine;
 | 
			
		||||
    this.conf = conf;
 | 
			
		||||
    this.datapool = datapool;
 | 
			
		||||
    this.postid = postid;
 | 
			
		||||
    this.parent = parent;
 | 
			
		||||
    this.num = num;
 | 
			
		||||
    this.linecount = linecount;
 | 
			
		||||
    this.creator_uid = creator_uid;
 | 
			
		||||
    this.posted = posted;
 | 
			
		||||
    this.hidden = hidden;
 | 
			
		||||
    this.scribble_uid = scribble_uid;
 | 
			
		||||
    this.scribble_date = scribble_date;
 | 
			
		||||
    this.pseud = pseud;
 | 
			
		||||
    this.datalen = datalen;
 | 
			
		||||
    this.filename = filename;
 | 
			
		||||
    this.mimetype = mimetype;
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
 | 
			
		||||
  TopicMessageUserContextImpl(EngineBackend engine, ConferenceBackend conf, DataPool datapool,
 | 
			
		||||
			      long postid, long parent, int num, int linecount, int creator_uid,
 | 
			
		||||
			      java.util.Date posted, String pseud)
 | 
			
		||||
  {
 | 
			
		||||
    this.engine = engine;
 | 
			
		||||
    this.conf = conf;
 | 
			
		||||
    this.datapool = datapool;
 | 
			
		||||
    this.postid = postid;
 | 
			
		||||
    this.parent = parent;
 | 
			
		||||
    this.num = num;
 | 
			
		||||
    this.linecount = linecount;
 | 
			
		||||
    this.creator_uid = creator_uid;
 | 
			
		||||
    this.posted = posted;
 | 
			
		||||
    this.hidden = false;
 | 
			
		||||
    this.scribble_uid = 0;
 | 
			
		||||
    this.scribble_date = null;
 | 
			
		||||
    this.pseud = pseud;
 | 
			
		||||
    this.datalen = 0;
 | 
			
		||||
    this.filename = null;
 | 
			
		||||
    this.mimetype = null;
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Internal functions
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private static String quickGetUserName(Connection conn, int uid) throws SQLException
 | 
			
		||||
  {
 | 
			
		||||
    Statement stmt = conn.createStatement();
 | 
			
		||||
    ResultSet rs = stmt.executeQuery("SELECT username FROM users WHERE uid = " + String.valueOf(uid) + ";");
 | 
			
		||||
    if (rs.next())
 | 
			
		||||
      return rs.getString(1);
 | 
			
		||||
    else
 | 
			
		||||
      return "(unknown)";
 | 
			
		||||
 | 
			
		||||
  } // end quickGetUserName
 | 
			
		||||
 | 
			
		||||
  private void refresh(Connection conn) throws SQLException
 | 
			
		||||
  {
 | 
			
		||||
    Statement stmt = conn.createStatement();
 | 
			
		||||
    StringBuffer sql = new StringBuffer("SELECT p.hidden, p.scribble_uid, p.scribble_date, p.pseud, "
 | 
			
		||||
					+ "a.datalen, a.filename, a.mimetype FROM posts p LEFT JOIN "
 | 
			
		||||
					+ "postattach a ON p.postid = a.postid WHERE p.postid = ");
 | 
			
		||||
    sql.append(postid).append(';');
 | 
			
		||||
    ResultSet rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
    if (rs.next())
 | 
			
		||||
    { // update a variety of fields
 | 
			
		||||
      hidden = rs.getBoolean(1);
 | 
			
		||||
      scribble_uid = rs.getInt(2);
 | 
			
		||||
      scribble_date = SQLUtil.getFullDateTime(rs,3);
 | 
			
		||||
      pseud = rs.getString(4);
 | 
			
		||||
      datalen = rs.getInt(5);
 | 
			
		||||
      filename = rs.getString(6);
 | 
			
		||||
      mimetype = rs.getString(7);
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
    else
 | 
			
		||||
    { // the post has been nuked - update accordingly
 | 
			
		||||
      linecount = 0;
 | 
			
		||||
      creator_uid = -1;
 | 
			
		||||
      posted = null;
 | 
			
		||||
      hidden = false;
 | 
			
		||||
      scribble_uid = -1;
 | 
			
		||||
      scribble_date = null;
 | 
			
		||||
      pseud = null;
 | 
			
		||||
      datalen = 0;
 | 
			
		||||
      filename = null;
 | 
			
		||||
      mimetype = null;
 | 
			
		||||
      nuked = true;
 | 
			
		||||
      creator_cache = null;
 | 
			
		||||
      text_cache = null;
 | 
			
		||||
 | 
			
		||||
    } // end else
 | 
			
		||||
 | 
			
		||||
  } // end refresh
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface TopicMessageContext
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public long getPostID()
 | 
			
		||||
  {
 | 
			
		||||
    return postid;
 | 
			
		||||
 | 
			
		||||
  } // end getPostID
 | 
			
		||||
 | 
			
		||||
  public long getParentPostID()
 | 
			
		||||
  {
 | 
			
		||||
    return parent;
 | 
			
		||||
 | 
			
		||||
  } // end getParentPostID
 | 
			
		||||
 | 
			
		||||
  public int getPostNumber()
 | 
			
		||||
  {
 | 
			
		||||
    return num;
 | 
			
		||||
 | 
			
		||||
  } // end getPostNumber
 | 
			
		||||
 | 
			
		||||
  public int getNumLines()
 | 
			
		||||
  {
 | 
			
		||||
    return linecount;
 | 
			
		||||
 | 
			
		||||
  } // end getNumLines
 | 
			
		||||
 | 
			
		||||
  public int getCreatorUID()
 | 
			
		||||
  {
 | 
			
		||||
    return creator_uid;
 | 
			
		||||
 | 
			
		||||
  } // end getCreatorUID
 | 
			
		||||
 | 
			
		||||
  public String getCreatorName() throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    if (creator_cache==null)
 | 
			
		||||
    { // we don't have the user name yet, get it out of the database
 | 
			
		||||
      if (nuked)
 | 
			
		||||
	return null;  // post nuked!
 | 
			
		||||
      Connection conn = null;
 | 
			
		||||
 | 
			
		||||
      try
 | 
			
		||||
      { // use a database connection to get the user name
 | 
			
		||||
	conn = datapool.getConnection();
 | 
			
		||||
	refresh(conn);
 | 
			
		||||
	if (nuked)
 | 
			
		||||
	  return null;  // post nuked!
 | 
			
		||||
	creator_cache = quickGetUserName(conn,creator_uid);
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (SQLException e)
 | 
			
		||||
      { // turn this into a DataException
 | 
			
		||||
	logger.error("DB error reading user name: " + e.getMessage(),e);
 | 
			
		||||
	throw new DataException("unable to retrieve user name: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
      finally
 | 
			
		||||
      { // make sure we release the connection before we go
 | 
			
		||||
	if (conn!=null)
 | 
			
		||||
	  datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
      } // end finally
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    return creator_cache;
 | 
			
		||||
 | 
			
		||||
  } // end getCreatorName
 | 
			
		||||
 | 
			
		||||
  public java.util.Date getPostDate()
 | 
			
		||||
  {
 | 
			
		||||
    return posted;
 | 
			
		||||
 | 
			
		||||
  } // end getPostDate
 | 
			
		||||
 | 
			
		||||
  public boolean isHidden()
 | 
			
		||||
  {
 | 
			
		||||
    return hidden;
 | 
			
		||||
 | 
			
		||||
  } // end isHidden
 | 
			
		||||
 | 
			
		||||
  public boolean isScribbled()
 | 
			
		||||
  {
 | 
			
		||||
    return (scribble_date!=null);
 | 
			
		||||
 | 
			
		||||
  } // end isScribbled
 | 
			
		||||
 | 
			
		||||
  public boolean isNuked()
 | 
			
		||||
  {
 | 
			
		||||
    return nuked;
 | 
			
		||||
 | 
			
		||||
  } // end isNuked
 | 
			
		||||
 | 
			
		||||
  public java.util.Date getScribbleDate()
 | 
			
		||||
  {
 | 
			
		||||
    return scribble_date;
 | 
			
		||||
 | 
			
		||||
  } // end getScribbleDate
 | 
			
		||||
 | 
			
		||||
  public String getPseud()
 | 
			
		||||
  {
 | 
			
		||||
    return pseud;
 | 
			
		||||
 | 
			
		||||
  } // return pseud
 | 
			
		||||
 | 
			
		||||
  public String getBodyText() throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    if (text_cache==null)
 | 
			
		||||
    { // we don't have the body text yet, go get it
 | 
			
		||||
      Connection conn = null;
 | 
			
		||||
      if (nuked)
 | 
			
		||||
	return null;  // post nuked!
 | 
			
		||||
 | 
			
		||||
      try
 | 
			
		||||
      { // use a database connection to get the body text
 | 
			
		||||
	conn = datapool.getConnection();
 | 
			
		||||
	refresh(conn);
 | 
			
		||||
 | 
			
		||||
	if (nuked)
 | 
			
		||||
	  return null;  // post nuked!
 | 
			
		||||
 | 
			
		||||
	if (scribble_date==null)
 | 
			
		||||
	{ // let's go get the body text!
 | 
			
		||||
	  Statement stmt = conn.createStatement();
 | 
			
		||||
	  ResultSet rs = stmt.executeQuery("SELECT data FROM postdata WHERE postid = "
 | 
			
		||||
					   + String.valueOf(postid) + ";");
 | 
			
		||||
	  if (rs.next())
 | 
			
		||||
	    text_cache = rs.getString(1);
 | 
			
		||||
	  else
 | 
			
		||||
	    return "Data Missing";  // FUTURE: throw an exception?
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
	else // for scribbled posts, we return the scribbler's name only
 | 
			
		||||
	  text_cache = quickGetUserName(conn,scribble_uid);
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (SQLException e)
 | 
			
		||||
      { // turn this into a DataException
 | 
			
		||||
	logger.error("DB error reading post data: " + e.getMessage(),e);
 | 
			
		||||
	throw new DataException("unable to retrieve post data: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
      finally
 | 
			
		||||
      { // make sure we release the connection before we go
 | 
			
		||||
	if (conn!=null)
 | 
			
		||||
	  datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
      } // end finally
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    return text_cache;
 | 
			
		||||
 | 
			
		||||
  } // end getBodyText
 | 
			
		||||
 | 
			
		||||
  public boolean hasAttachment()
 | 
			
		||||
  {
 | 
			
		||||
    return (mimetype!=null);
 | 
			
		||||
 | 
			
		||||
  } // end hasAttachment
 | 
			
		||||
 | 
			
		||||
  public boolean canHide()
 | 
			
		||||
  {
 | 
			
		||||
    return ((creator_uid==conf.realUID()) || conf.userCanHide());
 | 
			
		||||
 | 
			
		||||
  } // end canHide
 | 
			
		||||
 | 
			
		||||
  public boolean canScribble()
 | 
			
		||||
  {
 | 
			
		||||
    return ((creator_uid==conf.realUID()) || conf.userCanScribble());
 | 
			
		||||
 | 
			
		||||
  } // end canScribble
 | 
			
		||||
 | 
			
		||||
  public boolean canNuke()
 | 
			
		||||
  {
 | 
			
		||||
    return conf.userCanNuke();
 | 
			
		||||
 | 
			
		||||
  } // end canNuke
 | 
			
		||||
 | 
			
		||||
  public void setHidden(boolean flag) throws DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    if ((creator_uid!=conf.realUID()) && !(conf.userCanHide()))
 | 
			
		||||
    { // we can't change the hidden status!
 | 
			
		||||
      logger.error("trying to set hidden status of post w/o permission!");
 | 
			
		||||
      throw new AccessError("You are not permitted to change the hidden status of this message.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    if (nuked || (scribble_date!=null))
 | 
			
		||||
      return;  // changing the status of a nuked or scribbled post is futile
 | 
			
		||||
 | 
			
		||||
    Connection conn = null;
 | 
			
		||||
    AuditRecord ar = null;
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // open up a database connection
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
 | 
			
		||||
      // lock the tables we reference
 | 
			
		||||
      stmt.executeUpdate("LOCK TABLES posts WRITE, postattach READ;");
 | 
			
		||||
      try
 | 
			
		||||
      { // first, make sure we have the right status for our post
 | 
			
		||||
	refresh(conn);
 | 
			
		||||
	if (nuked || (scribble_date!=null))
 | 
			
		||||
	  return;  // changing the status of a nuked or scribbled post is futile
 | 
			
		||||
	if (hidden==flag)
 | 
			
		||||
	  return;  // this is a no-op
 | 
			
		||||
 | 
			
		||||
	// update the "hidden" flag in the database
 | 
			
		||||
	StringBuffer sql = new StringBuffer("UPDATE posts SET hidden = ");
 | 
			
		||||
	sql.append(flag ? '1' : '0').append(" WHERE postid = ").append(postid).append(';');
 | 
			
		||||
	stmt.executeUpdate(sql.toString());
 | 
			
		||||
 | 
			
		||||
	hidden = flag;  // store flag
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      finally
 | 
			
		||||
      { // unlock the tables before we go
 | 
			
		||||
	Statement ulk_stmt = conn.createStatement();
 | 
			
		||||
	ulk_stmt.executeUpdate("UNLOCK TABLES;");
 | 
			
		||||
 | 
			
		||||
      } // end finally
 | 
			
		||||
 | 
			
		||||
      // record what we did in an audit record
 | 
			
		||||
      ar = new AuditRecord(AuditRecord.HIDE_MESSAGE,conf.realUID(),conf.userRemoteAddress(),
 | 
			
		||||
			   conf.realSIGID(),"conf=" + String.valueOf(conf.realConfID()) + ",post="
 | 
			
		||||
			   + String.valueOf(postid),flag ? "hide" : "unhide");
 | 
			
		||||
      
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // turn this into a DataException
 | 
			
		||||
      logger.error("DB error setting hidden status: " + e.getMessage(),e);
 | 
			
		||||
      throw new DataException("unable to set hidden status: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    finally
 | 
			
		||||
    { // make sure we release the connection before we go
 | 
			
		||||
      try
 | 
			
		||||
      { // save off the audit record before we go, though
 | 
			
		||||
	if ((ar!=null) && (conn!=null))
 | 
			
		||||
	  ar.store(conn);
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (SQLException e)
 | 
			
		||||
      { // we couldn't store the audit record!
 | 
			
		||||
	logger.error("DB error saving audit record: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
      if (conn!=null)
 | 
			
		||||
	datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
  } // end setHidden
 | 
			
		||||
 | 
			
		||||
  public void scribble() throws DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    if ((creator_uid!=conf.realUID()) && !(conf.userCanScribble()))
 | 
			
		||||
    { // we can't scribble this post
 | 
			
		||||
      logger.error("trying to scribble post w/o permission!");
 | 
			
		||||
      throw new AccessError("You are not permitted to scribble this message.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    if (nuked || (scribble_date!=null))
 | 
			
		||||
      return;  // scribbling a nuked or scribbled post is futile
 | 
			
		||||
 | 
			
		||||
    Connection conn = null;
 | 
			
		||||
    AuditRecord ar = null;
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // open up a database connection
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
 | 
			
		||||
      // lock the tables we reference
 | 
			
		||||
      stmt.executeUpdate("LOCK TABLES posts WRITE, postdata WRITE, postattach WRITE;");
 | 
			
		||||
      try
 | 
			
		||||
      { // first, make sure we have the right status for our post
 | 
			
		||||
	refresh(conn);
 | 
			
		||||
	if (nuked || (scribble_date!=null))
 | 
			
		||||
	  return;  // scribbling a nuked or scribbled post is futile
 | 
			
		||||
 | 
			
		||||
	// First, set the appropriate "scribbled" information in the "header".
 | 
			
		||||
	StringBuffer sql = new StringBuffer("UPDATE posts SET linecount = 0, hidden = 0, scribble_uid = ");
 | 
			
		||||
	sql.append(conf.realUID()).append(", scribble_date = '");
 | 
			
		||||
	java.util.Date now = new java.util.Date();
 | 
			
		||||
	final String scribble_pseud = "<EM><B>(Scribbled)</B></EM>";  // TODO: configurable option
 | 
			
		||||
	sql.append(SQLUtil.encodeDate(now)).append("', pseud = '").append(scribble_pseud);
 | 
			
		||||
	sql.append("' WHERE postid = ").append(postid).append(';');
 | 
			
		||||
	if (logger.isDebugEnabled())
 | 
			
		||||
	  logger.debug("SQL: " + sql.toString());
 | 
			
		||||
	stmt.executeUpdate(sql.toString());
 | 
			
		||||
 | 
			
		||||
	// Determine if we need to "rub out" the post before we delete it.
 | 
			
		||||
	ResultSet rs = stmt.executeQuery("SELECT LENGTH(data) FROM postdata WHERE postid = "
 | 
			
		||||
					 + String.valueOf(postid) + ";");
 | 
			
		||||
	if (rs.next())
 | 
			
		||||
	{ // use this data to overwrite the post with X's
 | 
			
		||||
	  int len = rs.getInt(1);
 | 
			
		||||
	  if (len>0)
 | 
			
		||||
	  { // construct the "rubout" statement and execute it
 | 
			
		||||
	    sql.setLength(0);
 | 
			
		||||
	    sql.append("UPDATE postdata SET data = '");
 | 
			
		||||
	    while (len>0)
 | 
			
		||||
	    { // generate a string of X's the length of the post
 | 
			
		||||
	      sql.append('X');
 | 
			
		||||
	      len--;
 | 
			
		||||
 | 
			
		||||
	    } // end while
 | 
			
		||||
 | 
			
		||||
	    sql.append("' WHERE postid = ").append(postid).append(';');
 | 
			
		||||
	    stmt.executeUpdate(sql.toString());
 | 
			
		||||
 | 
			
		||||
	  } // end if
 | 
			
		||||
	  // else not much need to do a rubout
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
	// else don't try...we're deleting the row anyway
 | 
			
		||||
 | 
			
		||||
	// Delete the actual post data row.
 | 
			
		||||
	sql.setLength(0);
 | 
			
		||||
	sql.append("DELETE FROM postdata WHERE postid = ").append(postid).append(';');
 | 
			
		||||
	stmt.executeUpdate(sql.toString());
 | 
			
		||||
 | 
			
		||||
	// Delete the attachment data row.
 | 
			
		||||
	// FUTURE: can we do an overwrite on the attachment the way we did on the post data?
 | 
			
		||||
	sql.setLength(0);
 | 
			
		||||
	sql.append("DELETE FROM postattach WHERE postid = ").append(postid).append(';');
 | 
			
		||||
	stmt.executeUpdate(sql.toString());
 | 
			
		||||
 | 
			
		||||
	// Update our internal data fields.
 | 
			
		||||
	linecount = 0;
 | 
			
		||||
	hidden = false;
 | 
			
		||||
	scribble_uid = conf.realUID();
 | 
			
		||||
	scribble_date = now;
 | 
			
		||||
	pseud = scribble_pseud;
 | 
			
		||||
	text_cache = null;
 | 
			
		||||
	
 | 
			
		||||
      } // end try
 | 
			
		||||
      finally
 | 
			
		||||
      { // unlock the tables before we go
 | 
			
		||||
	Statement ulk_stmt = conn.createStatement();
 | 
			
		||||
	ulk_stmt.executeUpdate("UNLOCK TABLES;");
 | 
			
		||||
 | 
			
		||||
      } // end finally
 | 
			
		||||
 | 
			
		||||
      // record what we did in an audit record
 | 
			
		||||
      ar = new AuditRecord(AuditRecord.SCRIBBLE_MESSAGE,conf.realUID(),conf.userRemoteAddress(),
 | 
			
		||||
			   conf.realSIGID(),"conf=" + String.valueOf(conf.realConfID()) + ",post="
 | 
			
		||||
			   + String.valueOf(postid));
 | 
			
		||||
      
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // turn this into a DataException
 | 
			
		||||
      logger.error("DB error scribbling post: " + e.getMessage(),e);
 | 
			
		||||
      throw new DataException("unable to scribble message: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    finally
 | 
			
		||||
    { // make sure we release the connection before we go
 | 
			
		||||
      try
 | 
			
		||||
      { // save off the audit record before we go, though
 | 
			
		||||
	if ((ar!=null) && (conn!=null))
 | 
			
		||||
	  ar.store(conn);
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (SQLException e)
 | 
			
		||||
      { // we couldn't store the audit record!
 | 
			
		||||
	logger.error("DB error saving audit record: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
      if (conn!=null)
 | 
			
		||||
	datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
  } // end scribble
 | 
			
		||||
 | 
			
		||||
  public void nuke() throws DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    if (!(conf.userCanNuke()))
 | 
			
		||||
    { // we can't scribble this post
 | 
			
		||||
      logger.error("trying to nuke post w/o permission!");
 | 
			
		||||
      throw new AccessError("You are not permitted to nuke this message.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    if (nuked)
 | 
			
		||||
      return;  // nuking a nuked post is futile
 | 
			
		||||
 | 
			
		||||
    Connection conn = null;
 | 
			
		||||
    AuditRecord ar = null;
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // open up a database connection
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
 | 
			
		||||
      // lock the tables we reference
 | 
			
		||||
      stmt.executeUpdate("LOCK TABLES posts WRITE, postdata WRITE, postattach WRITE, postdogear WRITE;");
 | 
			
		||||
 | 
			
		||||
      try
 | 
			
		||||
      { // first, make sure we have the right status for our post
 | 
			
		||||
	refresh(conn);
 | 
			
		||||
	if (nuked)
 | 
			
		||||
	  return;  // nuking a nuked post is futile
 | 
			
		||||
 | 
			
		||||
	// Delete any and all references to this post!
 | 
			
		||||
	stmt.executeUpdate("DELETE FROM posts WHERE postid = " + String.valueOf(postid) + ";");
 | 
			
		||||
	stmt.executeUpdate("DELETE FROM postdata WHERE postid = " + String.valueOf(postid) + ";");
 | 
			
		||||
	stmt.executeUpdate("DELETE FROM postattach WHERE postid = " + String.valueOf(postid) + ";");
 | 
			
		||||
	stmt.executeUpdate("DELETE FROM postdogear WHERE postid = " + String.valueOf(postid) + ";");
 | 
			
		||||
 | 
			
		||||
	// Update our internal variables.
 | 
			
		||||
	linecount = 0;
 | 
			
		||||
	creator_uid = -1;
 | 
			
		||||
	posted = null;
 | 
			
		||||
	hidden = false;
 | 
			
		||||
	scribble_uid = -1;
 | 
			
		||||
	scribble_date = null;
 | 
			
		||||
	pseud = null;
 | 
			
		||||
	datalen = 0;
 | 
			
		||||
	filename = null;
 | 
			
		||||
	mimetype = null;
 | 
			
		||||
	nuked = true;
 | 
			
		||||
	creator_cache = null;
 | 
			
		||||
	text_cache = null;
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      finally
 | 
			
		||||
      { // unlock the tables before we go
 | 
			
		||||
	Statement ulk_stmt = conn.createStatement();
 | 
			
		||||
	ulk_stmt.executeUpdate("UNLOCK TABLES;");
 | 
			
		||||
 | 
			
		||||
      } // end finally
 | 
			
		||||
 | 
			
		||||
      // record what we did in an audit record
 | 
			
		||||
      ar = new AuditRecord(AuditRecord.NUKE_MESSAGE,conf.realUID(),conf.userRemoteAddress(),
 | 
			
		||||
			   conf.realSIGID(),"conf=" + String.valueOf(conf.realConfID()) + ",post="
 | 
			
		||||
			   + String.valueOf(postid));
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // turn this into a DataException
 | 
			
		||||
      logger.error("DB error nuking post: " + e.getMessage(),e);
 | 
			
		||||
      throw new DataException("unable to nuke message: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    finally
 | 
			
		||||
    { // make sure we release the connection before we go
 | 
			
		||||
      try
 | 
			
		||||
      { // save off the audit record before we go, though
 | 
			
		||||
	if ((ar!=null) && (conn!=null))
 | 
			
		||||
	  ar.store(conn);
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (SQLException e)
 | 
			
		||||
      { // we couldn't store the audit record!
 | 
			
		||||
	logger.error("DB error saving audit record: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
      if (conn!=null)
 | 
			
		||||
	datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
  } // end nuke
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * External static operations
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  static List loadMessageRange(EngineBackend engine, ConferenceBackend conf, DataPool datapool, int topicid,
 | 
			
		||||
			       int post_low, int post_high) throws DataException
 | 
			
		||||
  {
 | 
			
		||||
    if (logger.isDebugEnabled())
 | 
			
		||||
      logger.debug("loadMessageRange for conf # " + String.valueOf(conf.realConfID()) + ", topic #"
 | 
			
		||||
		   + String.valueOf(topicid) + ", range [" + String.valueOf(post_low) + ", "
 | 
			
		||||
		   + String.valueOf(post_high) + "]");
 | 
			
		||||
 | 
			
		||||
    Vector rc = new Vector();
 | 
			
		||||
    Connection conn = null;      // pooled database connection
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // get a database connection
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
 | 
			
		||||
      // run a query to get all the posts in a particular topic
 | 
			
		||||
      StringBuffer sql =
 | 
			
		||||
	  new StringBuffer("SELECT p.postid, p.parent, p.num, p.linecount, p.creator_uid, p.posted, "
 | 
			
		||||
			   + "p.hidden, p.scribble_uid,	p.scribble_date, p.pseud, a.datalen, a.filename, "
 | 
			
		||||
			   + "a.mimetype FROM posts p LEFT JOIN postattach a ON p.postid = a.postid "
 | 
			
		||||
			   + "WHERE p.topicid = ");
 | 
			
		||||
      sql.append(topicid).append(" AND p.num >= ").append(post_low).append(" AND p.num <= ");
 | 
			
		||||
      sql.append(post_high).append(" ORDER BY p.num ASC;");
 | 
			
		||||
      if (logger.isDebugEnabled())
 | 
			
		||||
	logger.debug("SQL: " + sql.toString());
 | 
			
		||||
      ResultSet rs = stmt.executeQuery(sql.toString());
 | 
			
		||||
 | 
			
		||||
      while (rs.next())
 | 
			
		||||
      { // create implementation objects and shove them into the return vector
 | 
			
		||||
	TopicMessageContext val =
 | 
			
		||||
	  new TopicMessageUserContextImpl(engine,conf,datapool,rs.getLong(1),rs.getLong(2),rs.getInt(3),
 | 
			
		||||
					  rs.getInt(4),rs.getInt(5),SQLUtil.getFullDateTime(rs,6),
 | 
			
		||||
					  rs.getBoolean(7),rs.getInt(8),SQLUtil.getFullDateTime(rs,9),
 | 
			
		||||
					  rs.getString(10),rs.getInt(11),rs.getString(12),rs.getString(13));
 | 
			
		||||
	rc.add(val);
 | 
			
		||||
 | 
			
		||||
      } // end while
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // turn SQLException into data exception
 | 
			
		||||
      logger.error("DB error reading message entries: " + e.getMessage(),e);
 | 
			
		||||
      throw new DataException("unable to retrieve messages: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    finally
 | 
			
		||||
    { // make sure we release the connection before we go
 | 
			
		||||
      if (conn!=null)
 | 
			
		||||
	datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
    return new ReadOnlyVector(rc);  // wrap the return vector
 | 
			
		||||
 | 
			
		||||
  } // end loadMessageRange
 | 
			
		||||
 | 
			
		||||
} // end class TopicMessageUserContextImpl
 | 
			
		||||
@ -21,6 +21,7 @@ import java.sql.*;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import org.apache.log4j.*;
 | 
			
		||||
import com.silverwrist.venice.db.*;
 | 
			
		||||
import com.silverwrist.venice.htmlcheck.*;
 | 
			
		||||
import com.silverwrist.venice.security.AuditRecord;
 | 
			
		||||
import com.silverwrist.venice.core.*;
 | 
			
		||||
 | 
			
		||||
@ -109,11 +110,13 @@ class TopicUserContextImpl implements TopicContext
 | 
			
		||||
  private static ResultSet queryByTopic(Statement stmt, int topicid, int uid) throws SQLException
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer sql =
 | 
			
		||||
      new StringBuffer("SELECT t.topicid, t.num, t.creator_uid, t.top_message, t.frozen, t.archived, "
 | 
			
		||||
		       + "t.createdate, t.lastupdate, t.name, IFNULL(s.hidden,0) AS hidden, "
 | 
			
		||||
		       + "(t.top_message - IFNULL(s.last_message,-1)) AS unread FROM topics t "
 | 
			
		||||
		       + "LEFT JOIN topicsettings s ON t.topicid = s.topicid AND s.uid = ");
 | 
			
		||||
    sql.append(uid).append(" WHERE t.topicid = ").append(topicid).append(';');
 | 
			
		||||
      new StringBuffer("SELECT topics.topicid, topics.num, topics.creator_uid, topics.top_message, "
 | 
			
		||||
		       + "topics.frozen, topics.archived, topics.createdate, topics.lastupdate, "
 | 
			
		||||
		       + "topics.name, IFNULL(topicsettings.hidden,0) AS hidden, "
 | 
			
		||||
		       + "(topics.top_message - IFNULL(topicsettings.last_message,-1)) AS unread "
 | 
			
		||||
		       + "FROM topics LEFT JOIN topicsettings ON topics.topicid = topicsettings.topicid "
 | 
			
		||||
		       + "AND topicsettings.uid = ");
 | 
			
		||||
    sql.append(uid).append(" WHERE topics.topicid = ").append(topicid).append(';');
 | 
			
		||||
    if (logger.isDebugEnabled())
 | 
			
		||||
      logger.debug("SQL: " + sql.toString());
 | 
			
		||||
    return stmt.executeQuery(sql.toString());
 | 
			
		||||
@ -134,8 +137,29 @@ class TopicUserContextImpl implements TopicContext
 | 
			
		||||
 | 
			
		||||
  } // end if
 | 
			
		||||
 | 
			
		||||
  private void refresh(Connection conn) throws SQLException
 | 
			
		||||
  {
 | 
			
		||||
    Statement stmt = conn.createStatement();
 | 
			
		||||
    
 | 
			
		||||
    // perform a requery of the database
 | 
			
		||||
    ResultSet rs = queryByTopic(stmt,topicid,conf.realUID());
 | 
			
		||||
    if (rs.next())
 | 
			
		||||
    { // update the fields that are capable of changing
 | 
			
		||||
      top_message = rs.getInt(4);
 | 
			
		||||
      frozen = rs.getBoolean(5);
 | 
			
		||||
      archived = rs.getBoolean(6);
 | 
			
		||||
      lastupdate = SQLUtil.getFullDateTime(rs,8);
 | 
			
		||||
      hidden = rs.getBoolean(10);
 | 
			
		||||
      unread = rs.getInt(11);
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
    else // this topic must have been deleted - fsck it
 | 
			
		||||
      makeDeleted();
 | 
			
		||||
 | 
			
		||||
  } // end refresh
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementatuions from interface TopicContext
 | 
			
		||||
   * Implementations from interface TopicContext
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
@ -148,22 +172,7 @@ class TopicUserContextImpl implements TopicContext
 | 
			
		||||
    try
 | 
			
		||||
    { // get a database connection
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
 | 
			
		||||
      // perform a requery of the database
 | 
			
		||||
      ResultSet rs = queryByTopic(stmt,topicid,conf.realUID());
 | 
			
		||||
      if (rs.next())
 | 
			
		||||
      { // update the fields that are capable of changing
 | 
			
		||||
	top_message = rs.getInt(4);
 | 
			
		||||
	frozen = rs.getBoolean(5);
 | 
			
		||||
	archived = rs.getBoolean(6);
 | 
			
		||||
	lastupdate = SQLUtil.getFullDateTime(rs,8);
 | 
			
		||||
	hidden = rs.getBoolean(10);
 | 
			
		||||
	unread = rs.getInt(11);
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
      else // this topic must have been deleted - fsck it
 | 
			
		||||
	makeDeleted();
 | 
			
		||||
      refresh(conn);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
@ -524,8 +533,8 @@ class TopicUserContextImpl implements TopicContext
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // turn SQLException into data exception
 | 
			
		||||
      logger.error("DB error setting topic data: " + e.getMessage(),e);
 | 
			
		||||
      throw new DataException("unable to set topic hidden status: " + e.getMessage(),e);
 | 
			
		||||
      logger.error("DB error setting topic user data: " + e.getMessage(),e);
 | 
			
		||||
      throw new DataException("unable to set unread messages: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    finally
 | 
			
		||||
@ -543,6 +552,213 @@ class TopicUserContextImpl implements TopicContext
 | 
			
		||||
 | 
			
		||||
  } // end fixSeen
 | 
			
		||||
 | 
			
		||||
  public List getMessages(int low, int high) throws DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    if (!(conf.userCanRead()))
 | 
			
		||||
    { // they can't read messages in this topic!
 | 
			
		||||
      logger.error("trying to read postings w/o permission!");
 | 
			
		||||
      throw new AccessError("You do not have permission to read messages in this conference.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    // reorder parameters so they come in the correct order!
 | 
			
		||||
    if (low<=high)
 | 
			
		||||
      return TopicMessageUserContextImpl.loadMessageRange(engine,conf,datapool,topicid,low,high);
 | 
			
		||||
    else
 | 
			
		||||
      return TopicMessageUserContextImpl.loadMessageRange(engine,conf,datapool,topicid,high,low);
 | 
			
		||||
 | 
			
		||||
  } // end getMessages
 | 
			
		||||
 | 
			
		||||
  public TopicMessageContext postNewMessage(long parent, String pseud, String text)
 | 
			
		||||
      throws DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    if (!(conf.userCanPost()))
 | 
			
		||||
    { // they can't post in this topic!
 | 
			
		||||
      logger.error("trying to post w/o permission!");
 | 
			
		||||
      throw new AccessError("You do not have permission to post messages in this conference.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    if (deleted)
 | 
			
		||||
    { // the topic has been deleted
 | 
			
		||||
      logger.error("can't post to a deleted topic!");
 | 
			
		||||
      throw new AccessError("You cannot post to a topic that has been deleted.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    if (frozen && !(conf.userCanHide()))
 | 
			
		||||
    { // can't post to a frozen topic!
 | 
			
		||||
      logger.error("can't post to a frozen topic!");
 | 
			
		||||
      throw new AccessError("The topic is frozen, and you do not have permission to post to it.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    if (archived && !(conf.userCanHide()))
 | 
			
		||||
    { // can't post to a frozen topic!
 | 
			
		||||
      logger.error("can't post to an archived topic!");
 | 
			
		||||
      throw new AccessError("The topic is archived, and you do not have permission to post to it.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    // preprocess the two arguments through HTML checkers
 | 
			
		||||
    HTMLChecker pseud_ch = engine.createCheckerObject(engine.HTMLC_POST_PSEUD);
 | 
			
		||||
    HTMLChecker text_ch = engine.createCheckerObject(engine.HTMLC_POST_BODY);
 | 
			
		||||
    try
 | 
			
		||||
    { // run both arguments through the HTML checker
 | 
			
		||||
      pseud_ch.append(pseud);
 | 
			
		||||
      pseud_ch.finish();
 | 
			
		||||
      text_ch.append(text);
 | 
			
		||||
      text_ch.finish();
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (AlreadyFinishedException e)
 | 
			
		||||
    { // this isn't right...
 | 
			
		||||
      throw new InternalStateError("HTMLChecker erroneously throwing AlreadyFinishedException",e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
    String real_pseud, real_text;
 | 
			
		||||
    int text_linecount;
 | 
			
		||||
    try
 | 
			
		||||
    { // retrieve the processed values
 | 
			
		||||
      real_pseud = pseud_ch.getValue();
 | 
			
		||||
      real_text = text_ch.getValue();
 | 
			
		||||
      text_linecount = text_ch.getLines();
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NotYetFinishedException e)
 | 
			
		||||
    { // this isn't right either!
 | 
			
		||||
      throw new InternalStateError("HTMLChecker erroneously throwing NotYetFinishedException",e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
    int new_post_num;
 | 
			
		||||
    long new_post_id;
 | 
			
		||||
    java.util.Date posted_date;
 | 
			
		||||
    Connection conn = null;
 | 
			
		||||
    AuditRecord ar = null;
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // get a database connection
 | 
			
		||||
      conn = datapool.getConnection();
 | 
			
		||||
      Statement stmt = conn.createStatement();
 | 
			
		||||
 | 
			
		||||
      // slap a lock on all the tables we need to touch
 | 
			
		||||
      stmt.executeUpdate("LOCK TABLES confs WRITE, topics WRITE, posts WRITE, postdata WRITE, "
 | 
			
		||||
			 + "confsettings WRITE, topicsettings READ;");
 | 
			
		||||
 | 
			
		||||
      try
 | 
			
		||||
      { // refresh our current status and recheck allowed status
 | 
			
		||||
	refresh(conn);
 | 
			
		||||
	if (deleted)
 | 
			
		||||
	{ // the topic has been deleted
 | 
			
		||||
	  logger.error("can't post to a deleted topic!");
 | 
			
		||||
	  throw new AccessError("You cannot post to a topic that has been deleted.");
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
 | 
			
		||||
	if (frozen && !(conf.userCanHide()))
 | 
			
		||||
	{ // can't post to a frozen topic!
 | 
			
		||||
	  logger.error("can't post to a frozen topic!");
 | 
			
		||||
	  throw new AccessError("The topic is frozen, and you do not have permission to post to it.");
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
 | 
			
		||||
	if (archived && !(conf.userCanHide()))
 | 
			
		||||
	{ // can't post to a frozen topic!
 | 
			
		||||
	  logger.error("can't post to an archived topic!");
 | 
			
		||||
	  throw new AccessError("The topic is archived, and you do not have permission to post to it.");
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
 | 
			
		||||
	// Determine what the new post number is.
 | 
			
		||||
	new_post_num = top_message + 1;
 | 
			
		||||
 | 
			
		||||
	// Add the post "header" to the posts table.
 | 
			
		||||
	StringBuffer sql = new StringBuffer("INSERT INTO posts (parent, topicid, num, linecount, creator_uid, "
 | 
			
		||||
					    + "posted, pseud) VALUES (");
 | 
			
		||||
	sql.append(parent).append(", ").append(topicid).append(", ").append(new_post_num).append(", ");
 | 
			
		||||
	sql.append(text_linecount).append(", ").append(conf.realUID()).append(", '");
 | 
			
		||||
	posted_date = new java.util.Date();
 | 
			
		||||
	sql.append(SQLUtil.encodeDate(posted_date)).append("', '").append(real_pseud).append("');");
 | 
			
		||||
	if (logger.isDebugEnabled())
 | 
			
		||||
	  logger.debug("SQL: " + sql.toString());
 | 
			
		||||
	stmt.executeUpdate(sql.toString());
 | 
			
		||||
 | 
			
		||||
	// Retrieve the new post ID.
 | 
			
		||||
	ResultSet rs = stmt.executeQuery("SELECT LAST_INSERT_ID();");
 | 
			
		||||
	if (!(rs.next()))
 | 
			
		||||
	  throw new InternalStateError("postMessage(): Unable to get new post ID!");
 | 
			
		||||
	new_post_id = rs.getLong(1);
 | 
			
		||||
   
 | 
			
		||||
	// Touch the topic values to reflect the added post.
 | 
			
		||||
	sql.setLength(0);
 | 
			
		||||
	sql.append("UPDATE topics SET top_message = ").append(new_post_num).append(", lastupdate = '");
 | 
			
		||||
	sql.append(SQLUtil.encodeDate(posted_date)).append("' WHERE topicid = ").append(topicid).append(';');
 | 
			
		||||
	if (logger.isDebugEnabled())
 | 
			
		||||
	  logger.debug("SQL: " + sql.toString());
 | 
			
		||||
	stmt.executeUpdate(sql.toString());
 | 
			
		||||
 | 
			
		||||
	// insert the post data
 | 
			
		||||
	sql.setLength(0);
 | 
			
		||||
	sql.append("INSERT INTO postdata (postid, data) VALUES (").append(new_post_id).append(", '");
 | 
			
		||||
	sql.append(real_text).append("');");
 | 
			
		||||
	stmt.executeUpdate(sql.toString());
 | 
			
		||||
 | 
			
		||||
	// mark that we posted to the conference
 | 
			
		||||
	conf.touchUpdate(conn,posted_date);
 | 
			
		||||
	conf.touchPost(conn,posted_date);
 | 
			
		||||
 | 
			
		||||
	// fill in our own local variables to reflect the update
 | 
			
		||||
	top_message = new_post_num;
 | 
			
		||||
	lastupdate = posted_date;
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      finally
 | 
			
		||||
      { // make sure we unlock the tables when we're done
 | 
			
		||||
	Statement ulk_stmt = conn.createStatement();
 | 
			
		||||
	ulk_stmt.executeUpdate("UNLOCK TABLES;");
 | 
			
		||||
 | 
			
		||||
      } // end finally
 | 
			
		||||
 | 
			
		||||
      // record what we did in an audit record
 | 
			
		||||
      ar = new AuditRecord(AuditRecord.POST_MESSAGE,conf.realUID(),conf.userRemoteAddress(),
 | 
			
		||||
			   conf.realSIGID(),"conf=" + String.valueOf(conf.realConfID()) + ",topic="
 | 
			
		||||
			   + String.valueOf(topicid) + ",post=" + String.valueOf(new_post_id),
 | 
			
		||||
			   "pseud=" + real_pseud);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (SQLException e)
 | 
			
		||||
    { // turn SQLException into data exception
 | 
			
		||||
      logger.error("DB error posting message: " + e.getMessage(),e);
 | 
			
		||||
      throw new DataException("unable to post message: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    finally
 | 
			
		||||
    { // make sure we release the connection before we go
 | 
			
		||||
      try
 | 
			
		||||
      { // save off the audit record before we go, though
 | 
			
		||||
	if ((ar!=null) && (conn!=null))
 | 
			
		||||
	  ar.store(conn);
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (SQLException e)
 | 
			
		||||
      { // we couldn't store the audit record!
 | 
			
		||||
	logger.error("DB error saving audit record: " + e.getMessage(),e);
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
      if (conn!=null)
 | 
			
		||||
	datapool.releaseConnection(conn);
 | 
			
		||||
 | 
			
		||||
    } // end finally
 | 
			
		||||
 | 
			
		||||
    // return the new message context
 | 
			
		||||
    return new TopicMessageUserContextImpl(engine,conf,datapool,new_post_id,parent,new_post_num,
 | 
			
		||||
					   text_linecount,conf.realUID(),posted_date,real_pseud);
 | 
			
		||||
 | 
			
		||||
  } // end postMessage
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * External operations usable only from within the package
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ class DictNode
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private static final int[] permute_tab =
 | 
			
		||||
    { 7, 21, 12, 9, 1, 13, 18, 10, 5, 25, 23, 11, 16, 3, 6, 14, 24, 4, 8, 2, 15, 20, 19, 22, 17, 26 };
 | 
			
		||||
    { 8, 22, 13, 10, 2, 14, 19, 11, 6, 26, 24, 12, 17, 4, 7, 15, 25, 5, 9, 3, 16, 21, 20, 23, 18, 27 };
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Attributes
 | 
			
		||||
@ -53,6 +53,8 @@ class DictNode
 | 
			
		||||
  {
 | 
			
		||||
    if (ltr=='-')
 | 
			
		||||
      return 0;
 | 
			
		||||
    else if (ltr=='\'')
 | 
			
		||||
      return 1;
 | 
			
		||||
    else
 | 
			
		||||
      return permute_tab[ltr - 'a'];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -41,6 +41,62 @@ public class TreeLexicon implements ModSpellingDictionary
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Internal functions
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private boolean checkSimple(String word)
 | 
			
		||||
  {
 | 
			
		||||
    DictNode cur = root;
 | 
			
		||||
    for (int i=0; i<word.length(); i++)
 | 
			
		||||
    { // loop through the characters and move down the trie
 | 
			
		||||
      char ch = word.charAt(i);
 | 
			
		||||
      if (((ch<'a') || (ch>'z')) && (ch!='-') && (ch!='\''))
 | 
			
		||||
	return false;
 | 
			
		||||
      cur = cur.getRef(ch);
 | 
			
		||||
      if (cur==null)
 | 
			
		||||
	return false;
 | 
			
		||||
 | 
			
		||||
    } // end for
 | 
			
		||||
 | 
			
		||||
    return cur.isTerminal();
 | 
			
		||||
 | 
			
		||||
  } // end checkSimple
 | 
			
		||||
 | 
			
		||||
  private boolean checkHyphenates(String word)
 | 
			
		||||
  {
 | 
			
		||||
    if (word.indexOf('-')<0)
 | 
			
		||||
      return false;  // non-hyphenated
 | 
			
		||||
 | 
			
		||||
    int st = 0;
 | 
			
		||||
    int p;
 | 
			
		||||
    boolean ok = true;
 | 
			
		||||
    do
 | 
			
		||||
    { // break the word up into hyphenated compounds
 | 
			
		||||
      p = word.indexOf('-',st);
 | 
			
		||||
      String frag;
 | 
			
		||||
      if (p>=0)
 | 
			
		||||
      { // get the middle fragment of the word
 | 
			
		||||
	frag = word.substring(st,p);
 | 
			
		||||
	st = p + 1;
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
      else  // get it from the end
 | 
			
		||||
	frag = word.substring(st);
 | 
			
		||||
 | 
			
		||||
      // check this fragment...
 | 
			
		||||
      if (frag.length()<=1)
 | 
			
		||||
	ok = true;   // fragments of length 0 or 1 are always OK
 | 
			
		||||
      else  // anything else goes through checkSimple
 | 
			
		||||
	ok = checkSimple(frag);
 | 
			
		||||
 | 
			
		||||
    } while (ok && (p>=0));
 | 
			
		||||
 | 
			
		||||
    return ok;
 | 
			
		||||
 | 
			
		||||
  } // end checkHyphenates
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface SpellingDictionary
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -54,20 +110,22 @@ public class TreeLexicon implements ModSpellingDictionary
 | 
			
		||||
 | 
			
		||||
  public synchronized boolean checkWord(String word)
 | 
			
		||||
  {
 | 
			
		||||
    if (word.length()<=1)
 | 
			
		||||
      return true;  // words of length 1 get a free pass
 | 
			
		||||
    String real_word = word.toLowerCase();
 | 
			
		||||
    DictNode cur = root;
 | 
			
		||||
    for (int i=0; i<real_word.length(); i++)
 | 
			
		||||
    { // loop through the characters and move down the trie
 | 
			
		||||
      char ch = real_word.charAt(i);
 | 
			
		||||
      if (((ch<'a') || (ch>'z')) && (ch!='-'))
 | 
			
		||||
	return false;
 | 
			
		||||
      cur = cur.getRef(ch);
 | 
			
		||||
      if (cur==null)
 | 
			
		||||
	return false;
 | 
			
		||||
    if (checkSimple(real_word))
 | 
			
		||||
      return true;  // word is in lexicon - we're OK to go
 | 
			
		||||
 | 
			
		||||
    } // end for
 | 
			
		||||
    if ((real_word.indexOf('\'')==(real_word.length()-2)) && (real_word.charAt(real_word.length()-1)=='s'))
 | 
			
		||||
    { // drop the apostrophe-s from the end of the word and retry
 | 
			
		||||
      String base = real_word.substring(0,real_word.length()-2);
 | 
			
		||||
      if (checkSimple(base))
 | 
			
		||||
	return true;
 | 
			
		||||
      return checkHyphenates(base);
 | 
			
		||||
 | 
			
		||||
    return cur.isTerminal();
 | 
			
		||||
    } // end if
 | 
			
		||||
    else // try hyphenated forms
 | 
			
		||||
      return checkHyphenates(real_word);
 | 
			
		||||
 | 
			
		||||
  } // end checkWord
 | 
			
		||||
 | 
			
		||||
@ -83,7 +141,7 @@ public class TreeLexicon implements ModSpellingDictionary
 | 
			
		||||
    for (int i=0; i<real_word.length(); i++)
 | 
			
		||||
    { // move through the word - bail out if bogus chars
 | 
			
		||||
      char ch = real_word.charAt(i);
 | 
			
		||||
      if (((ch<'a') || (ch>'z')) && (ch!='-'))
 | 
			
		||||
      if (((ch<'a') || (ch>'z')) && (ch!='-') && (ch!='\''))
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
      // advance down through trie
 | 
			
		||||
 | 
			
		||||
@ -79,6 +79,13 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic
 | 
			
		||||
  private static final short ST_PAREN = 4;
 | 
			
		||||
  private static final short ST_TAGQUOTE = 5;
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Internal constants
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private static final int MARGIN_SLOP = 5;
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Attributes
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -127,17 +134,17 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic
 | 
			
		||||
 | 
			
		||||
  private static final boolean isWordChar(char ch)
 | 
			
		||||
  {
 | 
			
		||||
    return (Character.isUpperCase(ch) || Character.isLowerCase(ch) || (ch=='-'));
 | 
			
		||||
    return (Character.isUpperCase(ch) || Character.isLowerCase(ch) || (ch=='-') || (ch=='\''));
 | 
			
		||||
 | 
			
		||||
  } // end isWordChar
 | 
			
		||||
 | 
			
		||||
  private static final int getRunLength(StringBuffer buf)
 | 
			
		||||
  private static final int getRunLength(StringBuffer buf, int start)
 | 
			
		||||
  {
 | 
			
		||||
    boolean word_char = isWordChar(buf.charAt(0));
 | 
			
		||||
    boolean word_char = isWordChar(buf.charAt(start));
 | 
			
		||||
    int l = 1;
 | 
			
		||||
    while (l<buf.length())
 | 
			
		||||
    { // see if there's a break from word characters to non-word characters
 | 
			
		||||
      if (isWordChar(buf.charAt(l))!=word_char)
 | 
			
		||||
    while ((start+l)<buf.length())
 | 
			
		||||
    { // see if there's a break from word characters to non-word characters, or vice versa
 | 
			
		||||
      if (isWordChar(buf.charAt(start+l))!=word_char)
 | 
			
		||||
	break;
 | 
			
		||||
      l++;
 | 
			
		||||
 | 
			
		||||
@ -145,7 +152,13 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic
 | 
			
		||||
 | 
			
		||||
    return l;
 | 
			
		||||
 | 
			
		||||
  } // end getStringRunLength
 | 
			
		||||
  } // end getRunLength
 | 
			
		||||
 | 
			
		||||
  private static final int getRunLength(StringBuffer buf)
 | 
			
		||||
  {
 | 
			
		||||
    return getRunLength(buf,0);
 | 
			
		||||
 | 
			
		||||
  } // end getRunLength
 | 
			
		||||
 | 
			
		||||
  private void copyRewriters(Vector dest, List source)
 | 
			
		||||
  {
 | 
			
		||||
@ -343,6 +356,7 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic
 | 
			
		||||
    { // calculate where the next line break is
 | 
			
		||||
      int line_break = temp_buffer.toString().indexOf('\n');
 | 
			
		||||
      int output_len = line_break;
 | 
			
		||||
      boolean force_line_break = false;
 | 
			
		||||
      if (output_len<0)
 | 
			
		||||
	output_len = temp_buffer.length();
 | 
			
		||||
 | 
			
		||||
@ -351,6 +365,8 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic
 | 
			
		||||
	int remain_space = (int)(config.getWordWrapLength() - columns);
 | 
			
		||||
	if (remain_space<output_len)
 | 
			
		||||
	  output_len = remain_space;
 | 
			
		||||
	if (output_len<=0)  // this means that NONE of the whitespace would fit on this line...
 | 
			
		||||
	  force_line_break = true;  // we need a line break to fill in!
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
 | 
			
		||||
@ -366,9 +382,14 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic
 | 
			
		||||
	  temp_buffer.setLength(0);
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
      else // no more line breaks on this line - clear out the buffer
 | 
			
		||||
      else
 | 
			
		||||
      { // no more line breaks on this line - clear out the buffer
 | 
			
		||||
	if (force_line_break)
 | 
			
		||||
	  emitLineBreak();  // notice we can only force a line break if we didn't have one in the text
 | 
			
		||||
	temp_buffer.setLength(0);
 | 
			
		||||
 | 
			
		||||
      } // end else
 | 
			
		||||
 | 
			
		||||
    } // end while (still data in temp buffer)
 | 
			
		||||
 | 
			
		||||
  } // end doFlushWhitespace
 | 
			
		||||
@ -418,23 +439,25 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    boolean first = true;
 | 
			
		||||
    while (temp_buffer.length()>0)
 | 
			
		||||
    { // find the length of the initial string of word or non-word characters
 | 
			
		||||
      int sublen = getRunLength(temp_buffer);
 | 
			
		||||
 | 
			
		||||
      if (isWordChar(temp_buffer.charAt(0)))
 | 
			
		||||
      { // we need to check the word...but first, we must eliminate leading hyphens
 | 
			
		||||
      { // we need to check the word...but first, we must eliminate leading hyphens and apostrophes
 | 
			
		||||
	int hyph_count = 0;
 | 
			
		||||
	while ((hyph_count<sublen) && (temp_buffer.charAt(hyph_count)=='-'))
 | 
			
		||||
	final String hyph_apos = "-\'";
 | 
			
		||||
	while ((hyph_count<sublen) && (hyph_apos.indexOf(temp_buffer.charAt(hyph_count))>=0))
 | 
			
		||||
	  hyph_count++;
 | 
			
		||||
	emitFromStartOfTempBuffer(hyph_count);
 | 
			
		||||
	sublen -= hyph_count;
 | 
			
		||||
 | 
			
		||||
	// now determine how many hyphens there are at the end of the word...
 | 
			
		||||
	// now determine how many hyphens/apostrophes there are at the end of the word...
 | 
			
		||||
	int word_len = sublen;
 | 
			
		||||
	hyph_count = 0;
 | 
			
		||||
	while ((word_len>0) && (temp_buffer.charAt(word_len-1)=='-'))
 | 
			
		||||
	{ // decrement word length, increment hyphen count
 | 
			
		||||
	while ((word_len>0) && (hyph_apos.indexOf(temp_buffer.charAt(word_len-1))>=0))
 | 
			
		||||
	{ // decrement word length, increment hyphen/apostrophe count
 | 
			
		||||
	  hyph_count++;
 | 
			
		||||
	  word_len--;
 | 
			
		||||
 | 
			
		||||
@ -458,13 +481,39 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
 | 
			
		||||
	// now emit the rest of the hyphens
 | 
			
		||||
	// now emit the rest of the hyphens/apostrophes
 | 
			
		||||
	emitFromStartOfTempBuffer(hyph_count);
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
      else // just emit this many characters, line-breaking where required
 | 
			
		||||
      else
 | 
			
		||||
      { // just emit this many characters, line-breaking where required
 | 
			
		||||
	if ((sublen==temp_buffer.length()) && !first && (sublen<=MARGIN_SLOP))
 | 
			
		||||
        { // This is intended to handle a small run of non-word characters at the end of a string (i.e.
 | 
			
		||||
	  // followed by whitespace) that should stay on the same line with its preceding word, to
 | 
			
		||||
	  // eliminate "funnies" in punctuation formatting.
 | 
			
		||||
	  emitString(temp_buffer.toString(),config.getOutputFilters(),true);
 | 
			
		||||
	  temp_buffer.setLength(0);
 | 
			
		||||
	  break;
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
 | 
			
		||||
	// This is kind of the inverse of the above check; if we have a small run of non-word
 | 
			
		||||
	// characters at the START of a word (preceded by whitespace and followed by at least
 | 
			
		||||
	// one word character), then ensure that we can keep that word and its prefixing non-word
 | 
			
		||||
	// characters on the same line (again, avoiding "funnies" in formatting).
 | 
			
		||||
	if ((sublen<temp_buffer.length()) && first && (sublen<=MARGIN_SLOP))
 | 
			
		||||
	{ // get the length of the word and ensure they can be kept together
 | 
			
		||||
	  int fw_len = getRunLength(temp_buffer,sublen);
 | 
			
		||||
	  ensureSpaceOnLine(sublen+fw_len);
 | 
			
		||||
 | 
			
		||||
        } // end if
 | 
			
		||||
 | 
			
		||||
	emitFromStartOfTempBuffer(sublen);
 | 
			
		||||
 | 
			
		||||
      } // end else
 | 
			
		||||
 | 
			
		||||
      first = false;
 | 
			
		||||
 | 
			
		||||
    } // end while
 | 
			
		||||
 | 
			
		||||
  } // end doFlushString
 | 
			
		||||
@ -884,7 +933,8 @@ class HTMLCheckerImpl implements HTMLChecker, HTMLCheckerBackend, RewriterServic
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    parse(str);  // parse things
 | 
			
		||||
    if (str!=null)
 | 
			
		||||
      parse(str);  // parse things
 | 
			
		||||
 | 
			
		||||
  } // end append
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -54,5 +54,9 @@ public interface Audit
 | 
			
		||||
  public static final int DELETE_TOPIC = 307;
 | 
			
		||||
  public static final int TOPIC_FREEZE = 308;
 | 
			
		||||
  public static final int TOPIC_ARCHIVE = 309;
 | 
			
		||||
  public static final int POST_MESSAGE = 310;
 | 
			
		||||
  public static final int HIDE_MESSAGE = 311;
 | 
			
		||||
  public static final int SCRIBBLE_MESSAGE = 312;
 | 
			
		||||
  public static final int NUKE_MESSAGE = 313;
 | 
			
		||||
 | 
			
		||||
} // end interface Audit
 | 
			
		||||
 | 
			
		||||
@ -29,6 +29,47 @@ import com.silverwrist.venice.servlets.format.*;
 | 
			
		||||
 | 
			
		||||
public class ConfDisplay extends VeniceServlet
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Internal class used to get post number defaults
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  static class PostInterval
 | 
			
		||||
  {
 | 
			
		||||
    private int first;
 | 
			
		||||
    private int last;
 | 
			
		||||
 | 
			
		||||
    public PostInterval(int f, int l)
 | 
			
		||||
    {
 | 
			
		||||
      if (f<=l)
 | 
			
		||||
      { // the sort is good
 | 
			
		||||
	first = f;
 | 
			
		||||
	last = l;
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
      else
 | 
			
		||||
      { // reverse the order
 | 
			
		||||
	first = l;
 | 
			
		||||
	last = f;
 | 
			
		||||
 | 
			
		||||
      } // end else
 | 
			
		||||
 | 
			
		||||
    } // end constructor
 | 
			
		||||
 | 
			
		||||
    public int getFirst()
 | 
			
		||||
    {
 | 
			
		||||
      return first;
 | 
			
		||||
 | 
			
		||||
    } // end getFirst
 | 
			
		||||
 | 
			
		||||
    public int getLast()
 | 
			
		||||
    {
 | 
			
		||||
      return last;
 | 
			
		||||
 | 
			
		||||
    } // end getLast
 | 
			
		||||
 | 
			
		||||
  } // end class PostInterval
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static data members
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -183,6 +224,106 @@ public class ConfDisplay extends VeniceServlet
 | 
			
		||||
 | 
			
		||||
  } // end getViewSortDefaults
 | 
			
		||||
 | 
			
		||||
  private static PostInterval getInterval(ServletRequest request, TopicContext topic)
 | 
			
		||||
     throws ValidationException
 | 
			
		||||
  {
 | 
			
		||||
    int first, last;
 | 
			
		||||
 | 
			
		||||
    String foo = request.getParameter("pxg");
 | 
			
		||||
    if (!(StringUtil.isStringEmpty(foo)))
 | 
			
		||||
    { // we have a Go box parameter - try and decode it
 | 
			
		||||
      try
 | 
			
		||||
      { // look for a range specifier
 | 
			
		||||
	int p = foo.indexOf('-');
 | 
			
		||||
	if (p<0)
 | 
			
		||||
	{ // single post number - try and use it
 | 
			
		||||
	  first = Integer.parseInt(foo);
 | 
			
		||||
	  last = first;
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
	else if (p==0)
 | 
			
		||||
	{ // "-number" - works like "0-number"
 | 
			
		||||
	  last = Integer.parseInt(foo.substring(1));
 | 
			
		||||
	  first = 0;
 | 
			
		||||
 | 
			
		||||
	} // end if
 | 
			
		||||
	else if (p==(foo.length()-1))
 | 
			
		||||
	{ // "number-" - works like "number-end"
 | 
			
		||||
	  first = Integer.parseInt(foo.substring(0,p));
 | 
			
		||||
	  last = topic.getTotalMessages() - 1;
 | 
			
		||||
 | 
			
		||||
	} // end else if
 | 
			
		||||
	else
 | 
			
		||||
	{ // two numbers to decode
 | 
			
		||||
	  first = Integer.parseInt(foo.substring(0,p));
 | 
			
		||||
	  last = Integer.parseInt(foo.substring(p+1));
 | 
			
		||||
 | 
			
		||||
	} // end else
 | 
			
		||||
 | 
			
		||||
	return new PostInterval(first,last);
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (NumberFormatException nfe)
 | 
			
		||||
      { // if numeric conversion fails, just fall out and try to redisplay the other way
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    foo = request.getParameter("p1");
 | 
			
		||||
    if (StringUtil.isStringEmpty(foo))
 | 
			
		||||
    { // no range specified - cook up a default one
 | 
			
		||||
      last = topic.getTotalMessages();
 | 
			
		||||
      int ur = topic.getUnreadMessages();
 | 
			
		||||
      if ((ur==0) || (ur>=20))  // TODO: configurable
 | 
			
		||||
	first = last - 20;
 | 
			
		||||
      else
 | 
			
		||||
	first = last - (ur+2);
 | 
			
		||||
      last--;
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
    else
 | 
			
		||||
    { // we have at least one parameter...
 | 
			
		||||
      try
 | 
			
		||||
      { // convert it to an integer and range-limit it
 | 
			
		||||
	first = Integer.parseInt(foo);
 | 
			
		||||
	if (first<0)
 | 
			
		||||
	  first = 0;
 | 
			
		||||
	else if (first>=topic.getTotalMessages())
 | 
			
		||||
	  first = topic.getTotalMessages() - 1;
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (NumberFormatException nfe)
 | 
			
		||||
      { // we could not translate the parameter to a number
 | 
			
		||||
	throw new ValidationException("Message parameter is invalid.");
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
      foo = request.getParameter("p2");
 | 
			
		||||
      if (StringUtil.isStringEmpty(foo))
 | 
			
		||||
        last = first;  // just specify ONE post...
 | 
			
		||||
      else
 | 
			
		||||
      { // OK, we have an actual "last message" parameter...
 | 
			
		||||
	try
 | 
			
		||||
	{ // convert it to an integer and range-limit it
 | 
			
		||||
	  last = Integer.parseInt(foo);
 | 
			
		||||
	  if ((last<0) || (last>=topic.getTotalMessages()))
 | 
			
		||||
	    last = topic.getTotalMessages() - 1;
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (NumberFormatException nfe)
 | 
			
		||||
	{ // we could not translate the parameter to a number
 | 
			
		||||
	  throw new ValidationException("Message parameter is invalid.");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end else
 | 
			
		||||
 | 
			
		||||
    } // end else
 | 
			
		||||
 | 
			
		||||
    return new PostInterval(first,last);
 | 
			
		||||
 | 
			
		||||
  } // end getInterval
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Overrides from class HttpServlet
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
@ -287,7 +428,39 @@ public class ConfDisplay extends VeniceServlet
 | 
			
		||||
	if (logger.isDebugEnabled())
 | 
			
		||||
	  logger.debug("MODE: display messages in topic");
 | 
			
		||||
 | 
			
		||||
	// TODO: handle this somehow
 | 
			
		||||
	try
 | 
			
		||||
	{ // determine what the post interval is we want to display
 | 
			
		||||
	  PostInterval piv = getInterval(request,topic);
 | 
			
		||||
	  boolean read_new = !(StringUtil.isStringEmpty(request.getParameter("rnm")));
 | 
			
		||||
	  boolean show_adv = !(StringUtil.isStringEmpty(request.getParameter("shac")));
 | 
			
		||||
 | 
			
		||||
	  // create the post display
 | 
			
		||||
	  TopicPosts tpos = new TopicPosts(request,sig,conf,topic,piv.getFirst(),piv.getLast(),
 | 
			
		||||
                                           read_new,show_adv);
 | 
			
		||||
	  content = tpos;
 | 
			
		||||
	  page_title = topic.getName() + ": " + String.valueOf(topic.getTotalMessages()) + " Total; "
 | 
			
		||||
                     + String.valueOf(tpos.getNewMessages()) + " New; Last: "
 | 
			
		||||
                     + rdat.formatDateForDisplay(topic.getLastUpdateDate());
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (ValidationException ve)
 | 
			
		||||
	{ // there's an error in the parameters somewhere
 | 
			
		||||
	  page_title = "Error";
 | 
			
		||||
	  content = new ErrorBox(null,ve.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // there was a database error retrieving topics
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error listing messages: " + de.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	catch (AccessError ae)
 | 
			
		||||
	{ // we were unable to retrieve the topic list
 | 
			
		||||
	  page_title = "Access Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,ae.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
      else
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										414
									
								
								src/com/silverwrist/venice/servlets/PostMessage.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,414 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 | 
			
		||||
 * (the "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 * 
 | 
			
		||||
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 | 
			
		||||
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 | 
			
		||||
 * language governing rights and limitations under the License.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Original Code is the Venice Web Communities System.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
 * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 | 
			
		||||
 * 
 | 
			
		||||
 * Contributor(s): 
 | 
			
		||||
 */
 | 
			
		||||
package com.silverwrist.venice.servlets;
 | 
			
		||||
 | 
			
		||||
import java.io.*;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import javax.servlet.*;
 | 
			
		||||
import javax.servlet.http.*;
 | 
			
		||||
import org.apache.log4j.*;
 | 
			
		||||
import com.silverwrist.util.StringUtil;
 | 
			
		||||
import com.silverwrist.venice.ValidationException;
 | 
			
		||||
import com.silverwrist.venice.core.*;
 | 
			
		||||
import com.silverwrist.venice.servlets.format.*;
 | 
			
		||||
 | 
			
		||||
public class PostMessage extends VeniceServlet
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static data members
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private static Category logger = Category.getInstance(PostMessage.class.getName());
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Internal functions
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private static SIGContext getSIGParameter(ServletRequest request, UserContext user)
 | 
			
		||||
      throws ValidationException, DataException
 | 
			
		||||
  {
 | 
			
		||||
    String str = request.getParameter("sig");
 | 
			
		||||
    if (str==null)
 | 
			
		||||
    { // no SIG parameter - bail out now!
 | 
			
		||||
      logger.error("SIG parameter not specified!");
 | 
			
		||||
      throw new ValidationException("No SIG specified.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // turn the string into a SIGID, and thence to a SIGContext
 | 
			
		||||
      int sigid = Integer.parseInt(str);
 | 
			
		||||
      return user.getSIGContext(sigid);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // error in Integer.parseInt
 | 
			
		||||
      logger.error("Cannot convert SIG parameter '" + str + "'!");
 | 
			
		||||
      throw new ValidationException("Invalid SIG parameter.");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getSIGParameter
 | 
			
		||||
 | 
			
		||||
  private static ConferenceContext getConferenceParameter(ServletRequest request, SIGContext sig)
 | 
			
		||||
    throws ValidationException, DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    String str = request.getParameter("conf");
 | 
			
		||||
    if (str==null)
 | 
			
		||||
    { // no conference parameter - bail out now!
 | 
			
		||||
      logger.error("Conference parameter not specified!");
 | 
			
		||||
      throw new ValidationException("No conference specified.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // turn the string into a ConfID, and thence to a ConferenceContext
 | 
			
		||||
      int confid = Integer.parseInt(str);
 | 
			
		||||
      return sig.getConferenceContext(confid);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // error in Integer.parseInt
 | 
			
		||||
      logger.error("Cannot convert conference parameter '" + str + "'!");
 | 
			
		||||
      throw new ValidationException("Invalid conference parameter.");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getConferenceParameter
 | 
			
		||||
 | 
			
		||||
  private static TopicContext getTopicParameter(ServletRequest request, ConferenceContext conf)
 | 
			
		||||
    throws ValidationException, DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    String str = request.getParameter("top");
 | 
			
		||||
    if (StringUtil.isStringEmpty(str))
 | 
			
		||||
    { // no topic parameter - bail out now!
 | 
			
		||||
      logger.error("Topic parameter not specified!");
 | 
			
		||||
      throw new ValidationException("No topic specified.");
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // turn the string into a TopicID, and thence to a TopicContext
 | 
			
		||||
      short topicid = Short.parseShort(str);
 | 
			
		||||
      return conf.getTopic(topicid);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // error in Integer.parseInt
 | 
			
		||||
      logger.error("Cannot convert topic parameter '" + str + "'!");
 | 
			
		||||
      throw new ValidationException("Invalid topic parameter.");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getTopicParameter
 | 
			
		||||
 | 
			
		||||
  private static int getPostNumber(ServletRequest request) throws ValidationException
 | 
			
		||||
  {
 | 
			
		||||
    String str = request.getParameter("sd");
 | 
			
		||||
    if (StringUtil.isStringEmpty(str))
 | 
			
		||||
      throw new ValidationException("Invalid parameter.");
 | 
			
		||||
    try
 | 
			
		||||
    { // get the number of posts we think he topic has
 | 
			
		||||
      return Integer.parseInt(str);
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (NumberFormatException nfe)
 | 
			
		||||
    { // not a good integer...
 | 
			
		||||
      throw new ValidationException("Invalid parameter.");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getPostNumber
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Overrides from class HttpServlet
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public String getServletInfo()
 | 
			
		||||
  {
 | 
			
		||||
    String rc = "PostMessage servlet - Handles posting messages to a conference\n"
 | 
			
		||||
              + "Part of the Venice Web Communities System\n";
 | 
			
		||||
    return rc;
 | 
			
		||||
 | 
			
		||||
  } // end getServletInfo
 | 
			
		||||
 | 
			
		||||
  public void doPost(HttpServletRequest request, HttpServletResponse response)
 | 
			
		||||
    throws ServletException, IOException
 | 
			
		||||
  {
 | 
			
		||||
    UserContext user = getUserContext(request);
 | 
			
		||||
    RenderData rdat = createRenderData(request,response);
 | 
			
		||||
    String page_title = null;
 | 
			
		||||
    Object content = null;
 | 
			
		||||
    SIGContext sig = null;            // SIG context
 | 
			
		||||
    ConferenceContext conf = null;    // conference context
 | 
			
		||||
    TopicContext topic = null;        // topic context
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // this outer try is to catch ValidationException
 | 
			
		||||
      try
 | 
			
		||||
      { // all commands require a SIG parameter
 | 
			
		||||
	sig = getSIGParameter(request,user);
 | 
			
		||||
	changeMenuSIG(request,sig);
 | 
			
		||||
	if (logger.isDebugEnabled())
 | 
			
		||||
	  logger.debug("found SIG #" + String.valueOf(sig.getSIGID()));
 | 
			
		||||
 | 
			
		||||
      } // end try
 | 
			
		||||
      catch (DataException de)
 | 
			
		||||
      { // error looking up the SIG
 | 
			
		||||
	page_title = "Database Error";
 | 
			
		||||
	content = new ErrorBox(page_title,"Database error finding SIG: " + de.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
      } // end catch
 | 
			
		||||
 | 
			
		||||
      if (content==null)
 | 
			
		||||
      { // we got the SIG parameter OK
 | 
			
		||||
	try
 | 
			
		||||
	{ // all commands require a conference parameter
 | 
			
		||||
	  conf = getConferenceParameter(request,sig);
 | 
			
		||||
	  if (logger.isDebugEnabled())
 | 
			
		||||
	    logger.debug("found conf #" + String.valueOf(conf.getConfID()));
 | 
			
		||||
	  
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // error looking up the conference
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error finding conference: " + de.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
 | 
			
		||||
      if (content==null)
 | 
			
		||||
      { // we got the conference parameter OK
 | 
			
		||||
	try
 | 
			
		||||
	{ // now we need a topic parameter
 | 
			
		||||
	  topic = getTopicParameter(request,conf);
 | 
			
		||||
	  if (logger.isDebugEnabled())
 | 
			
		||||
	    logger.debug("found topic #" + String.valueOf(topic.getTopicID()));
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // error looking up the conference
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error finding topic: " + de.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (ValidationException ve)
 | 
			
		||||
    { // these all get handled in pretty much the same way
 | 
			
		||||
      page_title = "Error";
 | 
			
		||||
      content = new ErrorBox(null,ve.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
    catch (AccessError ae)
 | 
			
		||||
    { // these all get handled in pretty much the same way
 | 
			
		||||
      page_title = "Access Error";
 | 
			
		||||
      content = new ErrorBox(page_title,ae.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
    if (content==null)
 | 
			
		||||
    { // make sure we've got some post data
 | 
			
		||||
      String raw_postdata = request.getParameter("pb");
 | 
			
		||||
      if (StringUtil.isStringEmpty(raw_postdata))
 | 
			
		||||
      { // don't allow zero-size posts
 | 
			
		||||
	rdat.nullResponse();
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
      } // end if
 | 
			
		||||
 | 
			
		||||
      final String yes = "Y";
 | 
			
		||||
 | 
			
		||||
      // now decide what to do based on which button got clicked
 | 
			
		||||
      if (isImageButtonClicked(request,"cancel"))
 | 
			
		||||
      { // canceled posting - take us back to familiar ground
 | 
			
		||||
	rdat.redirectTo("confdisp?sig=" + String.valueOf(sig.getSIGID()) + "&conf="
 | 
			
		||||
                        + String.valueOf(conf.getConfID()) + "&top="
 | 
			
		||||
                        + String.valueOf(topic.getTopicNumber()));
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
      } // end if ("Cancel")
 | 
			
		||||
      else if (isImageButtonClicked(request,"preview"))
 | 
			
		||||
      { // previewing the post!
 | 
			
		||||
	try
 | 
			
		||||
	{ // generate a preview view
 | 
			
		||||
	  content = new PostPreview(getVeniceEngine(),sig,conf,topic,request.getParameter("pseud"),
 | 
			
		||||
                                    raw_postdata,request.getParameter("next"),getPostNumber(request),
 | 
			
		||||
				    yes.equals(request.getParameter("attach")));
 | 
			
		||||
	  page_title = "Previewing Post";
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (ValidationException ve)
 | 
			
		||||
	{ // there was some sort of a parameter error in the display (getPostNumber can throw this)
 | 
			
		||||
	  page_title = "Error";
 | 
			
		||||
	  content = new ErrorBox(null,ve.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end else if ("Preview & Spellcheck")
 | 
			
		||||
      else if (isImageButtonClicked(request,"post"))
 | 
			
		||||
      { // post the message, and then reload the same topic
 | 
			
		||||
	try
 | 
			
		||||
	{ // first, check against slippage
 | 
			
		||||
	  int pn = getPostNumber(request);
 | 
			
		||||
	  if (pn==topic.getTotalMessages())
 | 
			
		||||
	  { // no slippage - post the message!!!
 | 
			
		||||
	    TopicMessageContext msg = topic.postNewMessage(0,request.getParameter("pseud"),raw_postdata);
 | 
			
		||||
	    if (yes.equals(request.getParameter("attach")))
 | 
			
		||||
	    { // we have an attachment to upload...
 | 
			
		||||
	      // TODO: do something to upload the attachment
 | 
			
		||||
	      rdat.redirectTo("confdisp?sig=" + String.valueOf(sig.getSIGID()) + "&conf="
 | 
			
		||||
			      + String.valueOf(conf.getConfID()) + "&top="
 | 
			
		||||
			      + String.valueOf(topic.getTopicNumber()) + "&rnm=1");
 | 
			
		||||
	      return;
 | 
			
		||||
 | 
			
		||||
	    } // end if
 | 
			
		||||
	    else
 | 
			
		||||
	    { // no attachment - jump back to the topic
 | 
			
		||||
	      rdat.redirectTo("confdisp?sig=" + String.valueOf(sig.getSIGID()) + "&conf="
 | 
			
		||||
			      + String.valueOf(conf.getConfID()) + "&top="
 | 
			
		||||
			      + String.valueOf(topic.getTopicNumber()) + "&rnm=1");
 | 
			
		||||
	      return;
 | 
			
		||||
 | 
			
		||||
	    } // end else
 | 
			
		||||
 | 
			
		||||
	  } // end if
 | 
			
		||||
	  else
 | 
			
		||||
	  { // slippage detected - show the slippage display
 | 
			
		||||
	    content = new PostSlippage(getVeniceEngine(),sig,conf,topic,pn,request.getParameter("next"),
 | 
			
		||||
				       request.getParameter("pseud"),raw_postdata,
 | 
			
		||||
                                       yes.equals(request.getParameter("attach")));
 | 
			
		||||
	    page_title = "Slippage or Double-Click Detected";
 | 
			
		||||
 | 
			
		||||
	  } // end else
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (ValidationException ve)
 | 
			
		||||
	{ // there was some sort of a parameter error in the display
 | 
			
		||||
	  page_title = "Error";
 | 
			
		||||
	  content = new ErrorBox(null,ve.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // there was a database error posting the message
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error posting message: " + de.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	catch (AccessError ae)
 | 
			
		||||
	{ // we were unable to retrieve the topic list
 | 
			
		||||
	  page_title = "Access Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,ae.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end else if ("Post & Reload")
 | 
			
		||||
      else if (isImageButtonClicked(request,"postnext"))
 | 
			
		||||
      { // post the message, and then go to the "next" topic
 | 
			
		||||
	try
 | 
			
		||||
	{ // first, check against slippage
 | 
			
		||||
	  int pn = getPostNumber(request);
 | 
			
		||||
	  if (pn==topic.getTotalMessages())
 | 
			
		||||
	  { // no slippage - post the message!
 | 
			
		||||
	    TopicMessageContext msg = topic.postNewMessage(0,request.getParameter("pseud"),raw_postdata);
 | 
			
		||||
 | 
			
		||||
	    short next;
 | 
			
		||||
	    try
 | 
			
		||||
	    { // attempt to get the value of the "next topic" parameter
 | 
			
		||||
	      String foo = request.getParameter("next");
 | 
			
		||||
	      if (StringUtil.isStringEmpty(foo))
 | 
			
		||||
		next = topic.getTopicNumber();
 | 
			
		||||
	      else
 | 
			
		||||
		next = Short.parseShort(foo);
 | 
			
		||||
 | 
			
		||||
	    } // end try
 | 
			
		||||
	    catch (NumberFormatException nfe)
 | 
			
		||||
	    { // just default me
 | 
			
		||||
	      next = topic.getTopicNumber();
 | 
			
		||||
 | 
			
		||||
	    } // end catch
 | 
			
		||||
 | 
			
		||||
	    if (yes.equals(request.getParameter("attach")))
 | 
			
		||||
	    { // we have an attachment to upload...
 | 
			
		||||
	      // TODO: jump somewhere we can upload the attachment!
 | 
			
		||||
	      rdat.redirectTo("confdisp?sig=" + String.valueOf(sig.getSIGID()) + "&conf="
 | 
			
		||||
			      + String.valueOf(conf.getConfID()) + "&top=" + String.valueOf(next) + "&rnm=1");
 | 
			
		||||
	      return;
 | 
			
		||||
 | 
			
		||||
	    } // end if
 | 
			
		||||
	    else
 | 
			
		||||
	    { // no attachment - jump to the next topic
 | 
			
		||||
	      rdat.redirectTo("confdisp?sig=" + String.valueOf(sig.getSIGID()) + "&conf="
 | 
			
		||||
			      + String.valueOf(conf.getConfID()) + "&top=" + String.valueOf(next) + "&rnm=1");
 | 
			
		||||
	      return;
 | 
			
		||||
 | 
			
		||||
	    } // end else
 | 
			
		||||
 | 
			
		||||
	  } // end if
 | 
			
		||||
	  else
 | 
			
		||||
	  { // slippage detected - show the slippage display
 | 
			
		||||
	    content = new PostSlippage(getVeniceEngine(),sig,conf,topic,pn,request.getParameter("next"),
 | 
			
		||||
				       request.getParameter("pseud"),raw_postdata,
 | 
			
		||||
                                       yes.equals(request.getParameter("attach")));
 | 
			
		||||
	    page_title = "Slippage or Double-Click Detected";
 | 
			
		||||
 | 
			
		||||
	  } // end else
 | 
			
		||||
 | 
			
		||||
	} // end try
 | 
			
		||||
	catch (ValidationException ve)
 | 
			
		||||
	{ // there was some sort of a parameter error in the display
 | 
			
		||||
	  page_title = "Error";
 | 
			
		||||
	  content = new ErrorBox(null,ve.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	catch (DataException de)
 | 
			
		||||
	{ // there was a database error posting the message
 | 
			
		||||
	  page_title = "Database Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,"Database error posting message: " + de.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
	catch (AccessError ae)
 | 
			
		||||
	{ // we were unable to retrieve the topic list
 | 
			
		||||
	  page_title = "Access Error";
 | 
			
		||||
	  content = new ErrorBox(page_title,ae.getMessage(),"top");
 | 
			
		||||
 | 
			
		||||
	} // end catch
 | 
			
		||||
 | 
			
		||||
      } // end else if ("Post & Go Next")
 | 
			
		||||
      else
 | 
			
		||||
      { // unknown button clicked
 | 
			
		||||
	page_title = "Internal Error";
 | 
			
		||||
	logger.error("no known button click on PostMessage.doPost");
 | 
			
		||||
	content = new ErrorBox(page_title,"Unknown command button pressed","top");
 | 
			
		||||
 | 
			
		||||
      } // end else
 | 
			
		||||
 | 
			
		||||
    } // end if (got all parameters oK)
 | 
			
		||||
 | 
			
		||||
    BaseJSPData basedat = new BaseJSPData(page_title,"post",content);
 | 
			
		||||
    basedat.transfer(getServletContext(),rdat);
 | 
			
		||||
 | 
			
		||||
  } // end doPost
 | 
			
		||||
 | 
			
		||||
} // end class PostMessage
 | 
			
		||||
							
								
								
									
										190
									
								
								src/com/silverwrist/venice/servlets/format/PostPreview.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,190 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 | 
			
		||||
 * (the "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 * 
 | 
			
		||||
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 | 
			
		||||
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 | 
			
		||||
 * language governing rights and limitations under the License.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Original Code is the Venice Web Communities System.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
 * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 | 
			
		||||
 * 
 | 
			
		||||
 * Contributor(s): 
 | 
			
		||||
 */
 | 
			
		||||
package com.silverwrist.venice.servlets.format;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import javax.servlet.*;
 | 
			
		||||
import javax.servlet.http.*;
 | 
			
		||||
import com.silverwrist.util.StringUtil;
 | 
			
		||||
import com.silverwrist.venice.htmlcheck.*;
 | 
			
		||||
import com.silverwrist.venice.core.*;
 | 
			
		||||
 | 
			
		||||
public class PostPreview implements JSPRender
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static data members
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  // Attribute name for request attribute
 | 
			
		||||
  protected static final String ATTR_NAME = "com.silverwrist.venice.content.PostPreview";
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Attributes
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private SIGContext sig;
 | 
			
		||||
  private ConferenceContext conf;
 | 
			
		||||
  private TopicContext topic;
 | 
			
		||||
  private String next;
 | 
			
		||||
  private String pseud;
 | 
			
		||||
  private String data;
 | 
			
		||||
  private String preview;
 | 
			
		||||
  private int num_errors;
 | 
			
		||||
  private int msgs;
 | 
			
		||||
  private boolean attach;
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Constructor
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public PostPreview(VeniceEngine engine, SIGContext sig, ConferenceContext conf, TopicContext topic,
 | 
			
		||||
                     String pseud, String data, String next, int msgs, boolean attach)
 | 
			
		||||
  {
 | 
			
		||||
    this.sig = sig;
 | 
			
		||||
    this.conf = conf;
 | 
			
		||||
    this.topic = topic;
 | 
			
		||||
    this.next = next;
 | 
			
		||||
    this.msgs = msgs;
 | 
			
		||||
    this.attach = attach;
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // sanitize the pseud data
 | 
			
		||||
      HTMLChecker check = engine.getEscapingChecker();
 | 
			
		||||
      check.append(pseud);
 | 
			
		||||
      check.finish();
 | 
			
		||||
      this.pseud = check.getValue();
 | 
			
		||||
 | 
			
		||||
      // sanitize the post box data
 | 
			
		||||
      check.reset();
 | 
			
		||||
      check.append(data);
 | 
			
		||||
      check.finish();
 | 
			
		||||
      this.data = check.getValue();
 | 
			
		||||
 | 
			
		||||
      // now generate the preview
 | 
			
		||||
      check = engine.getPreviewChecker();
 | 
			
		||||
      check.append(data);
 | 
			
		||||
      check.finish();
 | 
			
		||||
      this.preview = check.getValue();
 | 
			
		||||
      this.num_errors = check.getCounter("spelling");
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (HTMLCheckerException e)
 | 
			
		||||
    { // this is a bad issue...
 | 
			
		||||
      throw new InternalStateError("spurious HTMLCheckerException thrown");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * External static functions
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public static PostPreview retrieve(ServletRequest request)
 | 
			
		||||
  {
 | 
			
		||||
    return (PostPreview)(request.getAttribute(ATTR_NAME));
 | 
			
		||||
 | 
			
		||||
  } // end retrieve
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface JSPRender
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public void store(ServletRequest request)
 | 
			
		||||
  {
 | 
			
		||||
    request.setAttribute(ATTR_NAME,this);
 | 
			
		||||
 | 
			
		||||
  } // end store
 | 
			
		||||
 | 
			
		||||
  public String getTargetJSPName()
 | 
			
		||||
  {
 | 
			
		||||
    return "preview.jsp";
 | 
			
		||||
 | 
			
		||||
  } // end getTargetJSPName
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * External operations
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public int getNumSpellingErrors()
 | 
			
		||||
  {
 | 
			
		||||
    return num_errors;
 | 
			
		||||
 | 
			
		||||
  } // end getNumSpellingErrors
 | 
			
		||||
 | 
			
		||||
  public String getPreviewData()
 | 
			
		||||
  {
 | 
			
		||||
    return preview;
 | 
			
		||||
 | 
			
		||||
  } // end getPreviewData
 | 
			
		||||
 | 
			
		||||
  public int getSIGID()
 | 
			
		||||
  {
 | 
			
		||||
    return sig.getSIGID();
 | 
			
		||||
 | 
			
		||||
  } // end getSIGID
 | 
			
		||||
 | 
			
		||||
  public int getConfID()
 | 
			
		||||
  {
 | 
			
		||||
    return conf.getConfID();
 | 
			
		||||
 | 
			
		||||
  } // end getConfID
 | 
			
		||||
 | 
			
		||||
  public int getTopicNumber()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.getTopicNumber();
 | 
			
		||||
 | 
			
		||||
  } // end getTopicNumber
 | 
			
		||||
 | 
			
		||||
  public int getTotalMessages()
 | 
			
		||||
  {
 | 
			
		||||
    return msgs;
 | 
			
		||||
 | 
			
		||||
  } // end getTotalMessages
 | 
			
		||||
 | 
			
		||||
  public String getNextVal()
 | 
			
		||||
  {
 | 
			
		||||
    return next;
 | 
			
		||||
 | 
			
		||||
  } // end getNextVal
 | 
			
		||||
 | 
			
		||||
  public String getPseud()
 | 
			
		||||
  {
 | 
			
		||||
    return pseud;
 | 
			
		||||
 | 
			
		||||
  } // end getPseud
 | 
			
		||||
 | 
			
		||||
  public boolean attachChecked()
 | 
			
		||||
  {
 | 
			
		||||
    return attach;
 | 
			
		||||
 | 
			
		||||
  } // end attachChecked
 | 
			
		||||
 | 
			
		||||
  public String getBodyText()
 | 
			
		||||
  {
 | 
			
		||||
    return data;
 | 
			
		||||
 | 
			
		||||
  } // end getBodyText
 | 
			
		||||
 | 
			
		||||
} // end class PostPreview
 | 
			
		||||
							
								
								
									
										216
									
								
								src/com/silverwrist/venice/servlets/format/PostSlippage.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,216 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 | 
			
		||||
 * (the "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 * 
 | 
			
		||||
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 | 
			
		||||
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 | 
			
		||||
 * language governing rights and limitations under the License.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Original Code is the Venice Web Communities System.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
 * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 | 
			
		||||
 * 
 | 
			
		||||
 * Contributor(s): 
 | 
			
		||||
 */
 | 
			
		||||
package com.silverwrist.venice.servlets.format;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import javax.servlet.*;
 | 
			
		||||
import javax.servlet.http.*;
 | 
			
		||||
import com.silverwrist.util.StringUtil;
 | 
			
		||||
import com.silverwrist.venice.htmlcheck.*;
 | 
			
		||||
import com.silverwrist.venice.core.*;
 | 
			
		||||
 | 
			
		||||
public class PostSlippage implements JSPRender
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static data members
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  // Attribute name for request attribute
 | 
			
		||||
  protected static final String ATTR_NAME = "com.silverwrist.venice.content.PostSlippage";
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Attributes
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private SIGContext sig;
 | 
			
		||||
  private ConferenceContext conf;
 | 
			
		||||
  private TopicContext topic;
 | 
			
		||||
  private List messages;
 | 
			
		||||
  private String next;
 | 
			
		||||
  private String pseud;
 | 
			
		||||
  private String text;
 | 
			
		||||
  private boolean attach;
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Constructor
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public PostSlippage(VeniceEngine engine, SIGContext sig, ConferenceContext conf, TopicContext topic,
 | 
			
		||||
                      int lastval, String next, String pseud, String text, boolean attach)
 | 
			
		||||
      throws DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    this.sig = sig;
 | 
			
		||||
    this.conf = conf;
 | 
			
		||||
    this.topic = topic;
 | 
			
		||||
    this.messages = topic.getMessages(lastval,topic.getTotalMessages()-1);
 | 
			
		||||
    this.next = next;
 | 
			
		||||
    this.attach = attach;
 | 
			
		||||
 | 
			
		||||
    try
 | 
			
		||||
    { // run the text and pseud through an HTML checker to escape them
 | 
			
		||||
      HTMLChecker ch = engine.getEscapingChecker();
 | 
			
		||||
      ch.append(pseud);
 | 
			
		||||
      ch.finish();
 | 
			
		||||
      this.pseud = ch.getValue();
 | 
			
		||||
      ch.reset();
 | 
			
		||||
      ch.append(text);
 | 
			
		||||
      ch.finish();
 | 
			
		||||
      this.text = text;
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (HTMLCheckerException e)
 | 
			
		||||
    { // this shouldn't happen
 | 
			
		||||
      throw new InternalStateError("spurious HTMLCheckerException thrown");
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * External static functions
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public static PostSlippage retrieve(ServletRequest request)
 | 
			
		||||
  {
 | 
			
		||||
    return (PostSlippage)(request.getAttribute(ATTR_NAME));
 | 
			
		||||
 | 
			
		||||
  } // end retrieve
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface JSPRender
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public void store(ServletRequest request)
 | 
			
		||||
  {
 | 
			
		||||
    request.setAttribute(ATTR_NAME,this);
 | 
			
		||||
 | 
			
		||||
  } // end store
 | 
			
		||||
 | 
			
		||||
  public String getTargetJSPName()
 | 
			
		||||
  {
 | 
			
		||||
    return "slippage.jsp";
 | 
			
		||||
 | 
			
		||||
  } // end getTargetJSPName
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * External operations
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public static String getPosterName(TopicMessageContext msg)
 | 
			
		||||
  {
 | 
			
		||||
    try
 | 
			
		||||
    { // have to guard agains a DataException here
 | 
			
		||||
      return msg.getCreatorName();
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (DataException de)
 | 
			
		||||
    { // just return "unknown" on failure
 | 
			
		||||
      return "(unknown)";
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getPosterName
 | 
			
		||||
 | 
			
		||||
  public static String getMessageBodyText(TopicMessageContext msg)
 | 
			
		||||
  {
 | 
			
		||||
    try
 | 
			
		||||
    { // have to guard against a DataException here
 | 
			
		||||
      return msg.getBodyText();
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (DataException de)
 | 
			
		||||
    { // just return an error message
 | 
			
		||||
      return "<EM>(Unable to retrieve message data: " + StringUtil.encodeHTML(de.getMessage()) + ")</EM>";
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getMessageBodyText
 | 
			
		||||
 | 
			
		||||
  public int getSIGID()
 | 
			
		||||
  {
 | 
			
		||||
    return sig.getSIGID();
 | 
			
		||||
 | 
			
		||||
  } // end getSIGID
 | 
			
		||||
 | 
			
		||||
  public int getConfID()
 | 
			
		||||
  {
 | 
			
		||||
    return conf.getConfID();
 | 
			
		||||
 | 
			
		||||
  } // end getConfID
 | 
			
		||||
 | 
			
		||||
  public int getTopicNumber()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.getTopicNumber();
 | 
			
		||||
 | 
			
		||||
  } // end getTopicNumber
 | 
			
		||||
 | 
			
		||||
  public String getTopicName()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.getName();
 | 
			
		||||
 | 
			
		||||
  } // end getTopicName
 | 
			
		||||
 | 
			
		||||
  public String getIdentifyingData()
 | 
			
		||||
  {
 | 
			
		||||
    return "Slippage posting to topic " + String.valueOf(topic.getTopicID());
 | 
			
		||||
 | 
			
		||||
  } // end getIdentifyingData
 | 
			
		||||
 | 
			
		||||
  public int getTotalMessages()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.getTotalMessages();
 | 
			
		||||
 | 
			
		||||
  } // end getTotalMessages
 | 
			
		||||
 | 
			
		||||
  public Iterator getMessageIterator()
 | 
			
		||||
  {
 | 
			
		||||
    return messages.iterator();
 | 
			
		||||
 | 
			
		||||
  } // end getMessageIterator
 | 
			
		||||
 | 
			
		||||
  public String getNextVal()
 | 
			
		||||
  {
 | 
			
		||||
    return next;
 | 
			
		||||
 | 
			
		||||
  } // end getNextVal
 | 
			
		||||
 | 
			
		||||
  public String getPseud()
 | 
			
		||||
  {
 | 
			
		||||
    return pseud;
 | 
			
		||||
 | 
			
		||||
  } // end getPseud
 | 
			
		||||
 | 
			
		||||
  public boolean attachChecked()
 | 
			
		||||
  {
 | 
			
		||||
    return attach;
 | 
			
		||||
 | 
			
		||||
  } // end attachChecked
 | 
			
		||||
 | 
			
		||||
  public String getBodyText()
 | 
			
		||||
  {
 | 
			
		||||
    return text;
 | 
			
		||||
 | 
			
		||||
  } // end getBodyText
 | 
			
		||||
 | 
			
		||||
} // end class PostSlippage
 | 
			
		||||
@ -106,6 +106,14 @@ public class TopicListing implements JSPRender
 | 
			
		||||
 | 
			
		||||
  } // end getConfID
 | 
			
		||||
 | 
			
		||||
  public String getLocator()
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer buf = new StringBuffer("sig=");
 | 
			
		||||
    buf.append(sig.getSIGID()).append("&conf=").append(conf.getConfID());
 | 
			
		||||
    return buf.toString();
 | 
			
		||||
 | 
			
		||||
  } // end getLocator
 | 
			
		||||
 | 
			
		||||
  public String getConfName()
 | 
			
		||||
  {
 | 
			
		||||
    return conf.getName();
 | 
			
		||||
@ -118,6 +126,15 @@ public class TopicListing implements JSPRender
 | 
			
		||||
 | 
			
		||||
  } // end canDoReadNew
 | 
			
		||||
 | 
			
		||||
  public String getNextLocator()
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer buf = new StringBuffer("sig=");
 | 
			
		||||
    buf.append(sig.getSIGID()).append("&conf=").append(conf.getConfID()).append("&top=");
 | 
			
		||||
    buf.append(visit_order.getNext());
 | 
			
		||||
    return buf.toString();
 | 
			
		||||
 | 
			
		||||
  } // end getNextLocator
 | 
			
		||||
 | 
			
		||||
  public boolean canCreateTopic()
 | 
			
		||||
  {
 | 
			
		||||
    return conf.canCreateTopic();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										354
									
								
								src/com/silverwrist/venice/servlets/format/TopicPosts.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,354 @@
 | 
			
		||||
/*
 | 
			
		||||
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 | 
			
		||||
 * (the "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 * 
 | 
			
		||||
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 | 
			
		||||
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 | 
			
		||||
 * language governing rights and limitations under the License.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Original Code is the Venice Web Communities System.
 | 
			
		||||
 * 
 | 
			
		||||
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
 * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 | 
			
		||||
 * 
 | 
			
		||||
 * Contributor(s): 
 | 
			
		||||
 */
 | 
			
		||||
package com.silverwrist.venice.servlets.format;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import javax.servlet.*;
 | 
			
		||||
import javax.servlet.http.*;
 | 
			
		||||
import com.silverwrist.util.StringUtil;
 | 
			
		||||
import com.silverwrist.venice.core.*;
 | 
			
		||||
 | 
			
		||||
public class TopicPosts implements JSPRender
 | 
			
		||||
{
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Static data members
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  // Attribute name for request attribute
 | 
			
		||||
  protected static final String ATTR_NAME = "com.silverwrist.venice.content.TopicPosts";
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Attributes
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  private SIGContext sig;
 | 
			
		||||
  private ConferenceContext conf;
 | 
			
		||||
  private TopicContext topic;
 | 
			
		||||
  private int first;
 | 
			
		||||
  private int last;
 | 
			
		||||
  private boolean show_advanced;
 | 
			
		||||
  private int unread;
 | 
			
		||||
  private List messages;
 | 
			
		||||
  private TopicVisitOrder visit_order;
 | 
			
		||||
  private String cache_locator = null;
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Constructor
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public TopicPosts(HttpServletRequest request, SIGContext sig, ConferenceContext conf, TopicContext topic,
 | 
			
		||||
		    int first, int last, boolean read_new, boolean show_advanced)
 | 
			
		||||
      throws DataException, AccessError
 | 
			
		||||
  {
 | 
			
		||||
    this.sig = sig;
 | 
			
		||||
    this.conf = conf;
 | 
			
		||||
    this.topic = topic;
 | 
			
		||||
    this.first = first;
 | 
			
		||||
    this.last = last;
 | 
			
		||||
    this.show_advanced = show_advanced;
 | 
			
		||||
    this.unread = topic.getUnreadMessages();
 | 
			
		||||
    if (read_new)
 | 
			
		||||
      topic.setUnreadMessages(0);
 | 
			
		||||
    this.messages = topic.getMessages(first,last);
 | 
			
		||||
    this.visit_order = TopicVisitOrder.retrieve(request.getSession(true),conf.getConfID());
 | 
			
		||||
    visit_order.visit(topic.getTopicNumber());
 | 
			
		||||
 | 
			
		||||
  } // end constructor
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * External static functions
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public static TopicPosts retrieve(ServletRequest request)
 | 
			
		||||
  {
 | 
			
		||||
    return (TopicPosts)(request.getAttribute(ATTR_NAME));
 | 
			
		||||
 | 
			
		||||
  } // end retrieve
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * Implementations from interface JSPRender
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public void store(ServletRequest request)
 | 
			
		||||
  {
 | 
			
		||||
    request.setAttribute(ATTR_NAME,this);
 | 
			
		||||
 | 
			
		||||
  } // end store
 | 
			
		||||
 | 
			
		||||
  public String getTargetJSPName()
 | 
			
		||||
  {
 | 
			
		||||
    return "posts.jsp";
 | 
			
		||||
 | 
			
		||||
  } // end getTargetJSPName
 | 
			
		||||
 | 
			
		||||
  /*--------------------------------------------------------------------------------
 | 
			
		||||
   * External operations
 | 
			
		||||
   *--------------------------------------------------------------------------------
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  public static String getPosterName(TopicMessageContext msg)
 | 
			
		||||
  {
 | 
			
		||||
    try
 | 
			
		||||
    { // have to guard agains a DataException here
 | 
			
		||||
      return msg.getCreatorName();
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (DataException de)
 | 
			
		||||
    { // just return "unknown" on failure
 | 
			
		||||
      return "(unknown)";
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getPosterName
 | 
			
		||||
 | 
			
		||||
  public static String getMessageBodyText(TopicMessageContext msg)
 | 
			
		||||
  {
 | 
			
		||||
    try
 | 
			
		||||
    { // have to guard against a DataException here
 | 
			
		||||
      return msg.getBodyText();
 | 
			
		||||
 | 
			
		||||
    } // end try
 | 
			
		||||
    catch (DataException de)
 | 
			
		||||
    { // just return an error message
 | 
			
		||||
      return "<EM>(Unable to retrieve message data: " + StringUtil.encodeHTML(de.getMessage()) + ")</EM>";
 | 
			
		||||
 | 
			
		||||
    } // end catch
 | 
			
		||||
 | 
			
		||||
  } // end getMessageBodyText
 | 
			
		||||
 | 
			
		||||
  public int getSIGID()
 | 
			
		||||
  {
 | 
			
		||||
    return sig.getSIGID();
 | 
			
		||||
 | 
			
		||||
  } // end getSIGID
 | 
			
		||||
 | 
			
		||||
  public int getConfID()
 | 
			
		||||
  {
 | 
			
		||||
    return conf.getConfID();
 | 
			
		||||
 | 
			
		||||
  } // end getConfID
 | 
			
		||||
 | 
			
		||||
  public int getTopicNumber()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.getTopicNumber();
 | 
			
		||||
 | 
			
		||||
  } // end getTopicNumber
 | 
			
		||||
 | 
			
		||||
  public int getNextTopicNumber()
 | 
			
		||||
  {
 | 
			
		||||
    return visit_order.getNext();
 | 
			
		||||
 | 
			
		||||
  } // end getNextTopicNumber
 | 
			
		||||
 | 
			
		||||
  public String getConfLocator()
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer buf = new StringBuffer("sig=");
 | 
			
		||||
    buf.append(sig.getSIGID()).append("&conf=").append(conf.getConfID());
 | 
			
		||||
    return buf.toString();
 | 
			
		||||
 | 
			
		||||
  } // end getConfLocator
 | 
			
		||||
 | 
			
		||||
  public String getLocator()
 | 
			
		||||
  {
 | 
			
		||||
    if (cache_locator==null)
 | 
			
		||||
    { // build up the standard locator
 | 
			
		||||
      StringBuffer buf = new StringBuffer("sig=");
 | 
			
		||||
      buf.append(sig.getSIGID()).append("&conf=").append(conf.getConfID()).append("&top=");
 | 
			
		||||
      buf.append(topic.getTopicNumber());
 | 
			
		||||
      cache_locator = buf.toString();
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    return cache_locator;
 | 
			
		||||
 | 
			
		||||
  } // end getLocator
 | 
			
		||||
 | 
			
		||||
  public String getNextLocator()
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer buf = new StringBuffer("sig=");
 | 
			
		||||
    buf.append(sig.getSIGID()).append("&conf=").append(conf.getConfID()).append("&top=");
 | 
			
		||||
    buf.append(visit_order.getNext());
 | 
			
		||||
    return buf.toString();
 | 
			
		||||
 | 
			
		||||
  } // end getNextLocator
 | 
			
		||||
 | 
			
		||||
  public String getIdentifyingData()
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer buf = new StringBuffer("Posts ");
 | 
			
		||||
    buf.append(first).append(" through ").append(last).append(" in topic #").append(topic.getTopicID());
 | 
			
		||||
    return buf.toString();
 | 
			
		||||
 | 
			
		||||
  } // end getIdentifyingData
 | 
			
		||||
 | 
			
		||||
  public String getTopicName()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.getName();
 | 
			
		||||
 | 
			
		||||
  } // end getTopicName
 | 
			
		||||
 | 
			
		||||
  public int getTotalMessages()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.getTotalMessages();
 | 
			
		||||
 | 
			
		||||
  } // end getTotalMessages
 | 
			
		||||
 | 
			
		||||
  public int getNewMessages()
 | 
			
		||||
  {
 | 
			
		||||
    return unread;
 | 
			
		||||
 | 
			
		||||
  } // end getNewMessages
 | 
			
		||||
 | 
			
		||||
  public Date getLastUpdate()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.getLastUpdateDate();
 | 
			
		||||
 | 
			
		||||
  } // end getLastUpdate
 | 
			
		||||
 | 
			
		||||
  public boolean isTopicHidden()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.isHidden();
 | 
			
		||||
 | 
			
		||||
  } // end isTopicHidden
 | 
			
		||||
 | 
			
		||||
  public boolean canDoNextTopic()
 | 
			
		||||
  {
 | 
			
		||||
    return visit_order.isNext();
 | 
			
		||||
 | 
			
		||||
  } // end canDoNextTopic
 | 
			
		||||
 | 
			
		||||
  public boolean canFreezeTopic()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.canFreeze();
 | 
			
		||||
 | 
			
		||||
  } // end canFreezeTopic
 | 
			
		||||
 | 
			
		||||
  public boolean isTopicFrozen()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.isFrozen();
 | 
			
		||||
 | 
			
		||||
  } // end isTopicFrozen
 | 
			
		||||
 | 
			
		||||
  public boolean canArchiveTopic()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.canArchive();
 | 
			
		||||
 | 
			
		||||
  } // end canArchiveTopic
 | 
			
		||||
 | 
			
		||||
  public boolean isTopicArchived()
 | 
			
		||||
  {
 | 
			
		||||
    return topic.isArchived();
 | 
			
		||||
 | 
			
		||||
  } // end isTopicArchived
 | 
			
		||||
 | 
			
		||||
  public boolean canDeleteTopic()
 | 
			
		||||
  {
 | 
			
		||||
    return false;  // TODO: fix me
 | 
			
		||||
 | 
			
		||||
  } // end canDeleteTopic
 | 
			
		||||
 | 
			
		||||
  public boolean canScrollUp()
 | 
			
		||||
  {
 | 
			
		||||
    return (first>0);
 | 
			
		||||
 | 
			
		||||
  } // end canScrollUp
 | 
			
		||||
 | 
			
		||||
  public String getScrollUpLocator()
 | 
			
		||||
  {
 | 
			
		||||
    int new_first = first - 20;  // TODO: configurable
 | 
			
		||||
    int new_last = last - 1;
 | 
			
		||||
    if (new_first<0)
 | 
			
		||||
    { // normalize so we start at 0
 | 
			
		||||
      new_last += (-new_first);
 | 
			
		||||
      new_first = 0;
 | 
			
		||||
 | 
			
		||||
    } // end if
 | 
			
		||||
 | 
			
		||||
    StringBuffer buf = new StringBuffer("p1=");
 | 
			
		||||
    buf.append(new_first).append("&p2=").append(new_last);
 | 
			
		||||
    return buf.toString();
 | 
			
		||||
 | 
			
		||||
  } // end getScrollUpLocator
 | 
			
		||||
 | 
			
		||||
  public boolean canScrollDown()
 | 
			
		||||
  {
 | 
			
		||||
    return ((topic.getTotalMessages() - (1 + last))>=20); // TODO: configurable
 | 
			
		||||
 | 
			
		||||
  } // end canScrollDown
 | 
			
		||||
 | 
			
		||||
  public String getScrollDownLocator()
 | 
			
		||||
  {
 | 
			
		||||
    StringBuffer buf = new StringBuffer("p1=");
 | 
			
		||||
    buf.append(last+1).append("&p2=").append(last+20);  // TODO: configurable
 | 
			
		||||
    return buf.toString();
 | 
			
		||||
 | 
			
		||||
  } // end getScrollDownLocator
 | 
			
		||||
 | 
			
		||||
  public boolean canScrollToEnd()
 | 
			
		||||
  {
 | 
			
		||||
    return ((topic.getTotalMessages() - (1 + last))>0);
 | 
			
		||||
 | 
			
		||||
  } // end canScrollToEnd
 | 
			
		||||
 | 
			
		||||
  public String getScrollToEndLocator()
 | 
			
		||||
  {
 | 
			
		||||
    int my_last = topic.getTotalMessages();
 | 
			
		||||
    StringBuffer buf = new StringBuffer("p1=");
 | 
			
		||||
    buf.append(my_last-20).append("&p2=").append(my_last-1);  // TODO: configurable
 | 
			
		||||
    return buf.toString();
 | 
			
		||||
 | 
			
		||||
  } // end getScrollToEndLocator
 | 
			
		||||
 | 
			
		||||
  public Iterator getMessageIterator()
 | 
			
		||||
  {
 | 
			
		||||
    return messages.iterator();
 | 
			
		||||
 | 
			
		||||
  } // end getMessageIterator()
 | 
			
		||||
 | 
			
		||||
  public boolean emitBreakLinePoint(int msg)
 | 
			
		||||
  {
 | 
			
		||||
    return (msg==(topic.getTotalMessages()-unread));
 | 
			
		||||
 | 
			
		||||
  } // end emitBreakLinePoint
 | 
			
		||||
 | 
			
		||||
  public boolean showAdvanced()
 | 
			
		||||
  {
 | 
			
		||||
    return show_advanced && (last==first);
 | 
			
		||||
 | 
			
		||||
  } // end showAdvanced
 | 
			
		||||
 | 
			
		||||
  public boolean displayPostBox()
 | 
			
		||||
  {
 | 
			
		||||
    boolean flag1 = conf.canPostToConference();
 | 
			
		||||
    boolean flag2 = (topic.isFrozen() ? topic.canFreeze() : true);
 | 
			
		||||
    boolean flag3 = (topic.isArchived() ? topic.canArchive() : true);
 | 
			
		||||
    return flag1 && flag2 && flag3;
 | 
			
		||||
 | 
			
		||||
  } // end displayPostBox
 | 
			
		||||
 | 
			
		||||
  public String getDefaultPseud()
 | 
			
		||||
  {
 | 
			
		||||
    return conf.getDefaultPseud();
 | 
			
		||||
 | 
			
		||||
  } // end getDefaultPseud
 | 
			
		||||
 | 
			
		||||
} // end class TopicPosts
 | 
			
		||||
							
								
								
									
										327
									
								
								web/format/posts.jsp
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,327 @@
 | 
			
		||||
<%--
 | 
			
		||||
  The contents of this file are subject to the Mozilla Public License Version 1.1
 | 
			
		||||
  (the "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 | 
			
		||||
  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 | 
			
		||||
  WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 | 
			
		||||
  language governing rights and limitations under the License.
 | 
			
		||||
  
 | 
			
		||||
  The Original Code is the Venice Web Communities System.
 | 
			
		||||
  
 | 
			
		||||
  The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
  for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
  Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 | 
			
		||||
 | 
			
		||||
  Contributor(s): 
 | 
			
		||||
--%>
 | 
			
		||||
<%@ page import = "java.util.*" %>
 | 
			
		||||
<%@ page import = "com.silverwrist.util.StringUtil" %>
 | 
			
		||||
<%@ page import = "com.silverwrist.venice.core.*" %>
 | 
			
		||||
<%@ page import = "com.silverwrist.venice.servlets.Variables" %>
 | 
			
		||||
<%@ page import = "com.silverwrist.venice.servlets.format.*" %>
 | 
			
		||||
<%
 | 
			
		||||
  TopicPosts data = TopicPosts.retrieve(request);
 | 
			
		||||
  Variables.failIfNull(data);
 | 
			
		||||
  RenderData rdat = RenderConfig.createRenderData(application,request,response);
 | 
			
		||||
%>
 | 
			
		||||
<% if (rdat.useHTMLComments()) { %><!-- <%= data.getIdentifyingData() %> --><% } %>
 | 
			
		||||
<%
 | 
			
		||||
  String tmp;
 | 
			
		||||
  if (data.isTopicArchived())
 | 
			
		||||
    tmp = "(Archived) ";
 | 
			
		||||
  else if (data.isTopicFrozen())
 | 
			
		||||
    tmp = "(Frozen) ";
 | 
			
		||||
  else
 | 
			
		||||
    tmp = "";
 | 
			
		||||
  rdat.writeContentHeader(out,data.getTopicName(),tmp + String.valueOf(data.getTotalMessages())
 | 
			
		||||
                          + " Total; " + String.valueOf(data.getNewMessages()) + " New; Last: "
 | 
			
		||||
                          + rdat.formatDateForDisplay(data.getLastUpdate()));
 | 
			
		||||
%>
 | 
			
		||||
<TABLE BORDER=0 WIDTH="100%" CELLPADDING=0 CELLSPACING=0>
 | 
			
		||||
  <TR VALIGN=BOTTOM>
 | 
			
		||||
    <TD NOWRAP ALIGN=LEFT>
 | 
			
		||||
      <% if (rdat.useHTMLComments()) { %><!-- Topic user controls section --><% } %>
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getConfLocator()) %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_topic_list.gif") %>" ALT="Topic List" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
        
 | 
			
		||||
      <% if (data.isTopicHidden()) { %>
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_show_topic.gif") %>" ALT="Show Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
      <% } else { %>
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_hide_topic.gif") %>" ALT="Hide Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
        
 | 
			
		||||
      <% if (data.canDoNextTopic()) { %>
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getNextLocator() + "&rnm=1") %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_next_topic.gif") %>" ALT="Next Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
          
 | 
			
		||||
        <% if (data.getNewMessages()>0) { %>
 | 
			
		||||
          <%-- TODO: this doesn't do Keep New yet --%>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getNextLocator() + "&rnm=1") %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_next_keep_new.gif") %>" ALT="Next & Keep New" WIDTH=80 HEIGHT=24
 | 
			
		||||
           BORDER=0></A>
 | 
			
		||||
            
 | 
			
		||||
        <% } // end if %>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
    </TD>
 | 
			
		||||
    <TD NOWRAP ALIGN=RIGHT>
 | 
			
		||||
      <% if (rdat.useHTMLComments()) { %><!-- Topic admin controls section --><% } %>
 | 
			
		||||
      <% if (data.canFreezeTopic()) { %>
 | 
			
		||||
          
 | 
			
		||||
        <% if (data.isTopicFrozen()) { %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_unfreeze_topic.gif") %>" ALT="Unfreeze Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
           BORDER=0></A>
 | 
			
		||||
        <% } else { %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_freeze_topic.gif") %>" ALT="Freeze Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
           BORDER=0></A>
 | 
			
		||||
        <% } // end if %>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
      <% if (data.canArchiveTopic()) { %>
 | 
			
		||||
          
 | 
			
		||||
        <% if (data.isTopicArchived()) { %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_unarchive_topic.gif") %>" ALT="Unarchive Topic" WIDTH=80
 | 
			
		||||
           HEIGHT=24 BORDER=0></A>
 | 
			
		||||
        <% } else { %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_archive_topic.gif") %>" ALT="Archive Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
           BORDER=0></A>
 | 
			
		||||
        <% } // end if %>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
      <% if (data.canDeleteTopic()) { %>
 | 
			
		||||
          
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_delete_topic.gif") %>" ALT="Delete Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
    </TD>
 | 
			
		||||
  </TR>
 | 
			
		||||
  <TR><TD COLSPAN=2> </TD></TR>
 | 
			
		||||
  <TR VALIGN=BOTTOM>
 | 
			
		||||
    <TD NOWRAP ALIGN=LEFT>
 | 
			
		||||
      <% if (rdat.useHTMLComments()) { %><!-- Go box --><% } %>
 | 
			
		||||
      <FORM METHOD="GET" ACTION="<%= rdat.getEncodedServletPath("confdisp") %>">
 | 
			
		||||
        <INPUT TYPE="HIDDEN" NAME="sig" VALUE="<%= data.getSIGID() %>">
 | 
			
		||||
        <INPUT TYPE="HIDDEN" NAME="conf" VALUE="<%= data.getConfID() %>">
 | 
			
		||||
        <INPUT TYPE="HIDDEN" NAME="top" VALUE="<%= data.getTopicNumber() %>">
 | 
			
		||||
        <INPUT TYPE="TEXT" NAME="pxg" VALUE="" SIZE=6 MAXLENGTH=13>  
 | 
			
		||||
        <INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_go.gif") %>" NAME="Go" ALT="Go"
 | 
			
		||||
         ALIGN=BOTTOM WIDTH=80 HEIGHT=24 BORDER=0>
 | 
			
		||||
      </FORM>
 | 
			
		||||
    </TD>
 | 
			
		||||
    <TD NOWRAP ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
      <% if (rdat.useHTMLComments()) { %><!-- Upper navigation linkset --><% } %>
 | 
			
		||||
      <%-- TODO: the number "20" should be configurable --%>
 | 
			
		||||
      <A NAME="top">[</A> 
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&p1=0&p2=-1") %>">View All</A>
 | 
			
		||||
      <% if (data.canScrollUp()) { %>
 | 
			
		||||
         | 
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&"
 | 
			
		||||
                                                + data.getScrollUpLocator()) %>">Scroll Up 20</A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
      <% if (data.canScrollDown()) { %>
 | 
			
		||||
         | 
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&"
 | 
			
		||||
                                                + data.getScrollDownLocator()) %>">Scroll Down 20</A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
      <% if (data.canScrollDown()) { %>
 | 
			
		||||
         | 
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&"
 | 
			
		||||
                                                + data.getScrollToEndLocator()) %>">Scroll To End</A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
       | 
 | 
			
		||||
      <A HREF="#bottom">Bottom</A>
 | 
			
		||||
       ]
 | 
			
		||||
    </FONT></TD>
 | 
			
		||||
  </TR>
 | 
			
		||||
</TABLE>
 | 
			
		||||
 | 
			
		||||
<% if (rdat.useHTMLComments()) { %><!-- Begin Actual Messages --><% } %>
 | 
			
		||||
<%
 | 
			
		||||
  Iterator it = data.getMessageIterator();
 | 
			
		||||
  String last_post = rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&shac=1&p1="
 | 
			
		||||
                                                 + String.valueOf(data.getTotalMessages() - 1));
 | 
			
		||||
  boolean can_line = false;
 | 
			
		||||
%>
 | 
			
		||||
<% while (it.hasNext()) { %>
 | 
			
		||||
  <%
 | 
			
		||||
    TopicMessageContext msg = (TopicMessageContext)(it.next());
 | 
			
		||||
    String poster = data.getPosterName(msg);
 | 
			
		||||
  %>
 | 
			
		||||
  <% if (can_line && data.emitBreakLinePoint(msg.getPostNumber())) { %><HR WIDTH="70%"><% } %>
 | 
			
		||||
  <% if (data.showAdvanced()) { %>
 | 
			
		||||
    <BR>
 | 
			
		||||
    <TABLE WIDTH="100%" BORDER=0 CELLPADDING=0 CELLSPACING=0><TR VALIGN=TOP><TD NOWRAP ALIGN=LEFT>
 | 
			
		||||
  <% } // end if %>
 | 
			
		||||
  <%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
    <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&shac=1&p1="
 | 
			
		||||
                               + String.valueOf(msg.getPostNumber())) %>"><%= msg.getPostNumber() %></A> of
 | 
			
		||||
    <A HREF="<%= last_post %>"><%= data.getTotalMessages() - 1 %></A>
 | 
			
		||||
    <%= rdat.getStdFontTag(null,1) %><<%= "TODO" %>></FONT><BR>
 | 
			
		||||
    <B><%= msg.getPseud() %></B>
 | 
			
		||||
    (<EM>
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("user/" + poster) %>" TARGET="_blank"><%= poster %></A>,
 | 
			
		||||
      <%= rdat.formatDateForDisplay(msg.getPostDate()) %>
 | 
			
		||||
    </EM>)
 | 
			
		||||
    <%-- TODO: paperclip goes here if we have an attachment --%>
 | 
			
		||||
  </FONT><P>
 | 
			
		||||
  <% if (msg.isScribbled()) { %>
 | 
			
		||||
    <TT><EM><B>
 | 
			
		||||
      (Scribbled by <%= data.getMessageBodyText(msg) %> on
 | 
			
		||||
      <%= rdat.formatDateForDisplay(msg.getScribbleDate()) %>)
 | 
			
		||||
    </B></EM></TT>
 | 
			
		||||
  <% } else if (msg.isHidden() && !(data.showAdvanced())) { %>
 | 
			
		||||
    <TT><EM><B>
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&shac=1&p1="
 | 
			
		||||
                                              + String.valueOf(msg.getPostNumber())) %>">(Hidden
 | 
			
		||||
      Message: <%= msg.getNumLines() %> <% if (msg.getNumLines()==1) { %>Line<% } else { %>Lines<% } %></A>
 | 
			
		||||
    </B></EM></TT>
 | 
			
		||||
  <% } else { %>
 | 
			
		||||
    <PRE><%= data.getMessageBodyText(msg) %></PRE>
 | 
			
		||||
  <% } // end if %>
 | 
			
		||||
  <% if (data.showAdvanced()) { %>
 | 
			
		||||
    </TD><TD NOWRAP ALIGN=RIGHT>
 | 
			
		||||
      <% if (!(msg.isScribbled())) { %>
 | 
			
		||||
        <% if (msg.canHide()) { %>
 | 
			
		||||
          <% if (msg.isHidden()) { %>
 | 
			
		||||
            <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
             SRC="<%= rdat.getFullImagePath("bn_show.gif") %>" ALT="Show" WIDTH=80 HEIGHT=24 BORDER=0></A><P>
 | 
			
		||||
          <% } else { %>
 | 
			
		||||
            <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
             SRC="<%= rdat.getFullImagePath("bn_hide.gif") %>" ALT="Hide" WIDTH=80 HEIGHT=24 BORDER=0></A><P>
 | 
			
		||||
          <% } // end if %>
 | 
			
		||||
        <% } // end if (can hide) %> 
 | 
			
		||||
        <% if (msg.canScribble()) { %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_scribble.gif") %>" ALT="Scribble" WIDTH=80 HEIGHT=24
 | 
			
		||||
           BORDER=0></A><P>
 | 
			
		||||
        <% } // end if (can scribble) %> 
 | 
			
		||||
      <% } // end if (not already scribbled) %> 
 | 
			
		||||
      <% if (msg.canNuke()) { %>
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_nuke.gif") %>" ALT="Nuke" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A><P>
 | 
			
		||||
      <% } // end if (can nuke) %> 
 | 
			
		||||
    </TD></TR></TABLE><BR>
 | 
			
		||||
  <% } // end if (showing advanced controls) %>
 | 
			
		||||
  <% can_line = true; %>
 | 
			
		||||
<% } // end while %>
 | 
			
		||||
<% if (rdat.useHTMLComments()) { %><!-- End Actual Messages --><% } %>
 | 
			
		||||
 | 
			
		||||
<TABLE BORDER=0 WIDTH="100%" CELLPADDING=0 CELLSPACING=0>
 | 
			
		||||
  <TR VALIGN=BOTTOM>
 | 
			
		||||
    <TD NOWRAP ALIGN=LEFT> </TD>
 | 
			
		||||
    <TD NOWRAP ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
      <% if (rdat.useHTMLComments()) { %><!-- Upper navigation linkset --><% } %>
 | 
			
		||||
      <%-- TODO: the number "20" should be configurable --%>
 | 
			
		||||
      <A NAME="bottom">[</A> 
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&p1=0&p2=-1") %>">View All</A>
 | 
			
		||||
      <% if (data.canScrollUp()) { %>
 | 
			
		||||
         | 
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&"
 | 
			
		||||
                                                + data.getScrollUpLocator()) %>">Scroll Up 20</A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
      <% if (data.canScrollDown()) { %>
 | 
			
		||||
         | 
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&"
 | 
			
		||||
                                                + data.getScrollDownLocator()) %>">Scroll Down 20</A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
      <% if (data.canScrollDown()) { %>
 | 
			
		||||
         | 
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getLocator() + "&"
 | 
			
		||||
                                                + data.getScrollToEndLocator()) %>">Scroll To End</A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
       | 
 | 
			
		||||
      <A HREF="#top">Top</A>
 | 
			
		||||
       ]
 | 
			
		||||
    </FONT></TD>
 | 
			
		||||
  </TR>
 | 
			
		||||
  <TR VALIGN=BOTTOM>
 | 
			
		||||
    <TD NOWRAP ALIGN=LEFT>
 | 
			
		||||
      <% if (rdat.useHTMLComments()) { %><!-- Topic user controls section --><% } %>
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getConfLocator()) %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_topic_list.gif") %>" ALT="Topic List" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
        
 | 
			
		||||
      <% if (data.isTopicHidden()) { %>
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_show_topic.gif") %>" ALT="Show Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
      <% } else { %>
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("TODO?" + data.getLocator()) %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_hide_topic.gif") %>" ALT="Hide Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
        
 | 
			
		||||
      <% if (data.canDoNextTopic()) { %>
 | 
			
		||||
        <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getNextLocator() + "&rnm=1") %>"><IMG
 | 
			
		||||
         SRC="<%= rdat.getFullImagePath("bn_next_topic.gif") %>" ALT="Next Topic" WIDTH=80 HEIGHT=24
 | 
			
		||||
         BORDER=0></A>
 | 
			
		||||
          
 | 
			
		||||
        <% if (data.getNewMessages()>0) { %>
 | 
			
		||||
          <%-- TODO: this doesn't do Keep New yet --%>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getNextLocator() + "&rnm=1") %>"><IMG
 | 
			
		||||
           SRC="<%= rdat.getFullImagePath("bn_next_keep_new.gif") %>" ALT="Next & Keep New" WIDTH=80 HEIGHT=24
 | 
			
		||||
           BORDER=0></A>
 | 
			
		||||
            
 | 
			
		||||
        <% } // end if %>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
    </TD>
 | 
			
		||||
    <TD NOWRAP ALIGN=RIGHT> </TD>
 | 
			
		||||
  </TR>
 | 
			
		||||
</TABLE>
 | 
			
		||||
 | 
			
		||||
<% if (data.displayPostBox()) { %>
 | 
			
		||||
  <HR><%= rdat.getStdFontTag(null,3) %><B>Post Message in "<%= data.getTopicName() %>":</B></FONT>
 | 
			
		||||
  <BR>
 | 
			
		||||
  <FORM METHOD="POST" ACTION="<%= rdat.getEncodedServletPath("post") %>">
 | 
			
		||||
    <INPUT TYPE="HIDDEN" NAME="sig" VALUE="<%= data.getSIGID() %>">
 | 
			
		||||
    <INPUT TYPE="HIDDEN" NAME="conf" VALUE="<%= data.getConfID() %>">
 | 
			
		||||
    <INPUT TYPE="HIDDEN" NAME="top" VALUE="<%= data.getTopicNumber() %>">
 | 
			
		||||
    <% if (data.canDoNextTopic()) { %>
 | 
			
		||||
      <INPUT TYPE="HIDDEN" NAME="next" VALUE="<%= data.getNextTopicNumber() %>">
 | 
			
		||||
    <% } // end if %>
 | 
			
		||||
    <INPUT TYPE="HIDDEN" NAME="sd" VALUE="<%= data.getTotalMessages() %>">
 | 
			
		||||
    <TABLE BORDER=0 CELLPADDING=0>
 | 
			
		||||
      <TR><TD ALIGN=LEFT COLSPAN=2>
 | 
			
		||||
        <%= rdat.getStdFontTag(null,2) %>Your name/header:</FONT><BR>
 | 
			
		||||
        <INPUT TYPE="TEXT" NAME="pseud" SIZE=37 MAXLENGTH=255 VALUE="<%= data.getDefaultPseud() %>">
 | 
			
		||||
        <%= rdat.getStdFontTag(null,2) %><INPUT TYPE="CHECKBOX" NAME="attach" VALUE="Y"> Attach a file</FONT>
 | 
			
		||||
      </TD></TR>
 | 
			
		||||
      <TR>
 | 
			
		||||
        <TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>Message:</FONT></TD>
 | 
			
		||||
        <TD ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
          <A HREF="TODO" TARGET="_blank">HTML Guide</A>
 | 
			
		||||
        </FONT></TD>
 | 
			
		||||
      </TR>
 | 
			
		||||
      <TR><TD ALIGN=LEFT COLSPAN=2>
 | 
			
		||||
        <TEXTAREA NAME="pb" WRAP=SOFT ROWS=7 COLS=51></TEXTAREA>
 | 
			
		||||
      </TD></TR>
 | 
			
		||||
      <TR><TD ALIGN=CENTER COLSPAN=2>
 | 
			
		||||
        <INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_preview.gif") %>" ALT="Preview" NAME="preview"
 | 
			
		||||
         WIDTH=80 HEIGHT=24 BORDER=0>
 | 
			
		||||
          
 | 
			
		||||
        <INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_post_reload.gif") %>" ALT="Post & Reload"
 | 
			
		||||
         NAME="post" WIDTH=80 HEIGHT=24 BORDER=0>
 | 
			
		||||
        <% if (data.canDoNextTopic()) { %>
 | 
			
		||||
            
 | 
			
		||||
          <INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_post_go_next.gif") %>" ALT="Post & Go Next"
 | 
			
		||||
           NAME="postnext" WIDTH=80 HEIGHT=24 BORDER=0>
 | 
			
		||||
        <% } // end if %>
 | 
			
		||||
      </TD></TR>
 | 
			
		||||
    </TABLE>
 | 
			
		||||
  </FORM>
 | 
			
		||||
<% } else if (data.isTopicArchived()) { %>
 | 
			
		||||
  <DIV ALIGN=CENTER><%= rdat.getStdFontTag(null,2) %><B>This is an <EM>Archived</EM> Topic</B></DIV>
 | 
			
		||||
<% } else if (data.isTopicFrozen()) { %>
 | 
			
		||||
  <DIV ALIGN=CENTER><%= rdat.getStdFontTag(null,2) %><B>This is a <EM>Frozen</EM> Topic</B></DIV>
 | 
			
		||||
<% } // end if %>
 | 
			
		||||
<% rdat.writeFooter(out); %>
 | 
			
		||||
							
								
								
									
										81
									
								
								web/format/preview.jsp
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,81 @@
 | 
			
		||||
<%--
 | 
			
		||||
  The contents of this file are subject to the Mozilla Public License Version 1.1
 | 
			
		||||
  (the "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 | 
			
		||||
  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 | 
			
		||||
  WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 | 
			
		||||
  language governing rights and limitations under the License.
 | 
			
		||||
  
 | 
			
		||||
  The Original Code is the Venice Web Communities System.
 | 
			
		||||
  
 | 
			
		||||
  The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
  for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
  Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 | 
			
		||||
 | 
			
		||||
  Contributor(s): 
 | 
			
		||||
--%>
 | 
			
		||||
<%@ page import = "java.util.*" %>
 | 
			
		||||
<%@ page import = "com.silverwrist.util.StringUtil" %>
 | 
			
		||||
<%@ page import = "com.silverwrist.venice.core.*" %>
 | 
			
		||||
<%@ page import = "com.silverwrist.venice.servlets.Variables" %>
 | 
			
		||||
<%@ page import = "com.silverwrist.venice.servlets.format.*" %>
 | 
			
		||||
<%
 | 
			
		||||
  PostPreview data = PostPreview.retrieve(request);
 | 
			
		||||
  Variables.failIfNull(data);
 | 
			
		||||
  RenderData rdat = RenderConfig.createRenderData(application,request,response);
 | 
			
		||||
%>
 | 
			
		||||
<% rdat.writeContentHeader(out,"Previewing Post",null); %>
 | 
			
		||||
<%= rdat.getStdFontTag(null,3) %><B>
 | 
			
		||||
  <% if (data.getNumSpellingErrors()==0) { %>
 | 
			
		||||
    Your post did not contain any spelling errors.
 | 
			
		||||
  <% } else if (data.getNumSpellingErrors()==1) { %>
 | 
			
		||||
    There was 1 spelling error in your post.
 | 
			
		||||
  <% } else { %>
 | 
			
		||||
    There were <%= data.getNumSpellingErrors() %> spelling errors in your post.
 | 
			
		||||
  <% } // end if %>
 | 
			
		||||
</B></FONT>
 | 
			
		||||
<P><PRE><%= data.getPreviewData() %></PRE><HR>
 | 
			
		||||
 | 
			
		||||
<FORM METHOD="POST" ACTION="<%= rdat.getEncodedServletPath("post") %>">
 | 
			
		||||
  <INPUT TYPE="HIDDEN" NAME="sig" VALUE="<%= data.getSIGID() %>">
 | 
			
		||||
  <INPUT TYPE="HIDDEN" NAME="conf" VALUE="<%= data.getConfID() %>">
 | 
			
		||||
  <INPUT TYPE="HIDDEN" NAME="top" VALUE="<%= data.getTopicNumber() %>">
 | 
			
		||||
  <% if (!(StringUtil.isStringEmpty(data.getNextVal()))) { %>
 | 
			
		||||
    <INPUT TYPE="HIDDEN" NAME="next" VALUE="<%= data.getNextVal() %>">
 | 
			
		||||
  <% } // end if %>
 | 
			
		||||
  <INPUT TYPE="HIDDEN" NAME="sd" VALUE="<%= data.getTotalMessages() %>">
 | 
			
		||||
  <TABLE BORDER=0 CELLPADDING=0>
 | 
			
		||||
    <TR><TD ALIGN=LEFT COLSPAN=2>
 | 
			
		||||
      <%= rdat.getStdFontTag(null,2) %>Your name/header:</FONT><BR>
 | 
			
		||||
      <INPUT TYPE="TEXT" NAME="pseud" SIZE=37 MAXLENGTH=255 VALUE="<%= data.getPseud() %>">
 | 
			
		||||
      <%= rdat.getStdFontTag(null,2) %><INPUT TYPE="CHECKBOX" NAME="attach"
 | 
			
		||||
          VALUE="Y" <% if (data.attachChecked()) { %>CHECKED<% } %> > Attach a file</FONT>
 | 
			
		||||
    </TD></TR>
 | 
			
		||||
    <TR>
 | 
			
		||||
      <TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>Message:</FONT></TD>
 | 
			
		||||
      <TD ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
        <A HREF="TODO" TARGET="_blank">HTML Guide</A>
 | 
			
		||||
      </FONT></TD>
 | 
			
		||||
    </TR>
 | 
			
		||||
    <TR><TD ALIGN=LEFT COLSPAN=2>
 | 
			
		||||
      <TEXTAREA NAME="pb" WRAP=SOFT ROWS=7 COLS=51><%= data.getBodyText() %></TEXTAREA>
 | 
			
		||||
    </TD></TR>
 | 
			
		||||
    <TR><TD ALIGN=CENTER COLSPAN=2>
 | 
			
		||||
      <INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_preview.gif") %>" ALT="Preview" NAME="preview"
 | 
			
		||||
       WIDTH=80 HEIGHT=24 BORDER=0>
 | 
			
		||||
        
 | 
			
		||||
      <INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_post_reload.gif") %>" ALT="Post & Reload"
 | 
			
		||||
       NAME="post" WIDTH=80 HEIGHT=24 BORDER=0>
 | 
			
		||||
      <% if (!(StringUtil.isStringEmpty(data.getNextVal()))) { %>
 | 
			
		||||
          
 | 
			
		||||
        <INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_post_go_next.gif") %>" ALT="Post & Go Next"
 | 
			
		||||
         NAME="postnext" WIDTH=80 HEIGHT=24 BORDER=0>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
        
 | 
			
		||||
      <INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_cancel.gif") %>" ALT="Cancel"
 | 
			
		||||
       NAME="cancel" WIDTH=80 HEIGHT=24 BORDER=0>
 | 
			
		||||
    </TD></TR>
 | 
			
		||||
  </TABLE>
 | 
			
		||||
</FORM>
 | 
			
		||||
<% rdat.writeFooter(out); %>
 | 
			
		||||
							
								
								
									
										107
									
								
								web/format/slippage.jsp
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,107 @@
 | 
			
		||||
<%--
 | 
			
		||||
  The contents of this file are subject to the Mozilla Public License Version 1.1
 | 
			
		||||
  (the "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 | 
			
		||||
 | 
			
		||||
  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 | 
			
		||||
  WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 | 
			
		||||
  language governing rights and limitations under the License.
 | 
			
		||||
  
 | 
			
		||||
  The Original Code is the Venice Web Communities System.
 | 
			
		||||
  
 | 
			
		||||
  The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 | 
			
		||||
  for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 | 
			
		||||
  Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 | 
			
		||||
 | 
			
		||||
  Contributor(s): 
 | 
			
		||||
--%>
 | 
			
		||||
<%@ page import = "java.util.*" %>
 | 
			
		||||
<%@ page import = "com.silverwrist.util.StringUtil" %>
 | 
			
		||||
<%@ page import = "com.silverwrist.venice.core.*" %>
 | 
			
		||||
<%@ page import = "com.silverwrist.venice.servlets.Variables" %>
 | 
			
		||||
<%@ page import = "com.silverwrist.venice.servlets.format.*" %>
 | 
			
		||||
<%
 | 
			
		||||
  PostSlippage data = PostSlippage.retrieve(request);
 | 
			
		||||
  Variables.failIfNull(data);
 | 
			
		||||
  RenderData rdat = RenderConfig.createRenderData(application,request,response);
 | 
			
		||||
%>
 | 
			
		||||
<% if (rdat.useHTMLComments()) { %><!-- <%= data.getIdentifyingData() %> --><% } %>
 | 
			
		||||
<% rdat.writeContentHeader(out,"Slippage or Double-Click Detected",null); %>
 | 
			
		||||
<%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
  The following posts slipped in while you were typing.  You may choose to edit your message and
 | 
			
		||||
  re-post, just post it as is, or cancel your posting altogether.
 | 
			
		||||
</FONT>
 | 
			
		||||
 | 
			
		||||
<% if (rdat.useHTMLComments()) { %><!-- Begin Slipped Messages --><% } %>
 | 
			
		||||
<% Iterator it = data.getMessageIterator(); %>
 | 
			
		||||
<% while (it.hasNext()) { %>
 | 
			
		||||
  <%
 | 
			
		||||
    TopicMessageContext msg = (TopicMessageContext)(it.next());
 | 
			
		||||
    String poster = data.getPosterName(msg);
 | 
			
		||||
  %>
 | 
			
		||||
  <%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
    <B><%= msg.getPostNumber() %></B> of <B><%= data.getTotalMessages() - 1 %></B>
 | 
			
		||||
    <%= rdat.getStdFontTag(null,1) %><<%= "TODO" %>></FONT><BR>
 | 
			
		||||
    <B><%= msg.getPseud() %></B>
 | 
			
		||||
    (<EM>
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("user/" + poster) %>" TARGET="_blank"><%= poster %></A>,
 | 
			
		||||
      <%= rdat.formatDateForDisplay(msg.getPostDate()) %>
 | 
			
		||||
    </EM>)
 | 
			
		||||
  </FONT><P>
 | 
			
		||||
  <% if (msg.isScribbled()) { %>
 | 
			
		||||
    <TT><EM><B>
 | 
			
		||||
      (Scribbled by <%= data.getMessageBodyText(msg) %> on
 | 
			
		||||
      <%= rdat.formatDateForDisplay(msg.getScribbleDate()) %>)
 | 
			
		||||
    </B></EM></TT>
 | 
			
		||||
  <% } else { %>
 | 
			
		||||
    <PRE><%= data.getMessageBodyText(msg) %></PRE>
 | 
			
		||||
  <% } // end if %>
 | 
			
		||||
<% } // end while %>
 | 
			
		||||
<% if (rdat.useHTMLComments()) { %><!-- End Slipped Messages --><% } %>
 | 
			
		||||
 | 
			
		||||
<HR><%= rdat.getStdFontTag(null,3) %><B>Post Message in "<%= data.getTopicName() %>":</B></FONT>
 | 
			
		||||
<BR>
 | 
			
		||||
<FORM METHOD="POST" ACTION="<%= rdat.getEncodedServletPath("post") %>">
 | 
			
		||||
  <INPUT TYPE="HIDDEN" NAME="sig" VALUE="<%= data.getSIGID() %>">
 | 
			
		||||
  <INPUT TYPE="HIDDEN" NAME="conf" VALUE="<%= data.getConfID() %>">
 | 
			
		||||
  <INPUT TYPE="HIDDEN" NAME="top" VALUE="<%= data.getTopicNumber() %>">
 | 
			
		||||
  <% if (!(StringUtil.isStringEmpty(data.getNextVal()))) { %>
 | 
			
		||||
    <INPUT TYPE="HIDDEN" NAME="next" VALUE="<%= data.getNextVal() %>">
 | 
			
		||||
  <% } // end if %>
 | 
			
		||||
  <INPUT TYPE="HIDDEN" NAME="sd" VALUE="<%= data.getTotalMessages() %>">
 | 
			
		||||
  <TABLE BORDER=0 CELLPADDING=0>
 | 
			
		||||
    <TR><TD ALIGN=LEFT COLSPAN=2>
 | 
			
		||||
      <%= rdat.getStdFontTag(null,2) %>Your name/header:</FONT><BR>
 | 
			
		||||
      <INPUT TYPE="TEXT" NAME="pseud" SIZE=37 MAXLENGTH=255 VALUE="<%= data.getPseud() %>">
 | 
			
		||||
      <%= rdat.getStdFontTag(null,2) %><INPUT TYPE="CHECKBOX" NAME="attach"
 | 
			
		||||
          VALUE="Y" <% if (data.attachChecked()) { %>CHECKED<% } %> > Attach a file</FONT>
 | 
			
		||||
    </TD></TR>
 | 
			
		||||
    <TR>
 | 
			
		||||
      <TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>Message:</FONT></TD>
 | 
			
		||||
      <TD ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
        <A HREF="TODO" TARGET="_blank">HTML Guide</A>
 | 
			
		||||
      </FONT></TD>
 | 
			
		||||
    </TR>
 | 
			
		||||
    <TR><TD ALIGN=LEFT COLSPAN=2>
 | 
			
		||||
      <TEXTAREA NAME="pb" WRAP=SOFT ROWS=7 COLS=51><%= data.getBodyText() %></TEXTAREA>
 | 
			
		||||
    </TD></TR>
 | 
			
		||||
    <TR><TD ALIGN=CENTER COLSPAN=2>
 | 
			
		||||
      <INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_preview.gif") %>" ALT="Preview" NAME="preview"
 | 
			
		||||
       WIDTH=80 HEIGHT=24 BORDER=0>
 | 
			
		||||
        
 | 
			
		||||
      <INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_post_reload.gif") %>" ALT="Post & Reload"
 | 
			
		||||
       NAME="post" WIDTH=80 HEIGHT=24 BORDER=0>
 | 
			
		||||
      <% if (!(StringUtil.isStringEmpty(data.getNextVal()))) { %>
 | 
			
		||||
          
 | 
			
		||||
        <INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_post_go_next.gif") %>" ALT="Post & Go Next"
 | 
			
		||||
         NAME="postnext" WIDTH=80 HEIGHT=24 BORDER=0>
 | 
			
		||||
      <% } // end if %>
 | 
			
		||||
        
 | 
			
		||||
      <INPUT TYPE="IMAGE" SRC="<%= rdat.getFullImagePath("bn_cancel.gif") %>" ALT="Cancel"
 | 
			
		||||
       NAME="cancel" WIDTH=80 HEIGHT=24 BORDER=0>
 | 
			
		||||
    </TD></TR>
 | 
			
		||||
  </TABLE>
 | 
			
		||||
</FORM>
 | 
			
		||||
<% rdat.writeFooter(out); %>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -24,8 +24,7 @@
 | 
			
		||||
  TopicListing data = TopicListing.retrieve(request);
 | 
			
		||||
  Variables.failIfNull(data);
 | 
			
		||||
  RenderData rdat = RenderConfig.createRenderData(application,request,response);
 | 
			
		||||
  String self = "confdisp?sig=" + String.valueOf(data.getSIGID()) + "&conf="
 | 
			
		||||
	      + String.valueOf(data.getConfID());
 | 
			
		||||
  String self = "confdisp?" + data.getLocator();
 | 
			
		||||
  String tmp;
 | 
			
		||||
%>
 | 
			
		||||
<% if (rdat.useHTMLComments()) { %><!-- Topic list for conf #<%= data.getConfID() %> --><% } %>
 | 
			
		||||
@ -36,14 +35,14 @@
 | 
			
		||||
     SRC="<%= rdat.getFullImagePath("bn_conference_list.gif") %>" ALT="Conference List" WIDTH=80 HEIGHT=24
 | 
			
		||||
     BORDER=0></A>  
 | 
			
		||||
    <% if (data.canCreateTopic()) { %>
 | 
			
		||||
      <% tmp = "confops?sig=" + String.valueOf(data.getSIGID()) + "&conf="
 | 
			
		||||
             + String.valueOf(data.getConfID()) + "&cmd=T"; %>
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath(tmp) %>"><IMG SRC="<%= rdat.getFullImagePath("bn_add_topic.gif") %>"
 | 
			
		||||
       ALT="Add Topic" WIDTH=80 HEIGHT=24 BORDER=0></A>  
 | 
			
		||||
      <% tmp = rdat.getEncodedServletPath("confops?" + data.getLocator() + "&cmd=T"); %>
 | 
			
		||||
      <A HREF="<%= tmp %>"><IMG SRC="<%= rdat.getFullImagePath("bn_add_topic.gif") %>" ALT="Add Topic"
 | 
			
		||||
                            WIDTH=80 HEIGHT=24 BORDER=0></A>  
 | 
			
		||||
    <% } // end if %>
 | 
			
		||||
    <% if (data.canDoReadNew()) { %>
 | 
			
		||||
      <A HREF="TODO"><IMG SRC="<%= rdat.getFullImagePath("bn_read_new.gif") %>"
 | 
			
		||||
       ALT="Read New" WIDTH=80 HEIGHT=24 BORDER=0></A>  
 | 
			
		||||
      <A HREF="<%= rdat.getEncodedServletPath("confdisp?" + data.getNextLocator()) %>"><IMG
 | 
			
		||||
       SRC="<%= rdat.getFullImagePath("bn_read_new.gif") %>" ALT="Read New" WIDTH=80 HEIGHT=24
 | 
			
		||||
       BORDER=0></A>  
 | 
			
		||||
    <% } // end if %>
 | 
			
		||||
    <A HREF="TODO"><IMG SRC="<%= rdat.getFullImagePath("bn_manage.gif") %>"
 | 
			
		||||
     ALT="Manage" WIDTH=80 HEIGHT=24 BORDER=0></A>  
 | 
			
		||||
@ -59,52 +58,61 @@
 | 
			
		||||
          <% tmp = self + "&sort="
 | 
			
		||||
                 + String.valueOf(data.isSort(ConferenceContext.SORT_NUMBER) ? -ConferenceContext.SORT_NUMBER
 | 
			
		||||
                                                                          : ConferenceContext.SORT_NUMBER); %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath(tmp) %>">#</A>
 | 
			
		||||
          <B><A HREF="<%= rdat.getEncodedServletPath(tmp) %>">#</A></B>
 | 
			
		||||
        </FONT></TD>
 | 
			
		||||
        <TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
          <% tmp = self + "&sort="
 | 
			
		||||
                 + String.valueOf(data.isSort(ConferenceContext.SORT_NAME) ? -ConferenceContext.SORT_NAME
 | 
			
		||||
                                                                           : ConferenceContext.SORT_NAME); %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath(tmp) %>">Topic Name</A>
 | 
			
		||||
          <B><A HREF="<%= rdat.getEncodedServletPath(tmp) %>">Topic Name</A></B>
 | 
			
		||||
        </FONT></TD>
 | 
			
		||||
        <TD ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
          <% tmp = self + "&sort="
 | 
			
		||||
                 + String.valueOf(data.isSort(ConferenceContext.SORT_UNREAD) ? -ConferenceContext.SORT_UNREAD
 | 
			
		||||
                                                                           : ConferenceContext.SORT_UNREAD); %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath(tmp) %>">New</A>
 | 
			
		||||
          <B><A HREF="<%= rdat.getEncodedServletPath(tmp) %>">New</A></B>
 | 
			
		||||
        </FONT></TD>
 | 
			
		||||
        <TD ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
          <% tmp = self + "&sort="
 | 
			
		||||
                 + String.valueOf(data.isSort(ConferenceContext.SORT_TOTAL) ? -ConferenceContext.SORT_TOTAL
 | 
			
		||||
                                                                            : ConferenceContext.SORT_TOTAL); %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath(tmp) %>">Total</A>
 | 
			
		||||
          <B><A HREF="<%= rdat.getEncodedServletPath(tmp) %>">Total</A></B>
 | 
			
		||||
        </FONT></TD>
 | 
			
		||||
        <TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
          <% tmp = self + "&sort="
 | 
			
		||||
                 + String.valueOf(data.isSort(ConferenceContext.SORT_DATE) ? -ConferenceContext.SORT_DATE
 | 
			
		||||
                                                                           : ConferenceContext.SORT_DATE); %>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath(tmp) %>">Last Response</A>
 | 
			
		||||
          <B><A HREF="<%= rdat.getEncodedServletPath(tmp) %>">Last Response</A></B>
 | 
			
		||||
        </FONT></TD>
 | 
			
		||||
      </TR>
 | 
			
		||||
      <TR VALIGN=TOP><TD ALIGN=LEFT COLSPAN=5><%= rdat.getStdFontTag(null,2) %> </FONT></TD></TR>
 | 
			
		||||
      <% Iterator it = data.getTopicIterator(); %>
 | 
			
		||||
      <% while (it.hasNext()) { %>
 | 
			
		||||
        <% TopicContext topic = (TopicContext)(it.next()); %>
 | 
			
		||||
        <%
 | 
			
		||||
          TopicContext topic = (TopicContext)(it.next());
 | 
			
		||||
          tmp = self + "&top=" + String.valueOf(topic.getTopicNumber()) + "&rnm=1";
 | 
			
		||||
        %>
 | 
			
		||||
        <TR VALIGN=TOP>
 | 
			
		||||
          <TD ALIGN=LEFT WIDTH="1%"><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
	    <A HREF="TODO"><%= topic.getTopicNumber() %></A>
 | 
			
		||||
	    <A HREF="<%= rdat.getEncodedServletPath(tmp) %>"><%= topic.getTopicNumber() %></A>  
 | 
			
		||||
          </FONT></TD>
 | 
			
		||||
          <TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
            <A HREF="TODO"><%= topic.getName() %></A>
 | 
			
		||||
            <A HREF="<%= rdat.getEncodedServletPath(tmp) %>"><%= topic.getName() %></A>
 | 
			
		||||
            <% if (topic.isArchived() && !(data.isView(ConferenceContext.DISPLAY_ARCHIVED))) { %>
 | 
			
		||||
              <EM>(archived)</EM>
 | 
			
		||||
            <% } else if (topic.isFrozen()) { %>
 | 
			
		||||
              <EM>(frozen)</EM>
 | 
			
		||||
            <% } // end if %>
 | 
			
		||||
          </FONT></TD>
 | 
			
		||||
          <TD ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
            <A HREF="TODO"><%= topic.getUnreadMessages() %></A>
 | 
			
		||||
            <A HREF="<%= rdat.getEncodedServletPath(tmp) %>"><%= topic.getUnreadMessages() %></A>
 | 
			
		||||
          </FONT></TD>
 | 
			
		||||
          <TD ALIGN=RIGHT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
            <A HREF="TODO"><%= topic.getTotalMessages() %></A>
 | 
			
		||||
          <A HREF="<%= rdat.getEncodedServletPath(self + "&top=" + String.valueOf(topic.getTopicNumber())
 | 
			
		||||
                                                  + "&p1=0&p2=-1") %>"><%= topic.getTotalMessages() %></A>
 | 
			
		||||
          </FONT></TD>
 | 
			
		||||
          <TD ALIGN=LEFT><%= rdat.getStdFontTag(null,2) %>
 | 
			
		||||
            <A HREF="TODO"><%= rdat.formatDateForDisplay(topic.getLastUpdateDate()) %></A>
 | 
			
		||||
            <A HREF="<%= rdat.getEncodedServletPath(tmp) %>"><%= rdat.formatDateForDisplay(topic.getLastUpdateDate()) %></A>
 | 
			
		||||
          </FONT></TD>
 | 
			
		||||
        </TR>
 | 
			
		||||
      <% } // end while (more topics in enumeration) %>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_archive_topic.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 979 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_delete_topic.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 969 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_freeze_topic.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_go.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 879 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_hide.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 906 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_hide_topic.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 969 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_next_keep_new.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.0 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_next_topic.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 951 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_nuke.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 910 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_post_go_next.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 997 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_post_reload.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_scribble.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 949 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_show.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 917 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_show_topic.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 980 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_topic_list.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 950 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_unarchive_topic.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1004 B  | 
							
								
								
									
										
											BIN
										
									
								
								web/images/bn_unfreeze_topic.gif
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1015 B  |