diff --git a/TODO b/TODO index 4f9e33d..005eaaa 100644 --- a/TODO +++ b/TODO @@ -25,19 +25,6 @@ Lots! statements in the case of joined queries (no need to SELECT table.column AS name). -- Functions still to do on conferencing "posts" page: - Hide/Show Topic - Next & Keep New (make it actually Keep New) - Freeze/Unfreeze Topic - Archive/Unarchive Topic - Delete Topic - Make number of "viewable" posts per page a config option - Display the message locator (i.e. ) above each message - Hide/Show Post - Scribble Post - Nuke Post - Put the HTML Guide in (for all pages w/post boxes) - - Slippage during posting is still untested. - Functions still to do on conferencing "topics" page: diff --git a/etc/erbo.dict b/etc/erbo.dict index 7a6d8e7..1f8a59e 100644 --- a/etc/erbo.dict +++ b/etc/erbo.dict @@ -30,6 +30,7 @@ fucking hairstyle hairstyles hasn't +haven't he'd html i'd diff --git a/etc/render-config.xml b/etc/render-config.xml index fbc4dc0..3f56759 100644 --- a/etc/render-config.xml +++ b/etc/render-config.xml @@ -43,6 +43,9 @@ http://delenn:8080/venice/images/ + + http://delenn:8080/venice/static/ + http://delenn:8080/venice/images/powered-by-venice.gif diff --git a/etc/web.xml b/etc/web.xml index d77b804..0b71c40 100644 --- a/etc/web.xml +++ b/etc/web.xml @@ -11,7 +11,7 @@ WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. - The Original Code is the Venice Web Community System. + The Original Code is the Venice Web Communities System. The Initial Developer of the Original Code is Eric J. Bowersox , for Silverwrist Design Studios. Portions created by Eric J. Bowersox are @@ -21,9 +21,9 @@ --> - Venice Web Community System + Venice Web Communities System - The Venice Web conferencing system provides an online conferencing + The Venice Web Communities System provides an online conferencing environment, including discussions, online services, and other things. Written by Eric J. Bowersox (erbo@silcom.com). @@ -158,6 +158,30 @@ com.silverwrist.venice.servlets.Attachment + + topicoperations + + General topic operations. + + com.silverwrist.venice.servlets.TopicOperations + + + + postoperations + + General post operations. + + com.silverwrist.venice.servlets.PostOperations + + + + postshortcut + + Processes post links and redirects to the appropriate page. + + com.silverwrist.venice.servlets.PostShortcut + + @@ -226,6 +250,21 @@ /attachment + + topicoperations + /topicops + + + + postoperations + /postops + + + + postshortcut + /go/* + + testformdata diff --git a/setup/database.sql b/setup/database.sql index 32bfe4d..d83d0e2 100644 --- a/setup/database.sql +++ b/setup/database.sql @@ -30,6 +30,14 @@ USE venice; # Table Creation ############################################################################## +# The global parameters table. This is used for stuff that a Venice admin would be +# likely to edit "on the fly." Stuff that can only be updated with a shutdown should go +# in the XML config file. This table has ONLY ONE ROW! +CREATE TABLE globals ( + posts_per_page INT NOT NULL, + old_posts_at_top INT NOT NULL +); + # The audit records table. Most "major" events add a record to this table. CREATE TABLE audit ( record BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, @@ -1282,6 +1290,10 @@ INSERT INTO refsigftr (ftr_code, is_default, is_locked, is_hidden, require_read, # Database Initialization ############################################################################## +# Initialize the system globals table. +INSERT INTO globals (posts_per_page, old_posts_at_top) + VALUES (20, 2); + # Add the 'Anonymous Honyak' user to the users table. # (Do 'SELECT * FROM users WHERE is_anon = 1' to retrieve the AC user details.) # (UID = 1, CONTACTID = 1) diff --git a/src/com/silverwrist/venice/core/ConferenceContext.java b/src/com/silverwrist/venice/core/ConferenceContext.java index 91838d3..9d3150b 100644 --- a/src/com/silverwrist/venice/core/ConferenceContext.java +++ b/src/com/silverwrist/venice/core/ConferenceContext.java @@ -19,6 +19,7 @@ package com.silverwrist.venice.core; import java.util.Date; import java.util.List; +import com.silverwrist.venice.htmlcheck.HTMLChecker; public interface ConferenceContext { @@ -114,4 +115,6 @@ public interface ConferenceContext public abstract TopicMessageContext getMessageByPostID(long postid) throws DataException, AccessError; + public abstract HTMLChecker getNewTopicPreviewChecker(); + } // end interface ConferenceContext diff --git a/src/com/silverwrist/venice/core/IDUtils.java b/src/com/silverwrist/venice/core/IDUtils.java index a891869..f9072f7 100644 --- a/src/com/silverwrist/venice/core/IDUtils.java +++ b/src/com/silverwrist/venice/core/IDUtils.java @@ -7,7 +7,7 @@ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * - * The Original Code is the Venice Web Community System. + * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are @@ -72,4 +72,30 @@ public class IDUtils } // end isValidConfirmationNumber + public static boolean isValidVeniceIDChar(char c) + { + if ((c>='A') && (c<='Z')) + return true; // upper-case letters are OK + if ((c>='a') && (c<='z')) + return true; // lower-case letters are OK + if ((c>='0') && (c<='9')) + return true; // digits are OK + return (EXTRA_VALID.indexOf(c)>=0); + + } // end isValidVeniceIDChar + + public static boolean isValidPostLinkChar(char c) + { + if ((c>='A') && (c<='Z')) + return true; // upper-case letters are OK + if ((c>='a') && (c<='z')) + return true; // lower-case letters are OK + if ((c>='0') && (c<='9')) + return true; // digits are OK + if (EXTRA_VALID.indexOf(c)>=0) + return true; // other characters from Venice IDs are OK + return ((c=='.') || (c=='!')); // also dots and bangs + + } // end isValidPostLinkChar + } // end class IDUtils diff --git a/src/com/silverwrist/venice/core/TopicContext.java b/src/com/silverwrist/venice/core/TopicContext.java index ee350f3..2a8f528 100644 --- a/src/com/silverwrist/venice/core/TopicContext.java +++ b/src/com/silverwrist/venice/core/TopicContext.java @@ -19,6 +19,7 @@ package com.silverwrist.venice.core; import java.util.Date; import java.util.List; +import com.silverwrist.venice.htmlcheck.HTMLChecker; public interface TopicContext { @@ -71,4 +72,11 @@ public interface TopicContext public abstract TopicMessageContext postNewMessage(long parent, String pseud, String text) throws DataException, AccessError; + public abstract HTMLChecker getPreviewChecker(); + + public abstract boolean canDelete(); + + public abstract void delete() throws DataException, AccessError; + } // end interface TopicContext + diff --git a/src/com/silverwrist/venice/core/VeniceEngine.java b/src/com/silverwrist/venice/core/VeniceEngine.java index abfbb0a..f17bdb1 100644 --- a/src/com/silverwrist/venice/core/VeniceEngine.java +++ b/src/com/silverwrist/venice/core/VeniceEngine.java @@ -61,8 +61,10 @@ public interface VeniceEngine extends SearchMode public abstract boolean confAliasExists(String alias); - public abstract HTMLChecker getPreviewChecker(); - public abstract HTMLChecker getEscapingChecker(); + public abstract int getNumPostsPerPage(); + + public abstract int getNumOldPostsBeforeNew(); + } // end interface VeniceEngine diff --git a/src/com/silverwrist/venice/core/impl/BackgroundTopicPurge.java b/src/com/silverwrist/venice/core/impl/BackgroundTopicPurge.java new file mode 100644 index 0000000..c7b9d95 --- /dev/null +++ b/src/com/silverwrist/venice/core/impl/BackgroundTopicPurge.java @@ -0,0 +1,112 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.core.impl; + +import java.sql.*; +import org.apache.log4j.*; +import com.silverwrist.venice.db.*; + +class BackgroundTopicPurge implements Runnable +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Category logger = Category.getInstance(BackgroundTopicPurge.class.getName()); + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private DataPool datapool; + private int topicid; + private int num_posts; + private long max_postid; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + BackgroundTopicPurge(DataPool datapool, int topicid, int num_posts, long max_postid) + { + this.datapool = datapool; + this.topicid = topicid; + this.num_posts = num_posts; + this.max_postid = max_postid; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Implementations from interface Runnable + *-------------------------------------------------------------------------------- + */ + + public void run() + { + if (logger.isDebugEnabled()) + logger.debug("BackgroundTopicPurge running on topic #" + String.valueOf(topicid)); + + long[] postids = new long[num_posts]; // stores the post IDs + Connection conn = null; // pooled database connection + + try + { // get a database connection from the pool + conn = datapool.getConnection(); + Statement stmt = conn.createStatement(); + + // look up all the post IDs that are present for this topic + StringBuffer sql = new StringBuffer("SELECT postid FROM posts WHERE topicid = "); + sql.append(topicid).append(" AND postid <= ").append(max_postid).append(" ORDER BY postid;"); + ResultSet rs = stmt.executeQuery(sql.toString()); + int posts = 0; + while (rs.next()) + postids[posts++] = rs.getLong(1); + + for (int i=0; i, * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are @@ -27,6 +27,13 @@ import com.silverwrist.venice.core.IDUtils; public class PostLinkRewriter implements Rewriter { + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + public static final String URI_PREFIX = "x-postlink:"; + /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- @@ -52,7 +59,7 @@ public class PostLinkRewriter implements Rewriter private static String buildPostLink(PostLinkDecoder pl, PostLinkDecoderContext ctxt) { - StringBuffer b = new StringBuffer("x-postlink:"); + StringBuffer b = new StringBuffer(URI_PREFIX); boolean started = false; if (pl.getSIG()==null) b.append(ctxt.getSIGName()); diff --git a/src/com/silverwrist/venice/db/UserNameRewriter.java b/src/com/silverwrist/venice/db/UserNameRewriter.java index 9b44d17..408e9e5 100644 --- a/src/com/silverwrist/venice/db/UserNameRewriter.java +++ b/src/com/silverwrist/venice/db/UserNameRewriter.java @@ -7,7 +7,7 @@ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * - * The Original Code is the Venice Web Community System. + * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are @@ -26,6 +26,13 @@ import com.silverwrist.venice.core.IDUtils; public class UserNameRewriter implements Rewriter { + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + public static final String URI_PREFIX = "x-userlink:"; + /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- @@ -85,8 +92,9 @@ public class UserNameRewriter implements Rewriter } // end finally - StringBuffer open_a = new StringBuffer("=20)) // TODO: configurable - first = last - 20; + if ((ur==0) || (ur>=engine.getNumPostsPerPage())) + first = last - engine.getNumPostsPerPage(); else - first = last - (ur+2); + first = last - (ur + engine.getNumOldPostsBeforeNew()); last--; } // end if @@ -324,6 +324,72 @@ public class ConfDisplay extends VeniceServlet } // end getInterval + private static void restorePosts(ServletRequest request, ConferenceContext conf) + { + String xtopic = request.getParameter("rtop"); + if (StringUtil.isStringEmpty(xtopic)) + return; + String xcount = request.getParameter("rct"); + if (StringUtil.isStringEmpty(xcount)) + return; + + TopicContext topic; + try + { // get the topic corresponding to the first parameter + topic = conf.getTopic(Short.parseShort(xtopic)); + + } // end try + catch (NumberFormatException nfe) + { // the topic number was invalid - forget it + logger.warn("restorePosts: error translating topic number"); + return; + + } // end catch + catch (DataException de) + { // could not get the topic... + logger.warn("restorePosts: DataException getting topic - " + de.getMessage(),de); + return; + + } // end catch + catch (AccessError ae) + { // no access to the topic + logger.warn("restorePosts: AccessError getting topic - " + ae.getMessage(),ae); + return; + + } // end catch + + int nunread; + try + { // translate the number of unread posts to set + nunread = Integer.parseInt(xcount); + if ((nunread<=0) || (nunread>topic.getTotalMessages())) + { // must be in the range [1, #messages]... + logger.warn("restorePosts: unread post count out of range"); + return; + + } // end if + + } // end try + catch (NumberFormatException nfe) + { // the number of unread posts was invalid - forget it + logger.warn("restorePosts: error translating unread post count"); + return; + + } // end catch + + try + { // now try to set the unread messages + topic.setUnreadMessages(nunread); + + } // end try + catch (DataException de) + { // could not get the topic... + logger.warn("restorePosts: DataException setting unread messages - " + de.getMessage(),de); + + } // end catch + + } // end restorePosts + /*-------------------------------------------------------------------------------- * Overrides from class HttpServlet *-------------------------------------------------------------------------------- @@ -428,14 +494,18 @@ public class ConfDisplay extends VeniceServlet if (logger.isDebugEnabled()) logger.debug("MODE: display messages in topic"); + // if this request is restoring the number of unread posts in another topic, try to do so + restorePosts(request,conf); + try { // determine what the post interval is we want to display - PostInterval piv = getInterval(request,topic); + VeniceEngine engine = getVeniceEngine(); + PostInterval piv = getInterval(engine,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(), + TopicPosts tpos = new TopicPosts(request,engine,sig,conf,topic,piv.getFirst(),piv.getLast(), read_new,show_adv); content = tpos; page_title = topic.getName() + ": " + String.valueOf(topic.getTotalMessages()) + " Total; " diff --git a/src/com/silverwrist/venice/servlets/ConfOperations.java b/src/com/silverwrist/venice/servlets/ConfOperations.java index bbab418..999c32d 100644 --- a/src/com/silverwrist/venice/servlets/ConfOperations.java +++ b/src/com/silverwrist/venice/servlets/ConfOperations.java @@ -414,7 +414,7 @@ public class ConfOperations extends VeniceServlet try { // do a preview generation - ntf.generatePreview(getVeniceEngine(),request); + ntf.generatePreview(getVeniceEngine(),conf,request); if (ntf.isNullRequest()) { // no title or text specified - this is a "204 No Content" return diff --git a/src/com/silverwrist/venice/servlets/PostOperations.java b/src/com/silverwrist/venice/servlets/PostOperations.java new file mode 100644 index 0000000..204cc74 --- /dev/null +++ b/src/com/silverwrist/venice/servlets/PostOperations.java @@ -0,0 +1,393 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.servlets; + +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 PostOperations extends VeniceServlet +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final String NUKE_CONFIRM_ATTR = "servlets.PostOperations.nuke.confirm"; + private static final String NUKE_CONFIRM_PARAM = "confirm"; + + private static Category logger = Category.getInstance(TopicOperations.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 TopicMessageContext getMessageParameter(ServletRequest request, TopicContext topic) + throws ValidationException, DataException, AccessError + { + String str = request.getParameter("msg"); + if (StringUtil.isStringEmpty(str)) + { // no topic parameter - bail out now! + logger.error("Message parameter not specified!"); + throw new ValidationException("No message specified."); + + } // end if + + try + { // turn the string into a TopicID, and thence to a TopicContext + int message_num = Integer.parseInt(str); + return topic.getMessage(message_num); + + } // end try + catch (NumberFormatException nfe) + { // error in Integer.parseInt + logger.error("Cannot convert message parameter '" + str + "'!"); + throw new ValidationException("Invalid message parameter."); + + } // end catch + + } // end getMessageParameter + + /*-------------------------------------------------------------------------------- + * Overrides from class HttpServlet + *-------------------------------------------------------------------------------- + */ + + public String getServletInfo() + { + String rc = "PostOperations servlet - General post operations (hide, scribble, etc.)\n" + + "Part of the Venice Web Communities System\n"; + return rc; + + } // end getServletInfo + + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + UserContext user = getUserContext(request); + RenderData rdat = createRenderData(request,response); + String location = "top"; + String locator = null; + String page_title = null; + Object content = null; + SIGContext sig = null; // SIG context + ConferenceContext conf = null; // conference context + TopicContext topic = null; // topic context + TopicMessageContext msg = null; // message 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())); + locator = "sig=" + String.valueOf(sig.getSIGID()); + location = "sigprofile?" + locator; + + } // 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(),location); + + } // 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())); + locator += "&conf=" + String.valueOf(conf.getConfID()); + location = "confdisp?" + locator; + + } // 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(),location); + + } // 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())); + locator += "&top=" + String.valueOf(topic.getTopicID()); + location = "confdisp?" + locator; + + } // 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(),location); + + } // end catch + + } // end if + + if (content==null) + { // we got the topic parameter OK + try + { // now we need a message parameter + msg = getMessageParameter(request,topic); + if (logger.isDebugEnabled()) + logger.debug("found message #" + String.valueOf(msg.getPostID())); + location = "confdisp?" + locator + "&p1=" + msg.getPostNumber() + "&shac=1"; + + } // end try + catch (DataException de) + { // error looking up the conference + page_title = "Database Error"; + content = new ErrorBox(page_title,"Database error finding message: " + de.getMessage(),location); + + } // 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(),location); + + } // 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(),location); + + } // end catch + + if (content==null) + { // figure out what command we want to perform + String cmd = request.getParameter("cmd"); + if (cmd==null) + cmd = "???"; + + if (cmd.equals("HY") || cmd.equals("HN")) + { // we want to hide or show the message + try + { // attempt to hide or show the message + msg.setHidden(cmd.equals("HY")); + + // go back and display stuff + rdat.redirectTo(location); + return; + + } // end try + catch (DataException de) + { // there was a database error + page_title = "Database Error"; + content = new ErrorBox(page_title,"Database error setting hidden status: " + de.getMessage(), + location); + + } // end catch + catch (AccessError ae) + { // naughty naughty = you can't do this! + page_title = "Access Error"; + content = new ErrorBox(page_title,ae.getMessage(),location); + + } // end catch + + } // end if ("hide" or "show") + else if (cmd.equals("SCR")) + { // we want to scribble the message + try + { // attempt to scribble the message + msg.scribble(); + + // go back and display stuff + rdat.redirectTo(location); + return; + + } // end try + catch (DataException de) + { // there was a database error + page_title = "Database Error"; + content = new ErrorBox(page_title,"Database error scribbling message: " + de.getMessage(), + location); + + } // end catch + catch (AccessError ae) + { // naughty naughty = you can't do this! + page_title = "Access Error"; + content = new ErrorBox(page_title,ae.getMessage(),location); + + } // end catch + + } // end else if ("scribble") + else if (cmd.equals("NUKE")) + { // nuking requires confirmation + try + { // we need confirmation on this operation! + if (ConfirmBox.isConfirmed(request,NUKE_CONFIRM_ATTR,NUKE_CONFIRM_PARAM)) + { // OK, go ahead, nuke the message! + msg.nuke(); + + // after which, redirect to topic view + rdat.redirectTo("confdisp?" + locator); + return; + + } // end if + else + { // not a proper confirmation - better display one + List aliases = conf.getAliases(); + String message = "You are about to nuke message <" + (String)(aliases.get(0)) + "." + + String.valueOf(topic.getTopicNumber()) + "." + String.valueOf(msg.getPostNumber()) + + ">, originally composed by <" + msg.getCreatorName() + + ">! Are you sure you want to do this?"; + String confirm_url = "postops?" + locator + "&msg=" + msg.getPostNumber() + "&cmd=NUKE"; + + page_title = "Nuke Message"; + content = new ConfirmBox(request,NUKE_CONFIRM_ATTR,NUKE_CONFIRM_PARAM,page_title, + message,confirm_url,location); + + } // end else + + } // end try + catch (DataException de) + { // there was a database error + page_title = "Database Error"; + content = new ErrorBox(page_title,"Database error nuking message: " + de.getMessage(), + location); + + } // end catch + catch (AccessError ae) + { // naughty naughty = you can't do this! + page_title = "Access Error"; + content = new ErrorBox(page_title,ae.getMessage(),location); + + } // end catch + + } // end else if ("nuke") + else + { // unrecognized command! + page_title = "Internal Error"; + logger.error("invalid command to PostOperations.doGet: " + cmd); + content = new ErrorBox(page_title,"Invalid command to PostOperations.doGet",location); + + } // end else + + } // end if (got parameters OK) + + BaseJSPData basedat = new BaseJSPData(page_title,location,content); + basedat.transfer(getServletContext(),rdat); + + } // end doGet + +} // end class PostOperations + + + + + + diff --git a/src/com/silverwrist/venice/servlets/PostShortcut.java b/src/com/silverwrist/venice/servlets/PostShortcut.java new file mode 100644 index 0000000..69d6886 --- /dev/null +++ b/src/com/silverwrist/venice/servlets/PostShortcut.java @@ -0,0 +1,161 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.servlets; + +import java.io.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.silverwrist.venice.ValidationException; +import com.silverwrist.venice.core.*; +import com.silverwrist.venice.db.PostLinkDecoder; +import com.silverwrist.venice.servlets.format.*; + +public class PostShortcut extends VeniceServlet +{ + /*-------------------------------------------------------------------------------- + * Overrides from class HttpServlet + *-------------------------------------------------------------------------------- + */ + + public String getServletInfo() + { + String rc = "PostShortcut servlet - Decodes a post link and redirects to it\n" + + "Part of the Venice Web Communities System\n"; + return rc; + + } // end getServletInfo + + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + UserContext user = getUserContext(request); + RenderData rdat = createRenderData(request,response); + String raw_link = request.getPathInfo().substring(1); + PostLinkDecoder decoder; + + try + { // attempt to decode the path link information + decoder = new PostLinkDecoder(raw_link); + if (decoder.getSIG()==null) // it must include the SIG + throw new ValidationException("ambiguous post link (no SIG)"); + + } // end try + catch (ValidationException e) + { // display an error message for validation + String page_title = "Invalid Post Link"; + ContentRender content = new ErrorBox(page_title,"Invalid post link \"" + raw_link + "\": " + + e.getMessage(),null); + new BaseJSPData(page_title,"top",content).transfer(getServletContext(),rdat); + return; + + } // end catch + + SIGContext sig; + try + { // get the SIG represented by that alias + sig = user.getSIGContext(decoder.getSIG()); + + } // end try + catch (DataException e) + { // can't find the SIG - we're screwed + String page_title = "Invalid Post Link"; + ContentRender content = new ErrorBox(page_title,"Invalid post link \"" + raw_link + + "\": cannot find SIG: " + e.getMessage(),null); + new BaseJSPData(page_title,"top",content).transfer(getServletContext(),rdat); + return; + + } // end catch + + if (decoder.getConference()==null) + { // it's a SIG link only - redirect to the SIG's default page + rdat.redirectTo("sig/" + decoder.getSIG()); + return; + + } // end if + + ConferenceContext conf; + try + { // get the conference represented by that alias + conf = sig.getConferenceContext(decoder.getConference()); + + } // end try + catch (DataException e) + { // can't find the conference - we're screwed + String page_title = "Invalid Post Link"; + ContentRender content = new ErrorBox(page_title,"Invalid post link \"" + raw_link + + "\": cannot find conference: " + e.getMessage(),null); + new BaseJSPData(page_title,"top",content).transfer(getServletContext(),rdat); + return; + + } // end catch + catch (AccessError ae) + { // we can't get to the conference... + String page_title = "Access Error"; + ContentRender content = new ErrorBox(page_title,ae.getMessage(),null); + new BaseJSPData(page_title,"top",content).transfer(getServletContext(),rdat); + return; + + } // end catch + + // compute an elementary "locator" + String locator = "sig=" + String.valueOf(sig.getSIGID()) + "&conf=" + String.valueOf(conf.getConfID()); + + if (decoder.getTopic()==-1) + { // just a conference link - go to the top-level display + rdat.redirectTo("confdisp?" + locator); + return; + + } // end if + + TopicContext topic; + try + { // get the topic number specified within that topic + topic = conf.getTopic(decoder.getTopic()); + + } // end try + catch (DataException e) + { // we can't find the topic - we're screwed + String page_title = "Invalid Post Link"; + ContentRender content = new ErrorBox(page_title,"Invalid post link \"" + raw_link + + "\": cannot find topic: " + e.getMessage(),null); + new BaseJSPData(page_title,"top",content).transfer(getServletContext(),rdat); + return; + + } // end catch + catch (AccessError ae) + { // we can't get to the topic... + String page_title = "Access Error"; + ContentRender content = new ErrorBox(page_title,ae.getMessage(),null); + new BaseJSPData(page_title,"top",content).transfer(getServletContext(),rdat); + return; + + } // end catch + + // add the topic to our locator + locator += "&top=" + String.valueOf(decoder.getTopic()); + + if (decoder.getFirstPost()==-1) // we're just referencing the topic + rdat.redirectTo("confdisp?" + locator + "&rnm=1"); + else // we're referencing a post range within the topic + rdat.redirectTo("confdisp?" + locator + "&p1=" + String.valueOf(decoder.getFirstPost()) + "&p2=" + + String.valueOf(decoder.getLastPost())); + + } // end doGet + +} // end class PostShortcut + diff --git a/src/com/silverwrist/venice/servlets/SIGFrontEnd.java b/src/com/silverwrist/venice/servlets/SIGFrontEnd.java index 6117141..d729218 100644 --- a/src/com/silverwrist/venice/servlets/SIGFrontEnd.java +++ b/src/com/silverwrist/venice/servlets/SIGFrontEnd.java @@ -7,7 +7,7 @@ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * - * The Original Code is the Venice Web Community System. + * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are @@ -25,10 +25,15 @@ import com.silverwrist.venice.servlets.format.*; public class SIGFrontEnd extends VeniceServlet { + /*-------------------------------------------------------------------------------- + * Overrides from class HttpServlet + *-------------------------------------------------------------------------------- + */ + public String getServletInfo() { String rc = "SIGFrontEnd servlet - Redirects to the \"default feature\" of a SIG\n" - + "Part of the Venice Web conferencing system\n"; + + "Part of the Venice Web Communities System\n"; return rc; } // end getServletInfo diff --git a/src/com/silverwrist/venice/servlets/TopicOperations.java b/src/com/silverwrist/venice/servlets/TopicOperations.java new file mode 100644 index 0000000..ee1a5ac --- /dev/null +++ b/src/com/silverwrist/venice/servlets/TopicOperations.java @@ -0,0 +1,357 @@ +/* + * The contents of this file are subject to the Mozilla Public License Version 1.1 + * (the "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at . + * + * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT + * WARRANTY OF ANY KIND, either express or implied. See the License for the specific + * language governing rights and limitations under the License. + * + * The Original Code is the Venice Web Communities System. + * + * The Initial Developer of the Original Code is Eric J. Bowersox , + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.servlets; + +import java.io.*; +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 TopicOperations extends VeniceServlet +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static final String DELETE_CONFIRM_ATTR = "servlets.TopicOperations.delete.confirm"; + private static final String DELETE_CONFIRM_PARAM = "confirm"; + + private static Category logger = Category.getInstance(TopicOperations.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 + + /*-------------------------------------------------------------------------------- + * Overrides from class HttpServlet + *-------------------------------------------------------------------------------- + */ + + public String getServletInfo() + { + String rc = "TopicOperations servlet - General topic operations (freeze, archive, etc.)\n" + + "Part of the Venice Web Communities System\n"; + return rc; + + } // end getServletInfo + + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + UserContext user = getUserContext(request); + RenderData rdat = createRenderData(request,response); + String location = "top"; + String locator = null; + 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())); + locator = "sig=" + String.valueOf(sig.getSIGID()); + location = "sigprofile?" + locator; + + } // 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(),location); + + } // 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())); + locator += "&conf=" + String.valueOf(conf.getConfID()); + location = "confdisp?" + locator; + + } // 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(),location); + + } // 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())); + locator += "&top=" + String.valueOf(topic.getTopicNumber()); + location = "confdisp?" + locator; + + } // 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(),location); + + } // 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(),location); + + } // 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(),location); + + } // end catch + + if (content==null) + { // figure out what command we want to perform... + String cmd = request.getParameter("cmd"); + if (cmd==null) + cmd = "???"; + + if (cmd.equals("HY") || cmd.equals("HN")) + { // we want to set the hide status of the topic + try + { // call down to set the topic! + topic.setHidden(cmd.equals("HY")); + + // go back to the topic view + rdat.redirectTo(location); + return; + + } // end try + catch (DataException de) + { // there was a database error + page_title = "Database Error"; + content = new ErrorBox(page_title,"Database error setting hide status: " + de.getMessage(),location); + + } // end catch + + } // end if ("hide" or "show") + else if (cmd.equals("FY") || cmd.equals("FN")) + { // we want to set the frozen status of the topic + try + { // call down to set the topic! + topic.setFrozen(cmd.equals("FY")); + + // go back to the topic view + rdat.redirectTo(location); + return; + + } // end try + catch (DataException de) + { // there was a database error + page_title = "Database Error"; + content = new ErrorBox(page_title,"Database error setting freeze status: " + de.getMessage(), + location); + + } // end catch + catch (AccessError ae) + { // naughty naughty = you can't do this! + page_title = "Access Error"; + content = new ErrorBox(page_title,ae.getMessage(),location); + + } // end catch + + } // end else if ("freeze" or "unfreeze") + else if (cmd.equals("AY") || cmd.equals("AN")) + { // we want to change the archived status of the topic + try + { // call down to set the topic! + topic.setArchived(cmd.equals("AY")); + + // go back to the topic view + rdat.redirectTo(location); + return; + + } // end try + catch (DataException de) + { // there was a database error + page_title = "Database Error"; + content = new ErrorBox(page_title,"Database error setting archive status: " + de.getMessage(), + location); + + } // end catch + catch (AccessError ae) + { // naughty naughty = you can't do this! + page_title = "Access Error"; + content = new ErrorBox(page_title,ae.getMessage(),location); + + } // end catch + + } // end else if ("archive" or "unarchive") + else if (cmd.equals("DEL")) + { // we need confirmation on this operation! + if (ConfirmBox.isConfirmed(request,DELETE_CONFIRM_ATTR,DELETE_CONFIRM_PARAM)) + { // OK, go ahead, delete the topic! + location = "confdisp?sig=" + String.valueOf(sig.getSIGID()) + "&conf=" + + String.valueOf(conf.getConfID()); + + try + { // delete the bloody topic! + topic.delete(); + + // after which, redirect to conference view + rdat.redirectTo(location); + return; + + } // end try + catch (DataException de) + { // there was a database error + page_title = "Database Error"; + content = new ErrorBox(page_title,"Database error deleting topic: " + de.getMessage(),location); + + } // end catch + catch (AccessError ae) + { // naughty naughty = you can't do this! + page_title = "Access Error"; + content = new ErrorBox(page_title,ae.getMessage(),location); + + } // end catch + + } // end if + else + { // not a proper confirmation - better display one + String message = "You are about to delete topic " + String.valueOf(topic.getTopicNumber()) + + " from the \"" + conf.getName() + "\" conference! Are you sure you want to do this?"; + String confirm_url = "topicops?" + locator + "&cmd=DEL"; + page_title = "Delete Topic"; + content = new ConfirmBox(request,DELETE_CONFIRM_ATTR,DELETE_CONFIRM_PARAM,page_title, + message,confirm_url,location); + + } // end else + + } // end else if ("delete") + else + { // unrecognized command + page_title = "Internal Error"; + logger.error("invalid command to TopicOperations.doGet: " + cmd); + content = new ErrorBox(page_title,"Invalid command to TopicOperations.doGet",location); + + } // end else + + } // end if + + BaseJSPData basedat = new BaseJSPData(page_title,location,content); + basedat.transfer(getServletContext(),rdat); + + } // end doGet + +} // end class TopicOperations diff --git a/src/com/silverwrist/venice/servlets/format/NewTopicForm.java b/src/com/silverwrist/venice/servlets/format/NewTopicForm.java index 218c88f..f1dba8f 100644 --- a/src/com/silverwrist/venice/servlets/format/NewTopicForm.java +++ b/src/com/silverwrist/venice/servlets/format/NewTopicForm.java @@ -101,7 +101,8 @@ public class NewTopicForm implements JSPRender } // end setupNewRequest - public void generatePreview(VeniceEngine engine, ServletRequest request) throws ValidationException + public void generatePreview(VeniceEngine engine, ConferenceContext conf, ServletRequest request) + throws ValidationException { HTMLChecker check; @@ -136,7 +137,7 @@ public class NewTopicForm implements JSPRender post_box = check.getValue(); // generate the body text preview - check = engine.getPreviewChecker(); + check = conf.getNewTopicPreviewChecker(); check.append(foo); check.finish(); preview = check.getValue(); diff --git a/src/com/silverwrist/venice/servlets/format/PostPreview.java b/src/com/silverwrist/venice/servlets/format/PostPreview.java index 92e1984..f41eda8 100644 --- a/src/com/silverwrist/venice/servlets/format/PostPreview.java +++ b/src/com/silverwrist/venice/servlets/format/PostPreview.java @@ -79,7 +79,7 @@ public class PostPreview implements JSPRender this.data = check.getValue(); // now generate the preview - check = engine.getPreviewChecker(); + check = topic.getPreviewChecker(); check.append(data); check.finish(); this.preview = check.getValue(); diff --git a/src/com/silverwrist/venice/servlets/format/PostSlippage.java b/src/com/silverwrist/venice/servlets/format/PostSlippage.java index 3b6fa18..67ba6a4 100644 --- a/src/com/silverwrist/venice/servlets/format/PostSlippage.java +++ b/src/com/silverwrist/venice/servlets/format/PostSlippage.java @@ -47,6 +47,7 @@ public class PostSlippage implements JSPRender private String pseud; private String text; private boolean attach; + private String topic_stem; /*-------------------------------------------------------------------------------- * Constructor @@ -63,6 +64,8 @@ public class PostSlippage implements JSPRender this.messages = topic.getMessages(lastval,topic.getTotalMessages()-1); this.next = next; this.attach = attach; + List aliases = conf.getAliases(); + topic_stem = (String)(aliases.get(0)) + "." + String.valueOf(topic.getTopicNumber()) + "."; try { // run the text and pseud through an HTML checker to escape them @@ -213,4 +216,10 @@ public class PostSlippage implements JSPRender } // end getBodyText + public String getMessageReference(TopicMessageContext msg) + { + return topic_stem + String.valueOf(msg.getPostNumber()); + + } // end getMessageReference + } // end class PostSlippage diff --git a/src/com/silverwrist/venice/servlets/format/RenderConfig.java b/src/com/silverwrist/venice/servlets/format/RenderConfig.java index ad5e587..ec285cc 100644 --- a/src/com/silverwrist/venice/servlets/format/RenderConfig.java +++ b/src/com/silverwrist/venice/servlets/format/RenderConfig.java @@ -54,6 +54,7 @@ public class RenderConfig private String font_face; private String base_url; private String image_url; + private String static_url; private String site_logo; /*-------------------------------------------------------------------------------- @@ -148,6 +149,17 @@ public class RenderConfig if (logger.isDebugEnabled()) logger.debug("Image path: " + image_url); + static_url = paths_sect_h.getSubElementText("static"); + if (static_url==null) + { // no tag - bail out now! + logger.fatal(" section has no element"); + throw new ConfigException("no found in section",paths_sect); + + } // end if + + if (logger.isDebugEnabled()) + logger.debug("Static files path: " + static_url); + site_logo = paths_sect_h.getSubElementText("site-logo"); if (site_logo==null) { // no tag - bail out now! @@ -256,6 +268,14 @@ public class RenderConfig } // end getFullImagePath + String getStaticFilePath(String name) + { + StringBuffer buf = new StringBuffer(); + buf.append(static_url).append(name); + return buf.toString(); + + } // end getStaticFilePath + String getTitleTag(String specific) { StringBuffer buf = new StringBuffer(); diff --git a/src/com/silverwrist/venice/servlets/format/RenderData.java b/src/com/silverwrist/venice/servlets/format/RenderData.java index 360c01f..3231096 100644 --- a/src/com/silverwrist/venice/servlets/format/RenderData.java +++ b/src/com/silverwrist/venice/servlets/format/RenderData.java @@ -7,7 +7,7 @@ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * - * The Original Code is the Venice Web Community System. + * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are @@ -24,6 +24,9 @@ import javax.servlet.*; import javax.servlet.http.*; import org.apache.log4j.*; import com.silverwrist.util.StringUtil; +import com.silverwrist.venice.core.IDUtils; +import com.silverwrist.venice.db.PostLinkRewriter; +import com.silverwrist.venice.db.UserNameRewriter; public class RenderData { @@ -128,6 +131,12 @@ public class RenderData } // end getFullImagePath + public String getStaticFilePath(String name) + { + return rconf.getStaticFilePath(name); + + } // end getStaticFilePath + public String getFormatJSPPath(String name) { return "/format/" + name; @@ -320,4 +329,87 @@ public class RenderData } // end sendBinaryData + public String rewritePostData(String data) + { + if ((data.indexOf(PostLinkRewriter.URI_PREFIX)<0) && (data.indexOf(UserNameRewriter.URI_PREFIX)<0)) + return data; + + StringBuffer buf = new StringBuffer(); + String interm; + + if (data.indexOf(PostLinkRewriter.URI_PREFIX)>=0) + { // begin replacing everything with post links + String t = data; + int p = t.indexOf(PostLinkRewriter.URI_PREFIX); + while (p>=0) + { // break off the start of the string + if (p>0) + buf.append(t.substring(0,p)); + t = t.substring(p + PostLinkRewriter.URI_PREFIX.length()); + + // find the end of the post link... + p = 0; + while (IDUtils.isValidPostLinkChar(t.charAt(p))) + p++; + + if (p>0) + { // append the post link to the "go" servlet path, and encode the lot + buf.append(getEncodedServletPath("go/" + t.substring(0,p))); + t = t.substring(p); + + } // end if + else // false alarm + buf.append(PostLinkRewriter.URI_PREFIX); + + // and now look again... + p = t.indexOf(PostLinkRewriter.URI_PREFIX); + + } // end while + + buf.append(t); + interm = buf.toString(); + buf.setLength(0); + + } // end if + else // no post link strings, this is the intermediate form + interm = data; + + if (interm.indexOf(UserNameRewriter.URI_PREFIX)>=0) + { // begin replacing everything with user links + String t = interm; + int p = t.indexOf(UserNameRewriter.URI_PREFIX); + while (p>=0) + { // break off the start of the string + if (p>0) + buf.append(t.substring(0,p)); + t = t.substring(p + UserNameRewriter.URI_PREFIX.length()); + + // find the end of the user link... + p = 0; + while (IDUtils.isValidVeniceIDChar(t.charAt(p))) + p++; + + if (p>0) + { // append the post link to the "user" servlet path, and encode the lot + buf.append(getEncodedServletPath("user/" + t.substring(0,p))); + t = t.substring(p); + + } // end if + else // false alarm + buf.append(UserNameRewriter.URI_PREFIX); + + // and now look again... + p = t.indexOf(UserNameRewriter.URI_PREFIX); + + } // end while + + buf.append(t); + return buf.toString(); + + } // end if + else // no more to find - just return this + return interm; + + } // end rewritePostData + } // end class RenderData diff --git a/src/com/silverwrist/venice/servlets/format/TopicPosts.java b/src/com/silverwrist/venice/servlets/format/TopicPosts.java index 6859e13..9493ba5 100644 --- a/src/com/silverwrist/venice/servlets/format/TopicPosts.java +++ b/src/com/silverwrist/venice/servlets/format/TopicPosts.java @@ -38,6 +38,7 @@ public class TopicPosts implements JSPRender *-------------------------------------------------------------------------------- */ + private VeniceEngine engine; private SIGContext sig; private ConferenceContext conf; private TopicContext topic; @@ -47,6 +48,7 @@ public class TopicPosts implements JSPRender private int unread; private List messages; private TopicVisitOrder visit_order; + private String topic_stem; private String cache_locator = null; /*-------------------------------------------------------------------------------- @@ -54,10 +56,11 @@ public class TopicPosts implements JSPRender *-------------------------------------------------------------------------------- */ - public TopicPosts(HttpServletRequest request, SIGContext sig, ConferenceContext conf, TopicContext topic, - int first, int last, boolean read_new, boolean show_advanced) + public TopicPosts(HttpServletRequest request, VeniceEngine engine, SIGContext sig, ConferenceContext conf, + TopicContext topic, int first, int last, boolean read_new, boolean show_advanced) throws DataException, AccessError { + this.engine = engine; this.sig = sig; this.conf = conf; this.topic = topic; @@ -70,6 +73,8 @@ public class TopicPosts implements JSPRender this.messages = topic.getMessages(first,last); this.visit_order = TopicVisitOrder.retrieve(request.getSession(true),conf.getConfID()); visit_order.visit(topic.getTopicNumber()); + List aliases = conf.getAliases(); + topic_stem = (String)(aliases.get(0)) + "." + String.valueOf(topic.getTopicNumber()) + "."; } // end constructor @@ -192,6 +197,14 @@ public class TopicPosts implements JSPRender } // end getNextLocator + public String getRestoreLocator() + { + StringBuffer buf = new StringBuffer("rtop="); + buf.append(topic.getTopicNumber()).append("&rct=").append(unread); + return buf.toString(); + + } // end getRestoreLocator + public String getIdentifyingData() { StringBuffer buf = new StringBuffer("Posts "); @@ -262,7 +275,7 @@ public class TopicPosts implements JSPRender public boolean canDeleteTopic() { - return false; // TODO: fix me + return topic.canDelete(); } // end canDeleteTopic @@ -274,7 +287,7 @@ public class TopicPosts implements JSPRender public String getScrollUpLocator() { - int new_first = first - 20; // TODO: configurable + int new_first = first - engine.getNumPostsPerPage(); int new_last = last - 1; if (new_first<0) { // normalize so we start at 0 @@ -291,14 +304,14 @@ public class TopicPosts implements JSPRender public boolean canScrollDown() { - return ((topic.getTotalMessages() - (1 + last))>=20); // TODO: configurable + return ((topic.getTotalMessages() - (1 + last))>=engine.getNumPostsPerPage()); } // end canScrollDown public String getScrollDownLocator() { StringBuffer buf = new StringBuffer("p1="); - buf.append(last+1).append("&p2=").append(last+20); // TODO: configurable + buf.append(last+1).append("&p2=").append(last+engine.getNumPostsPerPage()); return buf.toString(); } // end getScrollDownLocator @@ -313,7 +326,7 @@ public class TopicPosts implements JSPRender { int my_last = topic.getTotalMessages(); StringBuffer buf = new StringBuffer("p1="); - buf.append(my_last-20).append("&p2=").append(my_last-1); // TODO: configurable + buf.append(my_last-engine.getNumPostsPerPage()).append("&p2=").append(my_last-1); return buf.toString(); } // end getScrollToEndLocator @@ -351,4 +364,16 @@ public class TopicPosts implements JSPRender } // end getDefaultPseud + public String getMessageReference(TopicMessageContext msg) + { + return topic_stem + String.valueOf(msg.getPostNumber()); + + } // end getMessageReference + + public int getNumPostsPerPage() + { + return engine.getNumPostsPerPage(); + + } // end getNumPostsPerPage + } // end class TopicPosts diff --git a/web/format/newtopic.jsp b/web/format/newtopic.jsp index ca77b66..e726762 100644 --- a/web/format/newtopic.jsp +++ b/web/format/newtopic.jsp @@ -38,7 +38,7 @@ There were <%= data.getNumSpellingErrors() %> spelling errors in your post. <% } // end if %> -

