diff --git a/apps/webchat/source/java/org/jivesoftware/webchat/EmoticonFilter.java b/apps/webchat/source/java/org/jivesoftware/webchat/EmoticonFilter.java new file mode 100644 index 000000000..293edf0ff --- /dev/null +++ b/apps/webchat/source/java/org/jivesoftware/webchat/EmoticonFilter.java @@ -0,0 +1,292 @@ +/** + * $RCSfile$ + * $Revision$ + * $Date$ + * + * Copyright (C) 2003 Jive Software. All rights reserved. + * + * This software is the proprietary information of Jive Software. Use is subject to license terms. + */ + +package org.jivesoftware.webchat; + +/** + * A Filter that converts ASCII emoticons into image equivalents. + * This filter should only be run after any HTML stripping filters.
+ * + * The filter must be configured with information about where the image files + * are located. A table containing all the supported emoticons with their + * ASCII representations and image file names is as follows:
+ * + *
Emotion | ASCII | Image |
Happy | :) or :-) | happy.gif |
Sad | :( or :-( | sad.gif |
Grin | :D | grin.gif |
Love | :x | love.gif |
Mischief | ;\ | mischief.gif |
Cool | B-) | cool.gif |
Devil | ]:) | devil.gif |
Silly | :p | silly.gif |
Angry | X-( | angry.gif |
Laugh | :^O | laugh.gif |
Wink | ;) or ;-) | wink.gif |
Blush | :8} | blush.gif |
Cry | :_| | cry.gif |
Confused | ?:| | confused.gif |
Shocked | :O | shocked.gif |
Plain | :| | plain.gif |
+ *
+ * The default set of patterns recognized are ftp://path-of-url
,
+ * http://path-of-url
, https://path-of-url
but can be expanded upon.
+ *
+ * In addition, the following patterns are also recognized.
+ *
+ * [url path-of-url]descriptive text[/url]
and
+ * [url=path-of-url]descriptive text[/url]
.
+ *
+ * The [url]
allows any path to be defined as link.
+ */
+public class URLFilter{
+
+ private ArrayList schemes = new ArrayList();
+
+ // define a preset default set of schemes
+ public URLFilter() {
+ schemes.add("http://");
+ schemes.add("https://");
+ schemes.add("ftp://");
+ }
+
+ public String applyFilter(String string) {
+ if (string == null || string.length() == 0) {
+ return string;
+ }
+
+ int length = string.length();
+ StringBuffer filtered = new StringBuffer((int) (length * 1.5));
+ ArrayList urlBlocks = new ArrayList(5);
+
+ // search for url's such as [url=..]text[/url] or [url ..]text[/url]
+ int start = string.indexOf("[url");
+ while (start != -1 && (start + 5 < length)) {
+ // check to verify we're not in another block
+ if (withinAnotherBlock(urlBlocks, start)) {
+ start = string.indexOf("[url", start + 5);
+ continue;
+ }
+
+ int end = string.indexOf("[/url]", start + 5);
+
+ if (end == -1 || end >= length) {
+ // went past end of string, skip
+ break;
+ }
+
+ String u = string.substring(start, end + 6);
+ int startTagClose = u.indexOf(']');
+ String url;
+ String description;
+ if (startTagClose > 5) {
+ url = u.substring(5, startTagClose);
+ description = u.substring(startTagClose + 1, u.length() - 6);
+
+ // Check the user entered URL for a "javascript:" or "file:" link. Only
+ // append the user entered link if it doesn't contain 'javascript:' and 'file:'
+ String lcURL = url.toLowerCase();
+ if (lcURL.indexOf("javascript:") == -1 && lcURL.indexOf("file:") == -1) {
+ URLBlock block = new URLBlock(start, end + 5, url, description);
+ urlBlocks.add(block);
+ }
+ }
+ else {
+ url = description = u.substring(startTagClose + 1, u.length() - 6);
+ // Check the user entered URL for a "javascript:" or "file:" link. Only
+ // append the user entered link if it doesn't contain 'javascript:' and 'file:'
+ String lcURL = url.toLowerCase();
+ if (lcURL.indexOf("javascript:") == -1 && lcURL.indexOf("file:") == -1) {
+ URLBlock block = new URLBlock(start, end + 5, url);
+ urlBlocks.add(block);
+ }
+ }
+
+ start = string.indexOf("[url", end + 6);
+ }
+
+ // now handle all the other urls
+ Iterator iter = schemes.iterator();
+
+ while (iter.hasNext()) {
+ String scheme = (String) iter.next();
+ start = string.indexOf(scheme, 0);
+
+ while (start != -1) {
+ int end = start;
+
+ // check context, don't handle patterns preceded by any of '"<=
+ if (start > 0) {
+ char c = string.charAt(start - 1);
+
+ if (c == '\'' || c == '"' || c == '<' || c == '=') {
+ start = string.indexOf(scheme, start + scheme.length());
+ continue;
+ }
+ }
+
+ // check to verify we're not in another block
+ if (withinAnotherBlock(urlBlocks, start)) {
+ start = string.indexOf(scheme, start + scheme.length());
+ continue;
+ }
+
+ // find the end of the url
+ int cur = start + scheme.length();
+ while (end == start && cur < length) {
+ char c = string.charAt(cur);
+
+ switch (c) {
+ case ' ':
+ end = cur;
+ break;
+ case '\t':
+ end = cur;
+ break;
+ case '\'':
+ end = cur;
+ break;
+ case '\"':
+ end = cur;
+ break;
+ case '<':
+ end = cur;
+ break;
+ case '[':
+ end = cur;
+ break;
+ case '\n':
+ end = cur;
+ break;
+ case '\r':
+ end = cur;
+ break;
+ default:
+ // acceptable character
+ }
+
+ cur++;
+ }
+
+ // if this is true it means the url goes to the end of the string
+ if (end == start) {
+ end = length - 1;
+ }
+
+ URLBlock block = new URLBlock(start, end-1, string.substring(start, end));
+ urlBlocks.add(block);
+
+ start = string.indexOf(scheme, end);
+ }
+ }
+
+ // sort the blocks so that they are in start index order
+ sortBlocks(urlBlocks);
+
+ // now, markup the urls and pass along the filter chain the rest
+ Iterator blocks = urlBlocks.iterator();
+ int last = 0;
+
+ while (blocks.hasNext()) {
+ URLBlock block = (URLBlock) blocks.next();
+
+ if (block.getStart() > 0) {
+ filtered.append(string.substring(last, block.getStart()));
+ }
+
+ last = block.getEnd() + 1;
+
+ filtered.append("");
+ if (block.getDescription().length() > 0) {
+ filtered.append(block.getDescription());
+ }
+ else {
+ filtered.append(block.getUrl());
+ }
+ filtered.append("");
+ }
+
+ if (last < string.length() - 1) {
+ filtered.append(string.substring(last));
+ }
+
+ return filtered.toString();
+ }
+
+ /**
+ * Returns the current supported uri schemes as a comma seperated string.
+ *
+ * @return the current supported uri schemes as a comma seperated string.
+ */
+ public String getSchemes() {
+ StringBuffer buf = new StringBuffer(50);
+
+ for (int i = 0; i < schemes.size(); i++) {
+ buf.append((String) schemes.get(i)).append(",");
+ }
+ buf.deleteCharAt(buf.length() - 1);
+
+ return buf.toString();
+ }
+
+ /**
+ * Sets the current supported uri schemes as a comma seperated string.
+ *
+ * @param schemes a comma seperated string of uri schemes.
+ */
+ public void setSchemes(String schemes) {
+ if (schemes == null) {
+ return;
+ }
+
+ // enpty the current list
+ this.schemes.clear();
+
+ StringTokenizer st = new StringTokenizer(schemes, ",");
+
+ while (st.hasMoreElements()) {
+ this.schemes.add(st.nextElement());
+ }
+ }
+
+ private void sortBlocks(ArrayList blocks) {
+ Collections.sort(blocks, new Comparator() {
+ public int compare(Object object1, Object object2) {
+ URLBlock b1 = (URLBlock) object1;
+ URLBlock b2 = (URLBlock) object2;
+ return (b1.getStart() > b2.getStart()) ? 1 : -1;
+ }
+ });
+ }
+
+ private boolean withinAnotherBlock(List blocks, int start) {
+ for (int i = 0; i < blocks.size(); i++) {
+ URLBlock block = (URLBlock) blocks.get(i);
+
+ if (start >= block.getStart() && start < block.getEnd()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ class URLBlock {
+ int start = 0;
+ int end = 0;
+ String description = "";
+ String url = "";
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ URLBlock(int start, int end, String url) {
+ this.start = start;
+ this.end = end;
+ this.url = url;
+ }
+
+ URLBlock(int start, int end, String url, String description) {
+ this.start = start;
+ this.end = end;
+ this.description = description;
+ this.url = url;
+ }
+
+ public int getStart() {
+ return start;
+ }
+
+ public void setStart(int start) {
+ this.start = start;
+ }
+
+ public int getEnd() {
+ return end;
+ }
+
+ public void setEnd(int end) {
+ this.end = end;
+ }
+ }
+}
\ No newline at end of file
diff --git a/apps/webchat/source/web/images/emoticons/angry.gif b/apps/webchat/source/web/images/emoticons/angry.gif
new file mode 100644
index 000000000..6489c9bc9
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/angry.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/blush.gif b/apps/webchat/source/web/images/emoticons/blush.gif
new file mode 100644
index 000000000..22f1db550
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/blush.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/confused.gif b/apps/webchat/source/web/images/emoticons/confused.gif
new file mode 100644
index 000000000..ef1107bec
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/confused.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/cool.gif b/apps/webchat/source/web/images/emoticons/cool.gif
new file mode 100644
index 000000000..2d805e5da
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/cool.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/cry.gif b/apps/webchat/source/web/images/emoticons/cry.gif
new file mode 100644
index 000000000..e244944c8
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/cry.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/devil.gif b/apps/webchat/source/web/images/emoticons/devil.gif
new file mode 100644
index 000000000..31bca49fb
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/devil.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/grin.gif b/apps/webchat/source/web/images/emoticons/grin.gif
new file mode 100644
index 000000000..e5c92e2d5
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/grin.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/happy.gif b/apps/webchat/source/web/images/emoticons/happy.gif
new file mode 100644
index 000000000..20a93e32b
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/happy.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/laugh.gif b/apps/webchat/source/web/images/emoticons/laugh.gif
new file mode 100644
index 000000000..e808a2583
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/laugh.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/love.gif b/apps/webchat/source/web/images/emoticons/love.gif
new file mode 100644
index 000000000..d1c320e3d
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/love.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/mischief.gif b/apps/webchat/source/web/images/emoticons/mischief.gif
new file mode 100644
index 000000000..238db06f3
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/mischief.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/plain.gif b/apps/webchat/source/web/images/emoticons/plain.gif
new file mode 100644
index 000000000..a5beeea43
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/plain.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/sad.gif b/apps/webchat/source/web/images/emoticons/sad.gif
new file mode 100644
index 000000000..0320885df
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/sad.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/shocked.gif b/apps/webchat/source/web/images/emoticons/shocked.gif
new file mode 100644
index 000000000..20a70f8cd
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/shocked.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/silly.gif b/apps/webchat/source/web/images/emoticons/silly.gif
new file mode 100644
index 000000000..a162605bd
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/silly.gif differ
diff --git a/apps/webchat/source/web/images/emoticons/wink.gif b/apps/webchat/source/web/images/emoticons/wink.gif
new file mode 100644
index 000000000..6d91b0fa2
Binary files /dev/null and b/apps/webchat/source/web/images/emoticons/wink.gif differ