added the ability for the HTML checker to recognize "emoticon" character

sequences and replace them with special tags, which the post-formatting
task will in turn replace with real emoticons (GIFs).
This commit is contained in:
Eric J. Bowersox 2004-07-27 08:54:48 +00:00
parent 8a745717e1
commit 15224c4f3f
13 changed files with 783 additions and 405 deletions

View File

@ -25,7 +25,7 @@
<text>Smile!</text>
</icon>
<icon name="frown">
<pattern>:(</pattern>
<pattern><![CDATA[:(]]></pattern>
<image width="15" height="15" fixup="true">emote/ei_frown.gif</image>
<text>frown...</text>
</icon>

View File

@ -328,8 +328,10 @@
<config name="post-body">
<options wordwrap="55" angles="true" parens="true" discardHTML="false"/>
<output-filter type="normal" class="com.silverwrist.venice.htmlcheck.filters.HTMLEncodingFilter"/>
<rewriter type="string" class="com.silverwrist.venice.htmlcheck.filters.EmoticonRewriter"/>
<rewriter type="string" class="com.silverwrist.venice.htmlcheck.filters.EmailRewriter"/>
<rewriter type="string" class="com.silverwrist.venice.htmlcheck.filters.URLRewriter"/>
<rewriter type="tag" class="com.silverwrist.venice.htmlcheck.filters.EmoticonTagHandler"/>
<rewriter type="tag" class="com.silverwrist.venice.db.PostLinkRewriter"/>
<rewriter type="tag" class="com.silverwrist.venice.db.UserNameRewriter"/>
<rewriter type="tag" class="com.silverwrist.venice.htmlcheck.filters.EmailRewriter"/>
@ -345,9 +347,11 @@
<config name="preview">
<options wordwrap="55" angles="true" parens="true" discardHTML="false"/>
<output-filter type="normal" class="com.silverwrist.venice.htmlcheck.filters.HTMLEncodingFilter"/>
<rewriter type="string" class="com.silverwrist.venice.htmlcheck.filters.EmoticonRewriter"/>
<rewriter type="string" class="com.silverwrist.venice.htmlcheck.filters.EmailRewriter"/>
<rewriter type="string" class="com.silverwrist.venice.htmlcheck.filters.URLRewriter"/>
<rewriter type="word" class="com.silverwrist.venice.htmlcheck.filters.SpellingRewriter"/>
<rewriter type="tag" class="com.silverwrist.venice.htmlcheck.filters.EmoticonTagHandler"/>
<rewriter type="tag" class="com.silverwrist.venice.db.PostLinkRewriter"/>
<rewriter type="tag" class="com.silverwrist.venice.db.UserNameRewriter"/>
<rewriter type="tag" class="com.silverwrist.venice.htmlcheck.filters.EmailRewriter"/>
@ -367,8 +371,10 @@
<options wordwrap="55" rewrap="true" angles="true" parens="true" discardHTML="false"
discardRejected="true" discardComments="true" discardXML="true"/>
<output-filter type="normal" class="com.silverwrist.venice.htmlcheck.filters.HTMLEncodingFilter"/>
<rewriter type="string" class="com.silverwrist.venice.htmlcheck.filters.EmoticonRewriter"/>
<rewriter type="string" class="com.silverwrist.venice.htmlcheck.filters.EmailRewriter"/>
<rewriter type="string" class="com.silverwrist.venice.htmlcheck.filters.URLRewriter"/>
<rewriter type="tag" class="com.silverwrist.venice.htmlcheck.filters.EmoticonTagHandler"/>
<rewriter type="tag" class="com.silverwrist.venice.db.PostLinkRewriter"/>
<rewriter type="tag" class="com.silverwrist.venice.db.UserNameRewriter"/>
<rewriter type="tag" class="com.silverwrist.venice.htmlcheck.filters.EmailRewriter"/>

View File

@ -65,8 +65,8 @@ public class GlobalSiteImpl implements GlobalSite
Runnable task = getNextTaskToRun(quitting);
while (task!=null)
{ // null task indicates we are shutting down
if (my_logger.isDebugEnabled())
my_logger.debug("Servicing task of class " + task.getClass().getName());
if (s_thread_logger.isDebugEnabled())
s_thread_logger.debug("Servicing task of class " + task.getClass().getName());
try
{ // run the background task
@ -75,7 +75,7 @@ public class GlobalSiteImpl implements GlobalSite
} // end try
catch (Exception e)
{ // log the exception and continue
my_logger.error("Background thread caught exception in task",e);
s_thread_logger.error("Background thread caught exception in task",e);
} // end catch
@ -92,11 +92,11 @@ public class GlobalSiteImpl implements GlobalSite
public void run()
{
my_logger.info("Background thread starting");
s_thread_logger.info("Background thread starting");
doRunLoop(false);
my_logger.info("Background thread quitting");
s_thread_logger.info("Background thread quitting");
doRunLoop(true);
my_logger.info("Background thread finished");
s_thread_logger.info("Background thread finished");
} // end run
@ -107,8 +107,8 @@ public class GlobalSiteImpl implements GlobalSite
*--------------------------------------------------------------------------------
*/
private static Category logger = Category.getInstance(GlobalSiteImpl.class);
private static Category my_logger = Category.getInstance(BackgroundThread.class);
private static Logger logger = Logger.getLogger(GlobalSiteImpl.class);
private static Logger s_thread_logger = Logger.getLogger(BackgroundThread.class);
private static final int NUM_TASK_THREADS = 4; // TODO: make this configurable
@ -117,18 +117,18 @@ public class GlobalSiteImpl implements GlobalSite
*--------------------------------------------------------------------------------
*/
private ServiceProvider engine_svc = null; // ServiceProvider for the VeniceEngine
private ServiceProvider m_engine_svc = null; // ServiceProvider for the VeniceEngine
private Set m_privileged_addrs = Collections.EMPTY_SET; // privileged addresses
private DataPool datapool = null; // the database pool
private Properties email_props = null; // email properties
private javax.mail.Session mailsession = null; // email session object
private StockMessages stock_messages = null; // stock messages holder
private HashMap html_checkers = new HashMap(); // HTML checkers
private SecurityMonitorEnvironment sm_env; // security monitor environment
private volatile boolean task_running = true; // running tasks flag
private Object task_semaphore = new Object(); // semaphore used for tasks
private LinkedList[] task_queues; // the task queues
private Thread[] task_threads; // the task threads
private DataPool m_datapool = null; // the database pool
private Properties m_email_props = null; // email properties
private javax.mail.Session m_mailsession = null; // email session object
private StockMessages m_stock_messages = null; // stock messages holder
private HashMap m_html_checkers = new HashMap(); // HTML checkers
private SecurityMonitorEnvironment m_sm_env; // security monitor environment
private volatile boolean m_task_running = true; // running tasks flag
private Object m_task_semaphore = new Object(); // semaphore used for tasks
private LinkedList[] m_task_queues; // the task queues
private Thread[] m_task_threads; // the task threads
/*--------------------------------------------------------------------------------
* Constructor
@ -138,7 +138,7 @@ public class GlobalSiteImpl implements GlobalSite
public GlobalSiteImpl(ServiceProvider engine_svc, Element config, String application_root)
throws ConfigException
{
this.engine_svc = engine_svc;
m_engine_svc = engine_svc;
XMLLoader loader = XMLLoader.get();
// Get the <engine/> section.
@ -168,7 +168,7 @@ public class GlobalSiteImpl implements GlobalSite
try
{ // allocate the data pool object
datapool = new DataPool(sect);
m_datapool = new DataPool(sect);
} // end try
catch (SQLException e)
@ -183,31 +183,31 @@ public class GlobalSiteImpl implements GlobalSite
sect_h = new DOMElementHelper(sect);
// initialize the email properties and get a mail session object
email_props = new Properties();
email_props.put("mail.transport.protocol","smtp");
email_props.put("mail.smtp.host",sect_h.getSubElementText("smtp-host"));
email_props.put("mail.from",sect_h.getSubElementText("mail-from-addr"));
email_props.put("com.silverwrist.venice.email.mailer",sect_h.getSubElementText("mailer"));
mailsession = javax.mail.Session.getInstance(email_props,null);
m_email_props = new Properties();
m_email_props.put("mail.transport.protocol","smtp");
m_email_props.put("mail.smtp.host",sect_h.getSubElementText("smtp-host"));
m_email_props.put("mail.from",sect_h.getSubElementText("mail-from-addr"));
m_email_props.put("com.silverwrist.venice.email.mailer",sect_h.getSubElementText("mailer"));
m_mailsession = javax.mail.Session.getInstance(m_email_props,null);
// Get the <messages/> section.
sect = loader.configGetSubSection(config_h,"messages");
// Initialize the stock messages list.
stock_messages = new StockMessages(sect);
m_stock_messages = new StockMessages(sect);
// Initialize the task queues.
int i;
task_queues = new LinkedList[TASK_PRIO_MAX + 1];
for (i=0; i<task_queues.length; i++)
task_queues[i] = new LinkedList();
m_task_queues = new LinkedList[TASK_PRIO_MAX + 1];
for (i=0; i<m_task_queues.length; i++)
m_task_queues[i] = new LinkedList();
// Initialize the threads.
task_threads = new Thread[NUM_TASK_THREADS];
for (i=0; i<task_threads.length; i++)
m_task_threads = new Thread[NUM_TASK_THREADS];
for (i=0; i<m_task_threads.length; i++)
{ // create and kick off the background threads
task_threads[i] = new BackgroundThread(i);
task_threads[i].start();
m_task_threads[i] = new BackgroundThread(i);
m_task_threads[i].start();
} // end for
@ -221,6 +221,10 @@ public class GlobalSiteImpl implements GlobalSite
LazyTreeLexicon lex = new LazyTreeLexicon((String[])(dictionary_tmp.toArray(new String[0])));
this.queueTask(lex,TASK_PRIO_MAX-2); // load the lexicon
// Load the emoticon configuration.
Document ei_config = loader.loadConfigDocument(emoticon_config);
Element ei_root = loader.configGetRootElement(ei_config,"emoticon-config");
// Create the intermediate object map for HTML checker creation, and "seed" it.
HashMap intermediate_map = new HashMap();
SpellingRewriter spell_rewriter = new SpellingRewriter();
@ -230,8 +234,10 @@ public class GlobalSiteImpl implements GlobalSite
intermediate_map.put(postlink_rewriter.getClass().getName(),postlink_rewriter);
UserNameRewriter username_rewriter = new UserNameRewriter(this);
intermediate_map.put(username_rewriter.getClass().getName(),username_rewriter);
EmoticonRewriter emoticon_rewriter = new EmoticonRewriter(emoticon_config);
EmoticonRewriter emoticon_rewriter = new EmoticonRewriter(ei_root);
intermediate_map.put(emoticon_rewriter.getClass().getName(),emoticon_rewriter);
EmoticonTagHandler emoticon_tag = new EmoticonTagHandler(ei_root);
intermediate_map.put(emoticon_tag.getClass().getName(),emoticon_tag);
// Get the <html-checker/> section.
sect = loader.configGetSubSection(config_h,"html-checker");
@ -257,14 +263,14 @@ public class GlobalSiteImpl implements GlobalSite
sect = loader.configGetSubSection(config_h,"security");
// Load the security monitors.
sm_env = new SecurityMonitorEnvironment();
m_sm_env = new SecurityMonitorEnvironment();
nl = sect.getChildNodes();
for (i=0; i<nl.getLength(); i++)
{ // scan through and find security monitors to initialize
Node n = nl.item(i);
if ((n.getNodeType()==Node.ELEMENT_NODE) && (n.getNodeName().equals("security-definition")))
// load one of the initial security definitions
new StaticSecurityMonitor((Element)n,sm_env);
new StaticSecurityMonitor((Element)n,m_sm_env);
} // end for
@ -385,7 +391,7 @@ public class GlobalSiteImpl implements GlobalSite
{
XMLLoader loader = XMLLoader.get();
String checker_name = loader.configGetAttribute(elt,"name");
if (html_checkers.containsKey(checker_name))
if (m_html_checkers.containsKey(checker_name))
throw new ConfigException("config name \"" + checker_name + "\" defined twice",elt);
HTMLCheckerConfig cfg = HTMLCheckerCreator.create();
@ -483,7 +489,7 @@ public class GlobalSiteImpl implements GlobalSite
} // end for
html_checkers.put(checker_name,cfg);
m_html_checkers.put(checker_name,cfg);
} // end createHTMLChecker
@ -491,26 +497,26 @@ public class GlobalSiteImpl implements GlobalSite
{
int i; // loop counter for cycling through priority queues
synchronized (task_semaphore)
synchronized (m_task_semaphore)
{ // acquire the task semaphore
if (quitting)
{ // just scan the queues and return the first available task
for (i=TASK_PRIO_MAX; i>=TASK_PRIO_MIN; i--)
if (!(task_queues[i].isEmpty())) // select a task from highest possible priority queue
return (Runnable)(task_queues[i].removeFirst());
if (!(m_task_queues[i].isEmpty())) // select a task from highest possible priority queue
return (Runnable)(m_task_queues[i].removeFirst());
} // end if
else
{ // work it normally
while (task_running)
while (m_task_running)
{ // look for a task we can do
for (i=TASK_PRIO_MAX; i>=TASK_PRIO_MIN; i--)
if (!(task_queues[i].isEmpty())) // select a task from highest possible priority queue
return (Runnable)(task_queues[i].removeFirst());
if (!(m_task_queues[i].isEmpty())) // select a task from highest possible priority queue
return (Runnable)(m_task_queues[i].removeFirst());
try
{ // wait for something to happen
task_semaphore.wait();
m_task_semaphore.wait();
} // end try
catch (InterruptedException e)
@ -525,7 +531,7 @@ public class GlobalSiteImpl implements GlobalSite
} // end synchronized block
return null; // if get here, task_running is false and we are quitting
return null; // if get here, m_task_running is false and we are quitting
// (or the task queue is empty, if quitting is true)
} // end getNextTaskToRun
@ -538,15 +544,15 @@ public class GlobalSiteImpl implements GlobalSite
public Object queryService(Class klass)
{
if (klass==DataPool.class)
return datapool;
return m_datapool;
if (klass==MailSend.class)
return new BaseMailSend(this,email_props,mailsession);
return new BaseMailSend(this,m_email_props,m_mailsession);
if (klass==SecurityMonitorEnvironment.class)
return sm_env;
return m_sm_env;
if (klass==SecurityMonitor.class)
return sm_env.getMonitor("Global");
return m_sm_env.getMonitor("Global");
if (klass==VeniceEngine.class)
return engine_svc.queryService(klass);
return m_engine_svc.queryService(klass);
throw new NoSuchServiceException("GlobalSite",klass);
} // end queryService
@ -570,7 +576,7 @@ public class GlobalSiteImpl implements GlobalSite
if (klass==HTMLCheckerConfig.class)
{ // get the HTML Checker config
Object rc = html_checkers.get(serviceid);
Object rc = m_html_checkers.get(serviceid);
if (rc==null)
throw new NoSuchServiceException("GlobalSite",klass,serviceid);
return rc;
@ -579,7 +585,7 @@ public class GlobalSiteImpl implements GlobalSite
if (klass==HTMLChecker.class)
{ // create an HTML Checker using the specified HTML Checker config
HTMLCheckerConfig fact = (HTMLCheckerConfig)(html_checkers.get(serviceid));
HTMLCheckerConfig fact = (HTMLCheckerConfig)(m_html_checkers.get(serviceid));
if (fact==null)
throw new NoSuchServiceException("GlobalSite",klass,serviceid);
return fact.createHTMLChecker();
@ -588,7 +594,7 @@ public class GlobalSiteImpl implements GlobalSite
if (klass==SecurityMonitor.class)
{ // get a security monitor from the environment
SecurityMonitor rc = sm_env.getMonitor(serviceid);
SecurityMonitor rc = m_sm_env.getMonitor(serviceid);
if (rc==null)
throw new NoSuchServiceException("GlobalSite",klass,serviceid);
return rc;
@ -613,13 +619,13 @@ public class GlobalSiteImpl implements GlobalSite
public Connection getConnection(String db_selector) throws SQLException
{
// db_selector is ignored for now
return datapool.getConnection();
return m_datapool.getConnection();
} // end getConnection
public String getStockMessage(String key)
{
return stock_messages.get(key);
return m_stock_messages.get(key);
} // end getStockMessage
@ -632,13 +638,13 @@ public class GlobalSiteImpl implements GlobalSite
if (task instanceof AcceptGlobalSite)
((AcceptGlobalSite)task).setGlobalSite(this);
synchronized (task_semaphore)
synchronized (m_task_semaphore)
{ // make sure we are running
// If the running flag is off, only the background tasks themselves may queue new tasks.
if (task_running || Thread.currentThread().getName().startsWith("GlobalSite_bkgd"));
if (m_task_running || Thread.currentThread().getName().startsWith("GlobalSite_bkgd"));
{ // add the task to a queue and notify a thread to take it
task_queues[priority].addLast(task);
task_semaphore.notify();
m_task_queues[priority].addLast(task);
m_task_semaphore.notify();
} // end if
@ -659,20 +665,20 @@ public class GlobalSiteImpl implements GlobalSite
public void shutdown()
{
synchronized (task_semaphore)
synchronized (m_task_semaphore)
{ // notify the task threads that we're quitting
task_running = false;
task_semaphore.notifyAll();
m_task_running = false;
m_task_semaphore.notifyAll();
} // end synchronized block
int i = 0;
while (i<task_threads.length)
while (i<m_task_threads.length)
{ // wait for all background threads to finally die
try
{ // wait for a thread to die
task_threads[i].join();
task_threads[i++] = null;
m_task_threads[i].join();
m_task_threads[i++] = null;
} // end try
catch (InterruptedException e)
@ -681,21 +687,21 @@ public class GlobalSiteImpl implements GlobalSite
} // end while
task_threads = null;
task_queues = null;
task_semaphore = null;
engine_svc = null;
if (datapool!=null)
datapool.closeAllConnections();
datapool = null;
email_props = null;
mailsession = null;
stock_messages = null;
html_checkers.clear();
html_checkers = null;
if (sm_env!=null)
sm_env.shutdown();
sm_env = null;
m_task_threads = null;
m_task_queues = null;
m_task_semaphore = null;
m_engine_svc = null;
if (m_datapool!=null)
m_datapool.closeAllConnections();
m_datapool = null;
m_email_props = null;
m_mailsession = null;
m_stock_messages = null;
m_html_checkers.clear();
m_html_checkers = null;
if (m_sm_env!=null)
m_sm_env.shutdown();
m_sm_env = null;
} // end shutdown

View File

@ -9,9 +9,9 @@
*
* The Original Code is the Venice Web Community System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@ricochet.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
* Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
@ -19,22 +19,22 @@ package com.silverwrist.venice.htmlcheck;
public interface HTMLChecker
{
public abstract void append(String str) throws AlreadyFinishedException;
public void append(String str) throws AlreadyFinishedException;
public abstract void finish() throws AlreadyFinishedException;
public void finish() throws AlreadyFinishedException;
public abstract void reset();
public void reset();
public abstract String getValue() throws NotYetFinishedException;
public String getValue() throws NotYetFinishedException;
public abstract int getLength() throws NotYetFinishedException;
public int getLength() throws NotYetFinishedException;
public abstract int getLines() throws NotYetFinishedException;
public int getLines() throws NotYetFinishedException;
public abstract int getCounter(String name) throws NotYetFinishedException;
public int getCounter(String name) throws NotYetFinishedException;
public abstract Object getContextValue(String name);
public Object getContextValue(String name);
public abstract void setContextValue(String name, Object val);
public void setContextValue(String name, Object val);
} // end interface HTMLChecker

View File

@ -9,9 +9,9 @@
*
* The Original Code is the Venice Web Community System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@ricochet.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
* Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
@ -24,20 +24,31 @@ public class MarkupData
*--------------------------------------------------------------------------------
*/
private String begin_markup;
private String text;
private String end_markup;
private String m_begin_markup;
private String m_text;
private String m_end_markup;
private boolean m_rescan;
/*--------------------------------------------------------------------------------
* Constructor
* Constructors
*--------------------------------------------------------------------------------
*/
public MarkupData(String begin_markup, String text, String end_markup)
{
this.begin_markup = begin_markup;
this.text = text;
this.end_markup = end_markup;
m_begin_markup = begin_markup;
m_text = text;
m_end_markup = end_markup;
m_rescan = false;
} // end constructor
public MarkupData(String begin_markup, String text, String end_markup, boolean rescan)
{
m_begin_markup = begin_markup;
m_text = text;
m_end_markup = end_markup;
m_rescan = rescan;
} // end constructor
@ -48,20 +59,51 @@ public class MarkupData
public String getBeginMarkup()
{
return begin_markup;
return m_begin_markup;
} // end getBeginMarkup
public String getText()
{
return text;
return m_text;
} // end getText
public boolean hasText()
{
return (m_text!=null) && (m_text.length()>0);
} // end hasText
public int getTextLength()
{
return (m_text==null) ? 0 : m_text.length();
} // end getTextLength
public String getEndMarkup()
{
return end_markup;
return m_end_markup;
} // end getEndMarkup
public String getAll()
{
StringBuffer buf = new StringBuffer();
if (m_begin_markup!=null)
buf.append(m_begin_markup);
if (m_text!=null)
buf.append(m_text);
if (m_end_markup!=null)
buf.append(m_end_markup);
return buf.toString();
} // end getAll
public boolean getRescan()
{
return m_rescan;
} // end getRescan
} // end class MarkupData

View File

@ -7,11 +7,11 @@
* 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 <erbo@silcom.com>,
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@ricochet.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
* Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
@ -19,8 +19,8 @@ package com.silverwrist.venice.htmlcheck;
public interface Rewriter
{
public abstract String getName();
public String getName();
public abstract MarkupData rewrite(String data, RewriterServices svc);
public MarkupData rewrite(String data, RewriterServices svc);
} // end interface Rewriter

View File

@ -33,25 +33,25 @@ public class EmoticonRewriter implements Rewriter
*--------------------------------------------------------------------------------
*/
private String m_prefixchars;
private char[] m_prefixchars;
private Map m_patmap;
private int m_minlength;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public EmoticonRewriter(String config_file) throws ConfigException
public EmoticonRewriter(Element root) throws ConfigException
{
// Load the configuration file.
XMLLoader loader = XMLLoader.get();
Document config = loader.loadConfigDocument(config_file);
Element root = loader.configGetRootElement(config,"emoticon-config");
// Get the set of prefix characters.
m_prefixchars = loader.configGetSubElementText(root,"prefix-chars");
String pfxchar = loader.configGetSubElementText(root,"prefix-chars");
m_prefixchars = pfxchar.toCharArray();
HashMap tmp = new HashMap();
m_minlength = Integer.MAX_VALUE;
// Look for all associated icons.
NodeList nl = root.getChildNodes();
@ -66,13 +66,17 @@ public class EmoticonRewriter implements Rewriter
NodeList nl2 = n.getChildNodes();
for (int j=0; j<nl2.getLength(); j++)
{ // look for <pattern/> elements
Node n2 = nl2.item(i);
Node n2 = nl2.item(j);
if ((n2.getNodeType()==Node.ELEMENT_NODE) && n2.getNodeName().equals("pattern"))
{ // get the element text
DOMElementHelper h = new DOMElementHelper((Element)n2);
String pattern = h.getElementText();
if (m_prefixchars.indexOf(pattern.charAt(0))>=0)
if (pfxchar.indexOf(pattern.charAt(0))>=0)
{ // add pattern and recompute minimum length
tmp.put(pattern,icon_name);
m_minlength = Math.min(m_minlength,pattern.length());
} // end if
} // end if
// else skip this element
@ -104,7 +108,74 @@ public class EmoticonRewriter implements Rewriter
public MarkupData rewrite(String data, RewriterServices svc)
{
return null;
int pos = Integer.MAX_VALUE;
for (int i=0; i<m_prefixchars.length; i++)
{ // hunt for the possible beginning of an emoticon sequence
int foo = data.indexOf(m_prefixchars[i]);
if (foo>=0)
pos = Math.min(pos,foo);
} // end for
if (pos==Integer.MAX_VALUE)
return null; // none present - we can short-circuit matters
boolean did_replace = false;
StringBuffer output = new StringBuffer();
String work = data;
do
{ // break off the front part of the string
if (pos>0)
{ // append it and make it work
output.append(work.substring(0,pos));
work = work.substring(pos);
} // end if
boolean looking = true;
if (work.length()>=m_minlength)
{ // there's a chance we have a pattern
for (Iterator it=m_patmap.entrySet().iterator(); looking && it.hasNext(); )
{ // hunt through all the smiley entries
Map.Entry ntry = (Map.Entry)(it.next());
String match = ntry.getKey().toString();
if (work.startsWith(match))
{ // found the right smiley
looking = false;
output.append("<ei:").append(ntry.getValue()).append("/>");
work = work.substring(match.length());
did_replace = true;
} // end if
} // end for
} // end if
if (looking)
{ // no such luck - shift the triggering character over
output.append(work.charAt(0));
work = work.substring(1);
} // end if
// now look for the next triggering character
pos = Integer.MAX_VALUE;
for (int i=0; i<m_prefixchars.length; i++)
{ // hunt for the possible beginning of an emoticon sequence
int foo = work.indexOf(m_prefixchars[i]);
if (foo>=0)
pos = Math.min(pos,foo);
} // end for
} while (pos!=Integer.MAX_VALUE); // end do
if (!did_replace)
return null; // no replacements done, so what's the point?
output.append(work); // tack this onto the end
return new MarkupData(null,output.toString(),null,true);
} // end rewrite

View File

@ -0,0 +1,105 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Community System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@ricochet.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.venice.htmlcheck.filters;
import java.util.*;
import org.apache.log4j.*;
import org.apache.regexp.*;
import org.w3c.dom.*;
import com.silverwrist.venice.except.*;
import com.silverwrist.venice.htmlcheck.Rewriter;
import com.silverwrist.venice.htmlcheck.RewriterServices;
import com.silverwrist.venice.htmlcheck.MarkupData;
import com.silverwrist.venice.util.XMLLoader;
public class EmoticonTagHandler implements Rewriter
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Logger logger = Logger.getLogger(EmoticonTagHandler.class);
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private Set m_valid_icons;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public EmoticonTagHandler(Element root) throws ConfigException
{
XMLLoader loader = XMLLoader.get();
HashSet tmp = new HashSet();
// Look for all associated icons.
NodeList nl = root.getChildNodes();
for (int i=0; i<nl.getLength(); i++)
{ // look through all the child nodes...
Node n = nl.item(i);
if ((n.getNodeType()==Node.ELEMENT_NODE) && n.getNodeName().equals("icon"))
{ // load the icon name
String icon_name = loader.configGetAttribute((Element)n,"name").intern();
tmp.add(icon_name);
} // end if
// else skip this element
} // end for
if (tmp.isEmpty())
m_valid_icons = Collections.EMPTY_SET;
else
m_valid_icons = Collections.unmodifiableSet(tmp);
if (logger.isDebugEnabled())
logger.debug("EmoticonTagHandler recognizes " + m_valid_icons.size() + " valid tag names");
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface Rewriter
*--------------------------------------------------------------------------------
*/
public String getName()
{
return "emoticon_tag";
} // end getName
public MarkupData rewrite(String data, RewriterServices svc)
{
logger.debug("EmoticonTagHandler looking at: " + data);
RE r = new RE("ei:\\s*(\\w+)(?:\\s*/)?\\s*");
if (!(r.match(data)))
return null;
String icon_name = r.getParen(1);
logger.debug("EmoticonTagHandler match icon name: " + icon_name);
if (!(m_valid_icons.contains(icon_name)))
return null;
return new MarkupData("<ei:" + icon_name + "/>",null,null);
} // end rewrite
} // end class EmoticonTagHandler

View File

@ -9,9 +9,9 @@
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@ricochet.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
* Copyright (C) 2001-2004 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
@ -23,6 +23,7 @@ import javax.servlet.jsp.tagext.*;
import com.silverwrist.venice.db.PostLinkRewriter;
import com.silverwrist.venice.db.UserNameRewriter;
import com.silverwrist.venice.ui.*;
import com.silverwrist.venice.ui.config.EmoticonManager;
import com.silverwrist.venice.ui.helpers.HTMLRendering;
import com.silverwrist.venice.util.IDUtils;
@ -59,6 +60,10 @@ public class PostRewriteTag extends VeniceConfBodyTagSupport
BodyContent body = getBodyContent();
String data = body.getString();
// Remap emoticons.
EmoticonManager em = (EmoticonManager)(getRequestInput().queryService(EmoticonManager.class));
data = em.rewriteText(getRequestOutput(),data);
if ((data.indexOf(PostLinkRewriter.URI_PREFIX)<0) && (data.indexOf(UserNameRewriter.URI_PREFIX)<0))
{ // no post links or user links in here - output what we've got and call it
output(body,data);

View File

@ -18,9 +18,13 @@
package com.silverwrist.venice.ui.config;
import java.util.*;
import org.apache.log4j.*;
import org.apache.regexp.*;
import org.w3c.dom.*;
import com.silverwrist.util.*;
import com.silverwrist.venice.except.*;
import com.silverwrist.venice.ui.*;
import com.silverwrist.venice.ui.helpers.*;
import com.silverwrist.venice.util.XMLLoader;
public class EmoticonManager
@ -63,11 +67,43 @@ public class EmoticonManager
// Get the text data.
m_text = h.getSubElementText("text");
if (m_text==null)
m_text = "";
} // end constructor
/*====================================================================
* External operations
*====================================================================
*/
String format(RequestOutput out)
{
StringBuffer buf = new StringBuffer("<img src=\"");
if (m_fixup)
{ // fix it up
HTMLRendering html = (HTMLRendering)(out.queryService(HTMLRendering.class));
m_path = html.getImagePath(m_path);
m_fixup = false;
} // end if
buf.append(m_path).append("\" width=\"").append(m_width).append("\" height=\"").append(m_height);
buf.append("\" border=\"0\" alt=\"").append(m_text).append("\" title=\"").append(m_text);
buf.append("\" />");
return buf.toString();
} // end format
} // end class IconDefinition
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Logger logger = Logger.getLogger(EmoticonManager.class);
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
@ -106,4 +142,44 @@ public class EmoticonManager
} // end constructor
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
public String rewriteText(RequestOutput out, String txt)
{
RE r = new RE("<ei:\\s*(\\w+)(?:\\s*/)?\\s*>");
if (!(r.match(txt)))
{ // null it out
logger.debug("EmoticonManager.rewriteText matched nothing at all");
return txt;
} // end if
StringBuffer buf = new StringBuffer();
String work = txt;
do
{ // figure out how many characters to skip
int skip = r.getParenStart(0);
if (skip>0)
buf.append(work.substring(0,skip));
skip += r.getParenLength(0);
// get the icon name
String icon_name = r.getParen(1);
IconDefinition defn = (IconDefinition)(m_iconmap.get(icon_name));
if (defn==null)
buf.append(StringUtil.encodeHTML(r.getParen(0)));
else
buf.append(defn.format(out));
work = work.substring(skip); // skip over stuff
} while (r.match(work)); // end do
return buf.append(work).toString(); // all done!
} // end rewriteText
} // end class EmoticonManager

View File

@ -425,6 +425,12 @@ public abstract class BaseServlet extends HttpServlet
init(config,ctxt,engine,rootconf,root_file_path);
} // end try
catch (RuntimeException e)
{ // report an error
logger.fatal("RuntimeException in configuration: " + e.getMessage(),e);
throw new ServletException("Venice configuration failed: " + e.getMessage(),e);
} // end catch
finally
{ // make sure and pop the diagnostic context before we go
NDC.pop();

View File

@ -81,6 +81,8 @@ public class RequestImpl implements RequestInput
return RequestImpl.this.queryService(klass);
if (klass==BrowserInformation.class)
return RequestImpl.this.queryService(klass);
if (klass==EmoticonManager.class)
return RequestImpl.this.queryService(klass);
throw new NoSuchServiceException("RequestOutput",klass);
} // end queryService
@ -899,8 +901,8 @@ public class RequestImpl implements RequestInput
*
* @param klass The class of the object that should be returned as a service.
* @return A service object. The service object is guaranteed to be of the class
* specified by <CODE>klass</CODE>; that is, if <CODE>queryService(klass)</CODE>
* yields some object <CODE>x</CODE>, then the expression <CODE>klass.isInstance(x)</CODE>
* specified by <code>klass</code>; that is, if <code>queryService(klass)</code>
* yields some object <code>x</code>, then the expression <CODE>klass.isInstance(x)</code>
* is true.
* @exception com.silverwrist.venice.except.NoSuchServiceException If no service is available in
* the specified class.
@ -958,6 +960,9 @@ public class RequestImpl implements RequestInput
} // end if
if (klass==EmoticonManager.class)
return config.getEmoticonManager();
throw new NoSuchServiceException("RequestInput",klass);
} // end queryService