<%= data.getPreviewData() %>

+

<%= rdat.rewritePostData(data.getPreviewData()) %>

<% } // end if %>
"> @@ -59,7 +59,7 @@ <%= rdat.getStdFontTag(null,2) %>Message: <%= rdat.getStdFontTag(null,2) %> - HTML Guide + " TARGET="_blank">HTML Guide diff --git a/web/format/posts.jsp b/web/format/posts.jsp index 3842571..d51b4c3 100644 --- a/web/format/posts.jsp +++ b/web/format/posts.jsp @@ -47,11 +47,11 @@ BORDER=0>    <% if (data.isTopicHidden()) { %> - ">">" ALT="Show Topic" WIDTH=80 HEIGHT=24 BORDER=0> <% } else { %> - ">">" ALT="Hide Topic" WIDTH=80 HEIGHT=24 BORDER=0> <% } // end if %> @@ -62,8 +62,8 @@ BORDER=0>    <% if (data.getNewMessages()>0) { %> - <%-- TODO: this doesn't do Keep New yet --%> - ">">" ALT="Next & Keep New" WIDTH=80 HEIGHT=24 BORDER=0>    @@ -75,11 +75,11 @@ <% if (data.canFreezeTopic()) { %>    <% if (data.isTopicFrozen()) { %> - ">">" ALT="Unfreeze Topic" WIDTH=80 HEIGHT=24 BORDER=0> <% } else { %> - ">">" ALT="Freeze Topic" WIDTH=80 HEIGHT=24 BORDER=0> <% } // end if %> @@ -87,18 +87,18 @@ <% if (data.canArchiveTopic()) { %>    <% if (data.isTopicArchived()) { %> - ">">" ALT="Unarchive Topic" WIDTH=80 HEIGHT=24 BORDER=0> <% } else { %> - ">">" ALT="Archive Topic" WIDTH=80 HEIGHT=24 BORDER=0> <% } // end if %> <% } // end if %> <% if (data.canDeleteTopic()) { %>    - ">">" ALT="Delete Topic" WIDTH=80 HEIGHT=24 BORDER=0> <% } // end if %> @@ -119,18 +119,17 @@ <%= rdat.getStdFontTag(null,2) %> <% if (rdat.useHTMLComments()) { %><% } %> - <%-- TODO: the number "20" should be configurable --%> [  ">View All <% if (data.canScrollUp()) { %>  |  ">Scroll Up 20 + + data.getScrollUpLocator()) %>">Scroll Up <%= data.getNumPostsPerPage() %> <% } // end if %> <% if (data.canScrollDown()) { %>  |  ">Scroll Down 20 + + data.getScrollDownLocator()) %>">Scroll Down <%= data.getNumPostsPerPage() %> <% } // end if %> <% if (data.canScrollDown()) { %>  |  @@ -165,7 +164,11 @@ "><%= msg.getPostNumber() %> of <%= data.getTotalMessages() - 1 %> - <%= rdat.getStdFontTag(null,1) %><<%= "TODO" %>>
+ <%= rdat.getStdFontTag(null,1) %><<%= data.getMessageReference(msg) %>> + <% if (data.showAdvanced() && msg.isHidden()) { %> + (Hidden) + <% } // end if %> +
<%= msg.getPseud() %> ( " TARGET="_blank"><%= poster %>, @@ -183,36 +186,37 @@ (Scribbled by <%= data.getMessageBodyText(msg) %> on <%= rdat.formatDateForDisplay(msg.getScribbleDate()) %>) - +

<% } else if (msg.isHidden() && !(data.showAdvanced())) { %> ">(Hidden - Message: <%= msg.getNumLines() %> <% if (msg.getNumLines()==1) { %>Line<% } else { %>Lines<% } %> - + Message: <%= msg.getNumLines() %> <% if (msg.getNumLines()==1) { %>Line<% } else { %>Lines<% } %>) +

<% } else { %> -

<%= data.getMessageBodyText(msg) %>
+
<%= rdat.rewritePostData(data.getMessageBodyText(msg)) %>
<% } // end if %> <% if (data.showAdvanced()) { %> + <% String po_loc = data.getLocator() + "&msg=" + String.valueOf(msg.getPostNumber()); %> <% if (!(msg.isScribbled())) { %> <% if (msg.canHide()) { %> <% if (msg.isHidden()) { %> - ">">" ALT="Show" WIDTH=80 HEIGHT=24 BORDER=0>

<% } else { %> - ">">" ALT="Hide" WIDTH=80 HEIGHT=24 BORDER=0>

<% } // end if %> <% } // end if (can hide) %> <% if (msg.canScribble()) { %> - ">">" ALT="Scribble" WIDTH=80 HEIGHT=24 BORDER=0>

<% } // end if (can scribble) %> <% } // end if (not already scribbled) %> <% if (msg.canNuke()) { %> - ">">" ALT="Nuke" WIDTH=80 HEIGHT=24 BORDER=0>

<% } // end if (can nuke) %> @@ -227,18 +231,17 @@   <%= rdat.getStdFontTag(null,2) %> <% if (rdat.useHTMLComments()) { %><% } %> - <%-- TODO: the number "20" should be configurable --%> [  ">View All <% if (data.canScrollUp()) { %>  |  ">Scroll Up 20 + + data.getScrollUpLocator()) %>">Scroll Up <%= data.getNumPostsPerPage() %> <% } // end if %> <% if (data.canScrollDown()) { %>  |  ">Scroll Down 20 + + data.getScrollDownLocator()) %>">Scroll Down <%= data.getNumPostsPerPage() %> <% } // end if %> <% if (data.canScrollDown()) { %>  |  @@ -258,11 +261,11 @@ BORDER=0>    <% if (data.isTopicHidden()) { %> - ">">" ALT="Show Topic" WIDTH=80 HEIGHT=24 BORDER=0> <% } else { %> - ">">" ALT="Hide Topic" WIDTH=80 HEIGHT=24 BORDER=0> <% } // end if %> @@ -273,8 +276,8 @@ BORDER=0>    <% if (data.getNewMessages()>0) { %> - <%-- TODO: this doesn't do Keep New yet --%> - ">">" ALT="Next & Keep New" WIDTH=80 HEIGHT=24 BORDER=0>    @@ -305,7 +308,7 @@ <%= rdat.getStdFontTag(null,2) %>Message: <%= rdat.getStdFontTag(null,2) %> - HTML Guide + " TARGET="_blank">HTML Guide diff --git a/web/format/preview.jsp b/web/format/preview.jsp index c8c52e5..5355a62 100644 --- a/web/format/preview.jsp +++ b/web/format/preview.jsp @@ -35,7 +35,7 @@ There were <%= data.getNumSpellingErrors() %> spelling errors in your post. <% } // end if %> -

<%= data.getPreviewData() %>

+

<%= rdat.rewritePostData(data.getPreviewData()) %>

"> @@ -55,7 +55,7 @@ <%= rdat.getStdFontTag(null,2) %>Message: <%= rdat.getStdFontTag(null,2) %> - HTML Guide + " TARGET="_blank">HTML Guide diff --git a/web/format/slippage.jsp b/web/format/slippage.jsp index 8313042..c457486 100644 --- a/web/format/slippage.jsp +++ b/web/format/slippage.jsp @@ -41,7 +41,7 @@ %> <%= rdat.getStdFontTag(null,2) %> <%= msg.getPostNumber() %> of <%= data.getTotalMessages() - 1 %> - <%= rdat.getStdFontTag(null,1) %><<%= "TODO" %>>
+ <%= rdat.getStdFontTag(null,1) %><<%= data.getMessageReference(msg) %>>
<%= msg.getPseud() %> ( " TARGET="_blank"><%= poster %>, @@ -54,7 +54,7 @@ <%= rdat.formatDateForDisplay(msg.getScribbleDate()) %>) <% } else { %> -
<%= data.getMessageBodyText(msg) %>
+
<%= rdat.rewritePostData(data.getMessageBodyText(msg)) %>
<% } // end if %> <% } // end while %> <% if (rdat.useHTMLComments()) { %><% } %> @@ -79,7 +79,7 @@ <%= rdat.getStdFontTag(null,2) %>Message: <%= rdat.getStdFontTag(null,2) %> - HTML Guide + " TARGET="_blank">HTML Guide diff --git a/web/format/topics.jsp b/web/format/topics.jsp index bdc7ce4..16eb1b6 100644 --- a/web/format/topics.jsp +++ b/web/format/topics.jsp @@ -28,7 +28,7 @@ String tmp; %> <% if (rdat.useHTMLComments()) { %><% } %> -<% rdat.writeContentHeader(out,data.getConfName() + " Topics",null); %> +<% rdat.writeContentHeader(out,"Topics in " + data.getConfName(),null); %> <%= rdat.getStdFontTag(null,2) %>
   <% } // end if %> <% if (data.canDoReadNew()) { %> - ">">" ALT="Read New" WIDTH=80 HEIGHT=24 BORDER=0>   <% } // end if %> diff --git a/web/static/html-reference.html b/web/static/html-reference.html new file mode 100644 index 0000000..15c0123 --- /dev/null +++ b/web/static/html-reference.html @@ -0,0 +1,1570 @@ + + + + Venice HTML Tags Reference + + + +

Venice HTML Tags Reference

+ + Colors in HTML

+ Special Characters +


+ +

A

+ The anchor tag, which encloses either text or graphics and either creates a hyperlink + to another page or a named reference which can be hyperlinked to. +
+
Syntax +
<A [HREF="reference"] [NAME="name"] + [TARGET="target-spec"] [TITLE="title"] > +
Allowed in Topic Names +
No +
Closing Tag +
Required +
Parameters +
+ HREF="reference"

+ Optional: Specifies a destination address for a hyperlink, which must be in URL format.

+ NAME="name"

+ Optional: Specifies a named reference within a document. Other pages can then link + to this reference within the document by appending a pound sign (#) and the name to + the URL for the document.

+ TARGET="target-spec"

+ Optional: Specifies a target frame name for the link to be loaded into.

+ TITLE="title"

+ Optional: Specifies the title that appears when the hyperlink is selected. +

Notes +
Either HREF or NAME, but not both, should be used with this tag. +
Example +
+ + <A HREF="http://www.megatokyo.com">This is a link to the MegaTokyo online + comic/manga.</A><P>
+ <A HREF="http://slashdot.org" TARGET="_blank">This link loads + Slashdot into a new window.</A> +
+
Example Output +
+ This is a link to the MegaTokyo online comic/manga.

+ This link loads Slashdot into a new window. +


+ +

ACRONYM

+ Formats text as an acronym abbreviation. +
+
Syntax +
<ACRONYM [TITLE="title"] > +
Allowed in Topic Names +
Yes +
Closing Tag +
Required +
Parameters +
+ TITLE="title"

+ Optional: Specifies an advisory title for the acronym, which may be displayed by the + browser via a tip window or other such mechanism. +

Notes +
The formatted text may be displayed differently in different browsers. Usually, it is + formatted as Roman type. +
Example +
+ Sun uses the <ACRONYM TITLE="Java Community Process">JCP</ACRONYM>
+ (Java Community Process) to determine which enhancements will go into the Java language. +
+
Example Output +
+ Sun uses the JCP + (Java Community Process) to determine which enhancements will go into the Java language. +

+ +

ADDRESS

+ Specifies information such as address, signature, and ownership. +
+
Syntax +
<ADDRESS> +
Allowed in Topic Names +
No +
Closing Tag +
Required +
Notes +
+ The formatted text may be displayed differently in different browsers. Usually, it is formatted + as italic type. +
Example +
+ Here's some text.
+ <ADDRESS>Jabber.com Inc. - support@jabber.com</ADDRESS> +
+
Example Output +
+ Here's some text. +
Jabber.com Inc. - support@jabber.com
+

+ +

B

+ Renders enclosed text in bold. +
+
Syntax +
<B> +
Allowed in Topic Names +
Yes +
Closing Tag +
Required +
Example +
+ Some of the text on this line will be <B>rendered in bold face</B> type. + +
Example Output +
+ Some of the text on this line will be rendered in bold face type. +

+ +

BIG

+ Renders enclosed text in larger type. +
+
Syntax +
<BIG> +
Allowed in Topic Names +
No +
Closing Tag +
Required +
Example +
+ Some of the text on this line will be <BIG>rendered in large</BIG> type. + +
Example Output +
+ Some of the text on this line will be rendered in large type. +

+ +

BLOCKQUOTE

+ Sets apart a long quotation in text. Usually displayed as indented by a small amount. +
+
Syntax +
<BLOCKQUOTE> +
Allowed in Topic Names +
No +
Closing Tag +
Required +
Example +
+ Season 2 opening monologue:
+ <BLOCKQUOTE>The Babylon Project was our last, best hope for peace. A self-contained
+ world five miles long, located in neutral territory. A place of commerce and diplomacy for
+ a quarter of a million humans and aliens. A shining beacon in space, all alone in the night.
+ It was the dawn of the Third Age of Mankind, the year the Great War came upon us all. This is
+ the story of the last of the Babylon stations. The year is 2259. The name of the place is
+ Babylon 5.</BLOCKQUOTE> +
+
Example Output +
+ Season 2 opening monologue: +
The Babylon Project was our last, best hope for peace. A self-contained + world five miles long, located in neutral territory. A place of commerce and diplomacy for + a quarter of a million humans and aliens. A shining beacon in space, all alone in the night. + It was the dawn of the Third Age of Mankind, the year the Great War came upon us all. This is + the story of the last of the Babylon stations. The year is 2259. The name of the place is + Babylon 5.
+

+ +

BR

+ Inserts a line break. +
+
Syntax +
<BR [CLEAR=LEFT|RIGHT|ALL]> +
Allowed in Topic Names +
No +
Closing Tag +
Forbidden +
Parameters +
+ CLEAR=LEFT|RIGHT|ALL

+ Inserts vertical space so that the next text displayed will be past left- or right-aligned + "floating" images. The align-type can be LEFT, + RIGHT, or ALL. +

    +
  • LEFT inserts space so that the next text appears aligned with the + left margin directly below a left-aligned floating image. +
  • RIGHT inserts space so that the next text appears aligned with the + right margin directly below a right-aligned floating image. +
  • ALLplaces the next text past all floating images. +
+
Example +
+ This line illustrates<BR>a simple line break.<P>
+ <IMG SRC="images/ref64yr.gif" WIDTH=64 HEIGHT=64 HSPACE=5 ALIGN=LEFT>
+ A left aligned image.<BR CLEAR=LEFT>
+ This shows the effect of the CLEAR=LEFT parameter. +
+
Example Output +
+ This line illustrates
a simple line break.

+ + A left aligned image.
+ This shows the effect of the CLEAR=LEFT parameter. +


+ +

CENTER

+ Centers text and images in the browser window. +
+
Syntax +
<CENTER> +
Allowed in Topic Names +
No +
Closing Tag +
Required +
Example +
+ <CENTER>These lines will be centered<P>
+ until the CENTER tag is closed.</CENTER> +
+
Example Output +
+
These lines will be centered

+ until the CENTER tag is closed.

+

+ +

CITE

+ Indicates a citation. Refers to a book, paper, or other published source material. +
+
Syntax +
<CITE> +
Allowed in Topic Names +
Yes +
Closing Tag +
Required +
Notes +
This may be rendered differently in different browsers. Usually, though, it renders text as italic. +
Example +
+ You can find a reference to that in <CITE>The Cathedral and The Bazaar</CITE>,
+ by Eric Raymond. +
+
Example Output +
+ You can find a reference to that in The Cathedral and The Bazaar, + by Eric Raymond. +

+ +

CODE

+ Indicates a code sample. +
+
Syntax +
<CODE> +
Allowed in Topic Names +
Yes +
Closing Tag +
Required +
Notes +
This may be rendered differently in different browsers. Usually, though, it renders text + in a small fixed-width font. +
Example +
+ Here's a recursive factorial function in Java:<P>
+ <CODE>public static long factorial(long n)<BR>
+ {<BR>
+ &nbsp;&nbsp;if (n==0)<BR>
+ &nbsp;&nbsp;&nbsp;&nbsp;return 1;<BR>
+ &nbsp;&nbsp;else<BR>
+ &nbsp;&nbsp;&nbsp;&nbsp;return n * factorial(n - 1);<BR>
+ }<BR></CODE> +
+
Example Output +
+ Here's a recursive factorial function in Java:

+ public static long factorial(long n)
+ {
+   if (n==0)
+     return 1;
+   else
+     return n * factorial(n - 1);
+ }
+


+ +

DD

+ Specifies a definition in a definition list. Indicates that the text is a definition + of a term, and should therefore be displayed in the right-hand column of a definition list. +
+
Syntax +
<DD> +
Allowed in Topic Names +
No +
Closing Tag +
Forbidden +
Example +
+ <DL>
+ <DT><EM>Anla'shok</EM>
+ <DD>The secret Minbari fighting force established by Valen after the last war with
+ the Shadows. The name translates roughly as "Rangers." Valen was the first
+ leader of this force, or "Ranger One" (<EM>Anla'shok Na</EM>);
+ this post was filled a thousand years later by Jeffrey Sinclair, and later by Delenn.
+ <DT><EM>Denn'bok</EM>
+ <DD>The Minbari fighting pike, nominally a compact cylinder approximately 1 foot
+ in length, but telescoping out to approximately 5 feet upon command. A standard weapon
+ of the Rangers.
+ <DT><EM>Entil'zha</EM>
+ <DD>One of Valen's titles as leader of the Rangers. The title's meaning is unknown;
+ it is thought to be of Vorlon origin.
+ </DL> +
+
Example Output +
+
+
Anla'shok +
The secret Minbari fighting force established by Valen after the last war with + the Shadows. The name translates roughly as "Rangers." Valen was the first + leader of this force, or "Ranger One" (Anla'shok Na); + this post was filled a thousand years later by Jeffrey Sinclair, and later by Delenn. +
Denn'bok +
The Minbari fighting pike, nominally a compact cylinder approximately 1 foot + in length, but telescoping out to approximately 5 feet upon command. A standard weapon + of the Rangers. +
Entil'zha +
One of Valen's titles as leader of the Rangers. The title's meaning is unknown; + it is thought to be of Vorlon origin. +
+

+ +

DFN

+ Specifies a definition. Formats a term for its first appearance in a document. +
+
Syntax +
<DFN> +
Allowed in Topic Names +
Yes +
Closing Tag +
Required +
Notes +
This may be rendered differently in different browsers. +
Example +
+ Jabber transmits all its messages in <DFN>XML (Extensible
+ Markup Language),</DFN> which contains plain text with some delimiting codes. +
+
Example Output +
+ Jabber transmits all its messages in XML (Extensible + Markup Language), which contains plain text with some delimiting codes. +

+ +

DIR

+ Denotes a directory list. Specifies that the following block consists of individual items, + each beginning with an LI element and none containing more than 20 characters, that should + be displayed in columns. +
+
Syntax +
<DFN> +
Allowed in Topic Names +
No +
Closing Tag +
Required +
Notes +
This may be rendered differently in different browsers, but will usually be rendered + similarly to the UL tag. +
Example +
+ Listing for the directory:<P>
+ <DIR>
+ <LI>bin
+ <LI>etc
+ <LI>lib
+ <LI>opt
+ <LI>usr
+ <LI>var
+ </DIR> +
+
Example Output +
+ Listing for the directory:

+

+
  • bin +
  • etc +
  • lib +
  • opt +
  • usr +
  • var +
  • +

    + +

    DIV

    + Denotes a division of text. Frequently used to align a block of text. +
    +
    Syntax +
    <DIV [ALIGN=CENTER|LEFT|RIGHT] > +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Required +
    Parameters +
    + ALIGN=CENTER|LEFT|RIGHT

    + Specifies the alignment of the lines within this particular division. The align-type can be + CENTER, LEFT, or RIGHT. +

      +
    • CENTER centers the lines of text within the division. +
    • LEFT aligns the left edges of all the lines of text within the division + with the left margin. This is the default. +
    • RIGHT aligns the right edges of all the lines of text within the division + with the right margin. +
    +
    Example +
    + <DIV ALIGN=CENTER>These lines of text<BR>will be centered.</DIV>
    + <DIV ALIGN=RIGHT>These lines of text<BR>will be flush right.</DIV> +
    +
    Example Output +
    +
    These lines of text
    will be centered.
    +
    These lines of text
    will be flush right.
    +

    + +

    DL

    + Specifies that the following block is a definition list, that is, an automatically + formatted two-column list with terms on the left and their definitions on the right. +
    +
    Syntax +
    <DL> +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Required +
    Example +
    + <DL>
    + <DT><EM>Anla'shok</EM>
    + <DD>The secret Minbari fighting force established by Valen after the last war with
    + the Shadows. The name translates roughly as "Rangers." Valen was the first
    + leader of this force, or "Ranger One" (<EM>Anla'shok Na</EM>);
    + this post was filled a thousand years later by Jeffrey Sinclair, and later by Delenn.
    + <DT><EM>Denn'bok</EM>
    + <DD>The Minbari fighting pike, nominally a compact cylinder approximately 1 foot
    + in length, but telescoping out to approximately 5 feet upon command. A standard weapon
    + of the Rangers.
    + <DT><EM>Entil'zha</EM>
    + <DD>One of Valen's titles as leader of the Rangers. The title's meaning is unknown;
    + it is thought to be of Vorlon origin.
    + </DL> +
    +
    Example Output +
    +
    +
    Anla'shok +
    The secret Minbari fighting force established by Valen after the last war with + the Shadows. The name translates roughly as "Rangers." Valen was the first + leader of this force, or "Ranger One" (Anla'shok Na); + this post was filled a thousand years later by Jeffrey Sinclair, and later by Delenn. +
    Denn'bok +
    The Minbari fighting pike, nominally a compact cylinder approximately 1 foot + in length, but telescoping out to approximately 5 feet upon command. A standard weapon + of the Rangers. +
    Entil'zha +
    One of Valen's titles as leader of the Rangers. The title's meaning is unknown; + it is thought to be of Vorlon origin. +
    +

    + +

    DT

    + Specifies a term in a definition list. Indicates that the text is a term to be defined, + and should therefore be displayed in the left-hand column of a definition list. +
    +
    Syntax +
    <DT> +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Forbidden +
    Example +
    + <DL>
    + <DT><EM>Anla'shok</EM>
    + <DD>The secret Minbari fighting force established by Valen after the last war with
    + the Shadows. The name translates roughly as "Rangers." Valen was the first
    + leader of this force, or "Ranger One" (<EM>Anla'shok Na</EM>);
    + this post was filled a thousand years later by Jeffrey Sinclair, and later by Delenn.
    + <DT><EM>Denn'bok</EM>
    + <DD>The Minbari fighting pike, nominally a compact cylinder approximately 1 foot
    + in length, but telescoping out to approximately 5 feet upon command. A standard weapon
    + of the Rangers.
    + <DT><EM>Entil'zha</EM>
    + <DD>One of Valen's titles as leader of the Rangers. The title's meaning is unknown;
    + it is thought to be of Vorlon origin.
    + </DL> +
    +
    Example Output +
    +
    +
    Anla'shok +
    The secret Minbari fighting force established by Valen after the last war with + the Shadows. The name translates roughly as "Rangers." Valen was the first + leader of this force, or "Ranger One" (Anla'shok Na); + this post was filled a thousand years later by Jeffrey Sinclair, and later by Delenn. +
    Denn'bok +
    The Minbari fighting pike, nominally a compact cylinder approximately 1 foot + in length, but telescoping out to approximately 5 feet upon command. A standard weapon + of the Rangers. +
    Entil'zha +
    One of Valen's titles as leader of the Rangers. The title's meaning is unknown; + it is thought to be of Vorlon origin. +
    +

    + +

    EM

    + Specifies that the text is emphasized. +
    +
    Syntax +
    <EM> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Notes +
    This may be rendered differently in different browsers. Usually, it is rendered as italics. +
    Example +
    + A thing can have as much value from <EM>where</EM> it is as from
    + <EM>what</EM> it is. +
    +
    Example Output +
    + A thing can have as much value from where it is as from + what it is. +

    + +

    FONT

    + Specifies the size, font and color of text. +
    +
    Syntax +
    <FONT [SIZE=n] + [FACE="name1 [,name2 [...]]" ] + [COLOR="colorvalue"] > +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Required +
    Parameters +
    + SIZE=n

    + Optional: Specifies a font size between 1 and 7 (7 is largest). A value with a + + or - sign in front of it denotes a size relative to the current BASEFONT setting. + Relative sizes are not cumulative, so two <FONT SIZE=+1> tags in a row will not + increase the size by 2. Default is no change.

    + FACE="name1 [,name2 [...]]"

    + Optional: Specifies the font face name to be used. A list of font face names can + be specified here; if the font face name specified by name1 is installed on the + target system, it will be used, otherwise the font face name specified by name2 + will be tried if it is specified, and so on. If none of those fonts are available, the + default font (as configured in the browser) will be used. Default is no change.

    + COLOR="colorvalue"

    + Optional: Sets the color of the text. colorvalue may either be specified + as a hexadecimal color value or as a standard color name. Default is no change. See also + Colors. +

    Example +
    + Comparison of font sizes:<P>
    + <FONT SIZE=1>Size 1</FONT>
    + <FONT SIZE=2>Size 2</FONT>
    + <FONT SIZE=3>Size 3</FONT>
    + <FONT SIZE=4>Size 4</FONT>
    + <FONT SIZE=5>Size 5</FONT>
    + <FONT SIZE=6>Size 6</FONT>
    + <FONT SIZE=7>Size 7</FONT><P>
    + <FONT SIZE=5 FACE="Comic Sans MS, Arial, Helvetica" COLOR="green">
    + This text will be displayed in green Comic Sans MS if you have that font, otherwise either
    + Arial or Helvetica.</FONT><P>
    + <FONT SIZE=2 COLOR="#007FFF">A footnote in a cool blue color.</FONT> +
    +
    Example Output +
    + Comparison of font sizes:

    + Size 1 + Size 2 + Size 3 + Size 4 + Size 5 + Size 6 + Size 7

    + + This text will be displayed in green Comic Sans MS if you have that font, otherwise either + Arial or Helvetica.

    + A footnote in a cool blue color. +


    + +

    H1, H2, H3, H4, H5, H6

    + Renders text in heading style. Use H1 through H6 to specify different sizes and styles of + heading. +
    +
    Syntax +
    <Hn [ALIGN=LEFT|CENTER|RIGHT] > +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Required +
    Parameters +
    + n

    + Required: Sets the heading level. Valid values range from 1 to 6 (1 highest-level + and usually largest).

    + ALIGN=LEFT|CENTER|RIGHT

    + Optional: Sets the alignment of the header text. Default is LEFT. +

    Notes +
    These styles may be rendered differently in different browsers. +
    Example +
    + <H1>The most general topic</H1>
    + <H2>A subhead under that general topic</H2>
    + <H3>And a further subhead under that subhead</H3>
    + <H4>A further specialization of that subhead</H4>
    + <H5>A topic even more specific under these subheads</H5>
    + <H6>The most specialized topic of all</H6> +
    +
    Example Output +
    +

    The most general topic

    +

    A subhead under that general topic

    +

    And a further subhead under that subhead

    +

    A further specialization of that subhead

    +
    A topic even more specific under these subheads
    +
    The most specialized topic of all
    +

    + +

    HR

    + Draws a horizontal rule. +
    +
    Syntax +
    <HR [ALIGN=LEFT|CENTER|RIGHT] [COLOR="colorvalue"] + [NOSHADE] [SIZE=n] [WIDTH=n] > +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Forbidden +
    Parameters +
    + [ALIGN=LEFT|CENTER|RIGHT]

    + Optional: Draws the rule left-aligned, right-aligned, or centered. The default + is CENTER.

    + COLOR="colorvalue"

    + Optional: Sets the color of the rule. colorvalue may either be specified + as a hexadecimal color value or as a standard color name. Default is the standard 3-D color. + See also Colors.

    + NOSHADE

    + Optional: Draws the rule without 3-D shading.

    + SIZE=n

    + Optional: Specifies the height of the rule in pixels.

    + WIDTH=n

    + Optional: Specifies the width of the rule, either in pixels, or, if the percent (%) + sign is appended to the value, as a percentage of total window width. Default is 100%. +

    Example +
    + Here's a small line (half the width).<HR WIDTH=50%>
    + And a tiny green line, off to the right:<HR WIDTH=96 ALIGN=RIGHT COLOR="green" NOSHADE#> +
    +
    Example Output +
    + Here's a small line (half the width).

    + And a tiny green line, off to the right:
    +

    + +

    I

    + Renders enclosed text in italics. +
    +
    Syntax +
    <I> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Example +
    + Some of the text on this line will be <I>rendered in italic</I> type. + +
    Example Output +
    + Some of the text on this line will be rendered in italic type. +

    + +

    IMG

    + Inserts an image into the text. +
    +
    Syntax +
    <IMG SRC="location" [ALIGN=alignoption] + [ALT="text"] [BORDER=n] [HEIGHT=n] [HSPACE=n] + [VSPACE=n] [WIDTH=n] > +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Forbidden +
    Parameters +
    + SRC="location"

    + Required: Specifies the URL of the picture to be inserted.

    + ALIGN=alignoption

    + Optional: Sets the alignment of the image relative to the surrounding text; + alignoption may be one of the following values: +

      +
    • TOP - Surrounding text is aligned with the top of the image. +
    • MIDDLE - Surrounding text is aligned with the middle of the image. +
    • BOTTOM - Surrounding text is aligned with the bottom of the image. +
    • LEFT - The picture is drawn as a left-flush "floating image," and text + flows around it. +
    • RIGHT - The picture is drawn as a right-flush "floating image," and text + flows around it. +

    + ALT="text"

    + Optional: Specifies text to be displayed in place of the picture if the browser is + non-graphical or has images turned off. Some browsers also display this text as a "tooltip" + element when the mouse is held over the image.

    + BORDER=n

    + Optional: Specifies the size of a border to be drawn around the image. If the image + is a hyperlink, the border is drawn in the appropriate hyperlink color. If the image is not + a hyperlink, the border is invisible.

    + HEIGHT=n

    + Optional: Along with WIDTH=, specifies the size at which the + picture is drawn. If the picture's actual dimensions differ from those specified, the + picture is stretched to match what's specified.

    + HSPACE=n

    + Optional: Along with VSPACE=, specifies margins for the image. + Similar to BORDER=, except the margins are not painted with color when the + image is a hyperlink.

    + VSPACE=n

    + Optional: Along with HSPACE=, specifies margins for the image. + Similar to BORDER=, except the margins are not painted with color when the + image is a hyperlink.

    + WIDTH=n

    + Optional: Along with HEIGHT=, specifies the size at which the + picture is drawn. If the picture's actual dimensions differ from those specified, the + picture is stretched to match what's specified. +

    Notes +
    Specification of HEIGHT= and WIDTH= speeds up display + of the page, as the browser can then preallocate space for the image and lay out the text + appropriately before the image data is downloaded. +
    Example +
    + This image is positioned <IMG SRC="images/ref32smi.gif" WIDTH=32 HEIGHT=32 ALIGN=BOTTOM>
    + with bottom alignment.<P>
    + This image is positioned <IMG SRC="images/ref32smi.gif" WIDTH=32 HEIGHT=32 ALIGN=TOP>
    + with top alignment.<P>
    + This image is positioned <IMG SRC="images/ref32smi.gif" WIDTH=32 HEIGHT=32 ALIGN=MIDDLE>
    + with middle alignment.<P>
    + <IMG SRC="images/ref64yr.gif" WIDTH=64 HEIGHT=64 HSPACE=5 ALIGN=LEFT>
    + This is an image aligned on the left...<P>
    + <IMG SRC="images/ref64yr.gif" WIDTH=64 HEIGHT=64 HSPACE=5 ALIGN=RIGHT>
    + This is an image aligned on the right...<BR CLEAR=BOTH> +
    +
    Example Output +
    + This image is positioned + with bottom alignment.

    + This image is positioned + with top alignment.

    + This image is positioned + with middle alignment.

    + + This is an image aligned on the left...

    + + This is an image aligned on the right...
    +


    + +

    KBD

    + Specifies text to be entered at the keyboard. +
    +
    Syntax +
    <KBD> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Notes +
    This may be rendered differently in different browsers. Usually, it is rendered + as fixed-width type. +
    Example +
    + To begin adding a new user account, enter the command <KBD>vi /etc/passwd</KBD>
    + at the shell prompt. +
    +
    Example Output +
    + To begin adding a new user account, enter the command vi /etc/passwd + at the shell prompt. +

    + +

    LI

    + Denotes the beginning of a new list item within a DIR, MENU, OL, or UL block. +
    +
    Syntax +
    <LI [TYPE=order-type] [VALUE=n] > +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Optional +
    Parameters +
    + TYPE=order-type

    + Optional: Specifies a new style for an ordered list. The order-type + can be one of these values: +

      +
    • A - Use upper-case letters. +
    • a - Use lower-case letters. +
    • I - Use upper-case Roman numerals. +
    • i - Use lower-case Roman numerals. +
    • 1 - Use Arabic numerals. +

    + VALUE=n

    + Optional: Changes the count for an ordered list as it progresses. +

    Example +
    + Things to get in life:
    + <UL>
    + <LI>Good education
    + <LI>Exact change
    + <LI>Happiness
    + <LI>Portable stereo
    + <LI>Sense of self-worth
    + <LI>Account on Electric Minds
    + </UL> +
    +
    Example Output +
    + Things to get in life: +
      +
    • Good education +
    • Exact change +
    • Happiness +
    • Portable stereo +
    • Sense of self-worth +
    • Account on Electric Minds +
    +

    + +

    MENU

    + Denotes a list of items. Specifies that the following block consists of individual items, + each beginning with an LI element. +
    +
    Syntax +
    <MENU> +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Required +
    Notes +
    This may be rendered differently in different browsers, but will usually be rendered + similarly to the UL tag. +
    Example +
    + Information about Linux:
    + <MENU>
    + <LI><A HREF="http://www.linux.com">Linux.com</A>
    + <LI><A HREF="http://linuxtoday.com">Linux Today</A>
    + <LI><A HREF="http://lwn.net">USA Today</A>
    + <LI><A HREF="http://www.freshmeat.net">Freshmeat</A>
    + <LI><A HREF="http://slashdot.org">Slashdot</A>
    + </MENU> +
    +
    Example Output +
    + Information about Linux: + +
  • Linux.com +
  • Linux Today +
  • Linux Weekly News +
  • Freshmeat +
  • Slashdot +
  • +

    + +

    NOBR

    + Turns off line breaking. Renders text without line breaks. +
    +
    Syntax +
    <NOBR> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Example +
    + <NOBR>Here's a line of text I don't want to be broken . . .
    + there could be an awful lot of text here and it must stay on one line . . .
    + here's the end of the line.</NOBR> +
    +
    Example Output +
    + Here's a line of text I don't want to be broken . . . + there could be an awful lot of text here and it must stay on one line . . . + here's the end of the line. +

    + +

    OL

    + Draws lines of text as an ordered list. Specifies that the following block consists of + individual items, each beginning with an LI tag. The items are numbered. +
    +
    Syntax +
    <OL [START=n] [TYPE=order-type] > +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Required +
    Parameters +
    + START=n

    + Optional: Specifies a starting index number for the list. The default is 1.

    + TYPE=order-type

    + Optional: Specifies a style for the ordered list. The order-type + can be one of these values: +

      +
    • A - Use upper-case letters. +
    • a - Use lower-case letters. +
    • I - Use upper-case Roman numerals. +
    • i - Use lower-case Roman numerals. +
    • 1 - Use Arabic numerals. +

    + The default is to use Arabic numerals. +

    Example +
    + <OL>
    + <LI>Pick up the TV remote control.
    + <LI>Push the POWER button to turn on the TV.
    + <LI>Change to channel 3.
    + <LI>Switch to the VCR remote control.
    + <LI>Push the POWER button to turn on the VCR.
    + <LI>Push the TV/VCR button to switch to the VCR input.
    + <LI>Change to desired channel on the VCR.
    + <LI>Insert a blank tape into the VCR.
    + <LI>Press RECORD.
    + </OL> +
    +
    Example Output +
    +
      +
    1. Pick up the TV remote control. +
    2. Push the POWER button to turn on the TV. +
    3. Change to channel 3. +
    4. Switch to the VCR remote control. +
    5. Push the POWER button to turn on the VCR. +
    6. Push the TV/VCR button to switch to the VCR input. +
    7. Change to desired channel on the VCR. +
    8. Insert a blank tape into the VCR. +
    9. Press RECORD. +
    +

    + +

    P

    + Inserts a paragraph break and denotes a paragraph. +
    +
    Syntax +
    <P [ALIGN=LEFT|CENTER|RIGHT] > +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Optional +
    Parameters +
    ALIGN=LEFT|CENTER|RIGHT

    + Sets the alignment of the paragraph. The align-type can be LEFT, CENTER, or RIGHT. + Default is left alignment. +

    Example +
    + There will be a paragraph break<P>between these two lines.
    + <P ALIGN=RIGHT>Here's a paragraph that will be flush-right.</P>
    + And back to normal again. +
    +
    Example Output +
    + There will be a paragraph break

    between these two lines. +

    Here's a paragraph that will be flush-right.

    + And back to normal again. +

    + +

    Q

    + Sets apart a short quotation in text. +
    +
    Syntax +
    <Q> +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Required +
    Notes +
    This may be rendered differently in different browsers. +
    Example +
    + <Q>Software is like sex; it's better when it's free.</Q> - Linus Torvalds + +
    Example Output +
    + Software is like sex; it's better when it's free. - Linus Torvalds +

    + +

    S

    + Renders text in strikethrough type. +
    +
    Syntax +
    <S> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Notes +
    This may be rendered differently in different browsers. +
    Example +
    + We have a lot of <S>crazy people</S> unique individuals in the Playground. + +
    Example Output +
    + We have a lot of crazy people unique individuals in the Playground. +

    + +

    SAMP

    + Specifies sample text. +
    +
    Syntax +
    <SAMP> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Notes +
    This may be rendered differently in different browsers. +
    Example +
    + <SAMP>If one-third of a hive of bees flies to a rose bush, one-fifth flies to a daisy,
    + three times the difference of those two numbers flies to an apple tree, and one bee hovers
    + attracted by both a jasmine and a tulip, how many bees are there in all?</SAMP> +
    +
    Example Output +
    + If one-third of a hive of bees flies to a rose bush, one-fifth flies to a daisy, + three times the difference of those two numbers flies to an apple tree, and one bee hovers + attracted by both a jasmine and a tulip, how many bees are there in all? +

    + +

    SMALL

    + Renders text in smaller type. +
    Syntax +
    + <SMALL> +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Required +
    Example +
    + Some of the text on this line will be <SMALL>rendered in small</SMALL> type. + +
    Example Output +
    + Some of the text on this line will be rendered in small type. +

    + +

    STRIKE

    + Renders text in strikethrough type. +
    +
    Syntax +
    <STRIKE> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Notes +
    This may be rendered differently in different browsers. +
    Example +
    + We have a lot of <STRIKE>crazy people</STRIKE> unique individuals in the Playground. + +
    Example Output +
    + We have a lot of crazy people unique individuals in the Playground. +

    + +

    STRONG

    + Specifies that the text is strongly emphasized. +
    +
    Syntax +
    <STRONG> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Notes +
    This may be rendered differently in different browsers. Usually, it is rendered as bold face. +
    Example +
    + A thing can have as much value from <STRONG>where</STRONG> it is as from
    + <STRONG>what</STRONG> it is. +
    +
    Example Output +
    + A thing can have as much value from where it is as from + what it is. +

    + +

    SUB

    + Displays the text in a smaller font, and with its baseline lower than that of the surrounding text. +
    +
    Syntax +
    <SUB> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Notes +
    This may be rendered differently in different browsers. +
    Example +
    + Fibonacci numbers are computed as follows:<BLOCKQUOTE>
    + <EM>F<SUB>0</SUB></EM> = 0<BR>
    + <EM>F<SUB>1</SUB></EM> = 1<BR>
    + <EM>F<SUB>n</SUB></EM> =
    + <EM>F<SUB>n-2</SUB></EM> + <EM>F<SUB>n-1</SUB></EM>
    + for all integer <EM>n</EM>>1</BLOCKQUOTE> +
    +
    Example Output +
    + Fibonacci numbers are computed as follows:
    + F0 = 0
    + F1 = 1
    + Fn = + Fn-2 + Fn-1 + for all integer n>1
    +

    + +

    SUP

    + Displays the text in a smaller font, and with its baseline higher than that of the surrounding text. +
    +
    Syntax +
    <SUP> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Notes +
    This may be rendered differently in different browsers. +
    Example +
    + Fermat's Last Theorem states that, for any integer <EM>n</EM> greater than 2,
    + there is no combination of values <EM>x</EM>, <EM>y</EM>,
    + and <EM>z</EM> such that <EM>x<SUP>2</SUP></EM>
    + + <EM>y<SUP>2</SUP></EM> = <EM>z<SUP>2</SUP></EM>. +
    +
    Example Output +
    + Fermat's Last Theorem states that, for any integer n greater than 2, + there is no combination of values x, y, + and z such that xn + + yn = zn. +

    + +

    TT

    + Indicates "teletype" or "typewriter text." Renders text in fixed-width type. +
    +
    Syntax +
    <TT> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Notes +
    This may be rendered differently in different browsers. Usually, it is rendered + as a fixed-width font. +
    Example +
    + <TT>This style of text can be useful for code listings.</TT> + +
    Example Output +
    + This style of text can be useful for code listings. +

    + +

    U

    + Displays text as underlined. +
    +
    Syntax +
    <U> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Example +
    + A thing can have as much value from <U>where</U> it is as from
    + <U>what</U> it is. +
    +
    Example Output +
    + A thing can have as much value from where it is as from + what it is. +

    + +

    UL

    + Draws lines of text as a bulleted list. Specifies that the following block consists of + individual items, each beginning with an LI tag. The items are bulleted. +
    +
    Syntax +
    <UL> +
    Allowed in Topic Names +
    No +
    Closing Tag +
    Required +
    Example +
    + Things to get in life:
    + <UL>
    + <LI>Good education
    + <LI>Exact change
    + <LI>Happiness
    + <LI>Portable stereo
    + <LI>Sense of self-worth
    + <LI>Account on Electric Minds
    + </UL> +
    +
    Example Output +
    + Things to get in life: +
      +
    • Good education +
    • Exact change +
    • Happiness +
    • Portable stereo +
    • Sense of self-worth +
    • Account on Electric Minds +
    +

    + +

    VAR

    + Indicates placeholder text for a variable. +
    +
    Syntax +
    <VAR> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Required +
    Notes +
    This may be rendered differently in different browsers. Usually, it is rendered as italics. +
    Example +
    + Enter the <VAR>filename</VAR> in the appropriate field in the dialog box. + +
    Example Output +
    + Enter the filename in the appropriate field in the dialog box. +

    + +

    WBR

    + Inserts a soft line break in a block of text formatted using the NOBR tag. +
    +
    Syntax +
    <NOBR> +
    Allowed in Topic Names +
    Yes +
    Closing Tag +
    Optional +
    Notes +
    If it is not placed inside a pair of NOBR tags, this tag has no effect. +
    Example +
    + <NOBR>This text will not break anywhere unless I tell it to. The text will
    + just keep on going until it runs off the edge of the screen.
    + <WBR>But I just told it to break here.</NOBR> +
    +
    Example Output +
    + This text will not break anywhere unless I tell it to. The text will + just keep on going until it runs off the edge of the screen. + But I just told it to break here. +

    + +

    Colors

    + When color values are called for in any HTML tag, they may be specified either by name or + by color value. The following named colors are supported: + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Black + + Maroon + + Gray + + Red +
    + Navy + + Purple + + Blue + + Fuchsia +
    + Green + + Olive + + Lime + + Yellow +
    + Teal + + Silver + + Aqua + + White +
    +Colors may also be specified as a color value in the form "#RRGGBB", where RR, +GG, and BB represent color intensity values for red, green, and blue, +respectively, as hexadecimal values from 00 to FF (decimal 0 to 255). For example, the color +"red" in the table above may also be represented as "#FF0000". In this color example, red +is set to its highest possible value (hex FF, decimal 255), while green and blue are set to 0. +

    Although red-green-blue color values theoretically allow for many thousands of colors, +the actual number of colors available depends on the color capabilities of the devices the +document will be viewed on. Many personal computers can display only 16 colors due to the +type of video display adapter they use. +


    + +

    Special Characters

    +In HTML, certain special characters may be written as &name;, where +name is a symbolic name. The most important of these are &lt; (the less-than +sign, or <), &gt; (the greater-than sign, or >), and &amp; (the ampersand +itself, or &). These allow you to use characters normally used by HTML to indicate +formatting commands.

    +In addition, special characters may be written as &#nnn;, where nnn +is a decimal character code in the document's character set (usually the ISO Latin-1 character +set).

    +Here follows a listing of additional special characters in HTML. (NOTE: +Your browser may not display all of these properly.) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    &nbsp; = nonbreaking space&iexcl; = inverted exclamation mark (¡)&cent; = cent sign (¢)&pound; = pound sterling sign (£)
    &curren; = general currency sign (¤)&yen; = yen sign (¥)&brvbar; = broken vertical bar (¦)&sect; = section sign (§)
    &uml; = umlaut (dieresis) (¨)&copy; = copyright sign (©)&ordf; = feminine ordinal (ª)&laquo; = left angle quotes («)
    &not; = not sign (¬)&shy; = soft hyphen (­)&reg; = registered sign (®)&macr; = macron (¯)
    &deg; = degree sign (°)&plusmn; = plus-or-minus sign (±)&sup2; = superscript 2 (²)&sup3; = superscript 3 (³)
    &acute; = acute accent (´)&micro; = micro sign (µ)&para; = paragraph sign (¶)&middot; = middle dot (·)
    &cedil; = cedilla (¸)&sup1; = superscript 1 (¹)&ordm; = masculine ordinal (º)&raquo; = right angle quotes (»)
    &frac14; = fraction 1/4 (¼)&frac12; = fraction 1/2 (½)&frac34; = fraction 3/4 (¾)&iquest; = inverted question mark (¿)
    &Agrave; = A grave accent (À)&Aacute; = A acute accent (Á)&Acirc; = A circumflex (Â)&Atilde; = A tilde (Ã)
    &Auml; = A umlaut (Ä)&Aring; = A ring (Å)&AElig; = AE ligature (Æ)&Ccedil; = C cedilla (Ç)
    &Egrave; = E grave accent (È)&Eacute; = E acute accent (É)&Ecirc; = E circumflex (Ê)&Euml; = E umlaut (Ë)
    &Igrave; = I grave accent (Ì)&Iacute; = I acute accent (Í)&Icirc; = I circumflex (Î)&Iuml; = I umlaut (Ï)
    &ETH; = Icelandic capital Eth (Ð)&Ntilde; = N tilde (Ñ)&Ograve; = O grave accent (Ò)&Oacute; = O acute accent (Ó)
    &Ocirc; = O circumflex (Ô)&Otilde; = O tilde (Õ)&Ouml; = O umlaut (Ö)&times; = multiply sign (×)
    &Oslash; = O slash (Ø)&Ugrave; = U grave accent (Ù)&Uacute; = U acute accent (Ú)&Ucirc; = U circumflex (Û)
    &Uuml; = U umlaut (Ü)&Yacute; = Y acute accent (Ý)&THORN; = Icelandic capital Thorn (Þ)&szlig; = German sharp s (ß)
    &agrave; = a grave accent (à)&aacute; = a acute accent (á)&acirc; = a circumflex (â)&atilde; = a tilde (ã)
    &auml; = a umlaut (ä)&aring; = a ring (å)&aelig; = ae ligature (æ)&ccedil; = c cedilla (ç)
    &egrave; = e grave accent (è)&eacute; = e acute accent (é)&ecirc; = e circumflex (ê)&euml; = e umlaut (ë)
    &igrave; = i grave accent (ì)&iacute; = i acute accent (í)&icirc; = i circumflex (î)&iuml; = i umlaut (ï)
    &eth; = Icelandic small Eth (ð)&ntilde; = n tilde (ñ)&ograve; = o grave accent (ò)&oacute; = o acute accent (ó)
    &ocirc; = o circumflex (ô)&otilde; = o tilde (õ)&ouml; = o umlaut (ö)&divide; = divide sign (÷)
    &oslash; = o slash (ø)&ugrave; = u grave accent (ù)&uacute; = u acute accent (ú)&ucirc; = u circumflex (û)
    &uuml; = u umlaut (ü)&yacute; = y acute accent (ý)&thorn; = Icelandic small Thorn (þ)&yuml; = y umlaut (ÿ)


    + +
    Original of this document is copyright © 1997 Durand Communications, All rights +reserved. Used in Venice by permission.
    +
    + + diff --git a/web/static/images/ref-c0.gif b/web/static/images/ref-c0.gif new file mode 100644 index 0000000..8959190 Binary files /dev/null and b/web/static/images/ref-c0.gif differ diff --git a/web/static/images/ref-c1.gif b/web/static/images/ref-c1.gif new file mode 100644 index 0000000..a082a6f Binary files /dev/null and b/web/static/images/ref-c1.gif differ diff --git a/web/static/images/ref-c2.gif b/web/static/images/ref-c2.gif new file mode 100644 index 0000000..45a2c1c Binary files /dev/null and b/web/static/images/ref-c2.gif differ diff --git a/web/static/images/ref-c3.gif b/web/static/images/ref-c3.gif new file mode 100644 index 0000000..a049709 Binary files /dev/null and b/web/static/images/ref-c3.gif differ diff --git a/web/static/images/ref-c4.gif b/web/static/images/ref-c4.gif new file mode 100644 index 0000000..9446a5b Binary files /dev/null and b/web/static/images/ref-c4.gif differ diff --git a/web/static/images/ref-c5.gif b/web/static/images/ref-c5.gif new file mode 100644 index 0000000..fc9d477 Binary files /dev/null and b/web/static/images/ref-c5.gif differ diff --git a/web/static/images/ref-c6.gif b/web/static/images/ref-c6.gif new file mode 100644 index 0000000..7607a04 Binary files /dev/null and b/web/static/images/ref-c6.gif differ diff --git a/web/static/images/ref-c7.gif b/web/static/images/ref-c7.gif new file mode 100644 index 0000000..02439cd Binary files /dev/null and b/web/static/images/ref-c7.gif differ diff --git a/web/static/images/ref-c8.gif b/web/static/images/ref-c8.gif new file mode 100644 index 0000000..bc67d6d Binary files /dev/null and b/web/static/images/ref-c8.gif differ diff --git a/web/static/images/ref-c9.gif b/web/static/images/ref-c9.gif new file mode 100644 index 0000000..7bdcc7c Binary files /dev/null and b/web/static/images/ref-c9.gif differ diff --git a/web/static/images/ref-ca.gif b/web/static/images/ref-ca.gif new file mode 100644 index 0000000..9cc6b91 Binary files /dev/null and b/web/static/images/ref-ca.gif differ diff --git a/web/static/images/ref-cb.gif b/web/static/images/ref-cb.gif new file mode 100644 index 0000000..1956f0d Binary files /dev/null and b/web/static/images/ref-cb.gif differ diff --git a/web/static/images/ref-cc.gif b/web/static/images/ref-cc.gif new file mode 100644 index 0000000..f6f82e1 Binary files /dev/null and b/web/static/images/ref-cc.gif differ diff --git a/web/static/images/ref-cd.gif b/web/static/images/ref-cd.gif new file mode 100644 index 0000000..947b41f Binary files /dev/null and b/web/static/images/ref-cd.gif differ diff --git a/web/static/images/ref-ce.gif b/web/static/images/ref-ce.gif new file mode 100644 index 0000000..e38ceff Binary files /dev/null and b/web/static/images/ref-ce.gif differ diff --git a/web/static/images/ref-cf.gif b/web/static/images/ref-cf.gif new file mode 100644 index 0000000..b5eeeb5 Binary files /dev/null and b/web/static/images/ref-cf.gif differ diff --git a/web/static/images/ref32smi.gif b/web/static/images/ref32smi.gif new file mode 100644 index 0000000..ce5deb2 Binary files /dev/null and b/web/static/images/ref32smi.gif differ diff --git a/web/static/images/ref64yr.gif b/web/static/images/ref64yr.gif new file mode 100644 index 0000000..b37d48b Binary files /dev/null and b/web/static/images/ref64yr.gif differ