smack_1_5_1
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@2639 b35dd754-fafc-0310-a699-88a17e54d16e
167
CopyOftrunk/apps/webchat/source/config/WEB-INF/web.xml
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
|
||||
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
|
||||
"http://java.sun.com/dtd/web-app_2_3.dtd">
|
||||
|
||||
<web-app>
|
||||
|
||||
<display-name>WebChat</display-name>
|
||||
<description>Smack-powered WebChat Application</description>
|
||||
|
||||
<context-param>
|
||||
<param-name>host</param-name>
|
||||
<param-value>jivesoftware.com</param-value>
|
||||
</context-param>
|
||||
|
||||
<!--
|
||||
*******************
|
||||
ALL OF THE FOLLOWING context-params are optional, and are listed with their
|
||||
default values. Since they are optional, they needn't be included in this
|
||||
file if you're satisfied with the default values; they're listed here
|
||||
for informational purposes.
|
||||
*******************
|
||||
-->
|
||||
|
||||
<!-- allow users to logon anonymously? -->
|
||||
<context-param>
|
||||
<param-name>allowAnonymous</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- allow users to create new accounts? -->
|
||||
<context-param>
|
||||
<param-name>allowAccountCreation</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- allow users to login using their username/password? -->
|
||||
<context-param>
|
||||
<param-name>allowLogin</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the url for the logo image in the chat window (path relative to the .jsp files) -->
|
||||
<context-param>
|
||||
<param-name>logoFilename</param-name>
|
||||
<param-value>images/logo.gif</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the text for chat window room announcements -->
|
||||
<context-param>
|
||||
<param-name>chat.announcement-color</param-name>
|
||||
<param-value>#009d00</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the text for the dialog label associated with the user of the web client -->
|
||||
<context-param>
|
||||
<param-name>chat.owner-label-color</param-name>
|
||||
<param-value>#aa0000</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the text for the dialog label associated with other chat participants -->
|
||||
<context-param>
|
||||
<param-name>chat.participant-label-color</param-name>
|
||||
<param-value>#0000aa</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the text for the dialog in the chat window -->
|
||||
<context-param>
|
||||
<param-name>chat.text-color</param-name>
|
||||
<param-value>#434343</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of error message text -->
|
||||
<context-param>
|
||||
<param-name>error.text-color</param-name>
|
||||
<param-value>#ff0000</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the text for unvisited links -->
|
||||
<context-param>
|
||||
<param-name>link.color</param-name>
|
||||
<param-value>#045d30</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the text for links with the pointer hovering over them -->
|
||||
<context-param>
|
||||
<param-name>link.hover-color</param-name>
|
||||
<param-value>#350000</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the text for already visited links -->
|
||||
<context-param>
|
||||
<param-name>link.visited-color</param-name>
|
||||
<param-value>#3b3757</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the background of all pages -->
|
||||
<context-param>
|
||||
<param-name>body.background-color</param-name>
|
||||
<param-value>#ffffff</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the default color of the text on all pages -->
|
||||
<context-param>
|
||||
<param-name>body.text-color</param-name>
|
||||
<param-value>#362f2d</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the chat window divider between the participant listing and the chat -->
|
||||
<context-param>
|
||||
<param-name>frame.divider-color</param-name>
|
||||
<param-value>#83272b</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the form element buttons -->
|
||||
<context-param>
|
||||
<param-name>button.color</param-name>
|
||||
<param-value>#d6dfdf</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the text in the form element buttons -->
|
||||
<context-param>
|
||||
<param-name>button.text-color</param-name>
|
||||
<param-value>#333333</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the background in the form element text fields -->
|
||||
<context-param>
|
||||
<param-name>textfield.color</param-name>
|
||||
<param-value>#f7f7fb</param-value>
|
||||
</context-param>
|
||||
|
||||
<!-- the color of the text in the form element text fields and textareas -->
|
||||
<context-param>
|
||||
<param-name>textfield.text-color</param-name>
|
||||
<param-value>#333333</param-value>
|
||||
</context-param>
|
||||
|
||||
|
||||
<!-- Session listener -->
|
||||
<listener>
|
||||
<listener-class>org.jivesoftware.webchat.JiveChatServlet</listener-class>
|
||||
</listener>
|
||||
|
||||
<!-- Servlets -->
|
||||
<servlet>
|
||||
<servlet-name>ChatServlet</servlet-name>
|
||||
<servlet-class>org.jivesoftware.webchat.JiveChatServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!-- Servlet mappings -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>ChatServlet</servlet-name>
|
||||
<url-pattern>/ChatServlet/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<session-config>
|
||||
<session-timeout>3</session-timeout>
|
||||
</session-config>
|
||||
|
||||
<!-- Welcome file list -->
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
</web-app>
|
||||
|
|
@ -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.<p>
|
||||
*
|
||||
* 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:<p>
|
||||
*
|
||||
* <table border=1>
|
||||
* <tr><td><b>Emotion</b></td><td><b>ASCII</b></td><td><b>Image</b></td></tr>
|
||||
*
|
||||
* <tr><td>Happy</td><td>:) or :-)</td><td>happy.gif</td></tr>
|
||||
* <tr><td>Sad</td><td>:( or :-(</td><td>sad.gif</td></tr>
|
||||
* <tr><td>Grin</td><td>:D</td><td>grin.gif</td></tr>
|
||||
* <tr><td>Love</td><td>:x</td><td>love.gif</td></tr>
|
||||
* <tr><td>Mischief</td><td>;\</td><td>mischief.gif</td></tr>
|
||||
* <tr><td>Cool</td><td>B-)</td><td>cool.gif</td></tr>
|
||||
* <tr><td>Devil</td><td>]:)</td><td>devil.gif</td></tr>
|
||||
* <tr><td>Silly</td><td>:p</td><td>silly.gif</td></tr>
|
||||
* <tr><td>Angry</td><td>X-(</td><td>angry.gif</td></tr>
|
||||
* <tr><td>Laugh</td><td>:^O</td><td>laugh.gif</td></tr>
|
||||
* <tr><td>Wink</td><td>;) or ;-)</td><td>wink.gif</td></tr>
|
||||
* <tr><td>Blush</td><td>:8}</td><td>blush.gif</td></tr>
|
||||
* <tr><td>Cry</td><td>:_|</td><td>cry.gif</td></tr>
|
||||
* <tr><td>Confused</td><td>?:|</td><td>confused.gif</td></tr>
|
||||
* <tr><td>Shocked</td><td>:O</td><td>shocked.gif</td></tr>
|
||||
* <tr><td>Plain</td><td>:|</td><td>plain.gif</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* Note: special thanks to August Harrison for implementing an earlier version of this filter.
|
||||
*/
|
||||
public class EmoticonFilter {
|
||||
|
||||
private static String imageHappy = "happy.gif";
|
||||
private static String imageSad = "sad.gif";
|
||||
private static String imageGrin = "grin.gif";
|
||||
private static String imageLove = "love.gif";
|
||||
private static String imageMischief = "mischief.gif";
|
||||
private static String imageCool = "cool.gif";
|
||||
private static String imageDevil = "devil.gif";
|
||||
private static String imageSilly = "silly.gif";
|
||||
private static String imageAngry = "angry.gif";
|
||||
private static String imageLaugh = "laugh.gif";
|
||||
private static String imageWink = "wink.gif";
|
||||
private static String imageBlush = "blush.gif";
|
||||
private static String imageCry = "cry.gif";
|
||||
private static String imageConfused = "confused.gif";
|
||||
private static String imageShocked = "shocked.gif";
|
||||
private static String imagePlain = "plain.gif";
|
||||
private static String imageURL = "images/emoticons";
|
||||
|
||||
// Placeholders for the built image tags
|
||||
private static String imgHappy;
|
||||
private static String imgSad;
|
||||
private static String imgGrin;
|
||||
private static String imgLove;
|
||||
private static String imgMischief;
|
||||
private static String imgCool;
|
||||
private static String imgDevil;
|
||||
private static String imgSilly;
|
||||
private static String imgAngry;
|
||||
private static String imgLaugh;
|
||||
private static String imgWink;
|
||||
private static String imgBlush;
|
||||
private static String imgCry;
|
||||
private static String imgConfused;
|
||||
private static String imgShocked;
|
||||
private static String imgPlain;
|
||||
|
||||
public EmoticonFilter() {
|
||||
buildImageTags();
|
||||
}
|
||||
|
||||
public String applyFilter(String string) {
|
||||
if (string == null || string.length() < 1) {
|
||||
return string;
|
||||
}
|
||||
|
||||
int length = string.length();
|
||||
StringBuffer filtered = new StringBuffer(string.length() + 100);
|
||||
char[] chars = string.toCharArray();
|
||||
|
||||
int length1 = length - 1;
|
||||
int length2 = length - 2;
|
||||
|
||||
int index = -1, i = 0, oldend = 0;
|
||||
String imgTag;
|
||||
|
||||
// Replace each of the emoticons, expanded search for performance
|
||||
while (++index < length1) {
|
||||
// no tag found yet...
|
||||
imgTag = null;
|
||||
|
||||
switch (chars[i = index]) {
|
||||
case ']':
|
||||
// "]:)"
|
||||
if (i < length2 && chars[++i] == ':' && chars[++i] == ')') {
|
||||
imgTag = imgDevil;
|
||||
}
|
||||
break;
|
||||
case ':':
|
||||
switch (chars[++i]) {
|
||||
case ')':
|
||||
// ":)"
|
||||
imgTag = imgHappy;
|
||||
break;
|
||||
case '-':
|
||||
// ":-)"
|
||||
if (i < length1 && chars[++i] == ')') {
|
||||
imgTag = imgHappy;
|
||||
}
|
||||
// ":-("
|
||||
else if (chars[i] == '(') {
|
||||
imgTag = imgSad;
|
||||
}
|
||||
break;
|
||||
case '(':
|
||||
// ":("
|
||||
imgTag = imgSad;
|
||||
break;
|
||||
case 'D':
|
||||
// ":D"
|
||||
imgTag = imgGrin;
|
||||
break;
|
||||
case 'x':
|
||||
// ":x"
|
||||
imgTag = imgLove;
|
||||
break;
|
||||
case 'p':
|
||||
// ":p"
|
||||
imgTag = imgSilly;
|
||||
break;
|
||||
case '^':
|
||||
// ":^O"
|
||||
if (i < length1 && chars[++i] == 'O') {
|
||||
imgTag = imgLaugh;
|
||||
}
|
||||
break;
|
||||
case '8':
|
||||
// ":8}"
|
||||
if (i < length1 && chars[++i] == '}') {
|
||||
imgTag = imgBlush;
|
||||
}
|
||||
break;
|
||||
case '_':
|
||||
// ":_|"
|
||||
if (i < length1 && chars[++i] == '|') {
|
||||
imgTag = imgCry;
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
// ":O"
|
||||
imgTag = imgShocked;
|
||||
break;
|
||||
case '|':
|
||||
// ":|"
|
||||
imgTag = imgPlain;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ';':
|
||||
switch (chars[++i]) {
|
||||
case ')':
|
||||
// ";)"
|
||||
imgTag = imgWink;
|
||||
break;
|
||||
case '-':
|
||||
// ";-)"
|
||||
if (i < length1 && chars[++i] == ')') {
|
||||
imgTag = imgWink;
|
||||
}
|
||||
break;
|
||||
case '\\':
|
||||
// ";\\"
|
||||
imgTag = imgMischief;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'B':
|
||||
// "B-)"
|
||||
if (i < length2 && chars[++i] == '-' && chars[++i] == ')') {
|
||||
imgTag = imgCool;
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
// "X-("
|
||||
if (i < length2 && chars[++i] == '-' && chars[++i] == '(') {
|
||||
imgTag = imgAngry;
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
// "?:|"
|
||||
if (i < length2 && chars[++i] == ':' && chars[++i] == '|') {
|
||||
imgTag = imgConfused;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// if we found one, replace
|
||||
if (imgTag != null) {
|
||||
filtered.append(chars, oldend, index-oldend);
|
||||
filtered.append(imgTag);
|
||||
|
||||
oldend = i + 1;
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (oldend < length) {
|
||||
filtered.append(chars, oldend, length-oldend);
|
||||
}
|
||||
|
||||
return filtered.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base URL for emoticon images. This can be specified as
|
||||
* an absolute or relative path.
|
||||
*
|
||||
* @return the base URL for smiley images.
|
||||
*/
|
||||
public String getImageURL() {
|
||||
return imageURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the base URL for emoticon images. This can be specified as
|
||||
* an absolute or relative path.
|
||||
*
|
||||
* @param imageURL the base URL for emoticon images.
|
||||
*/
|
||||
public void setImageURL(String imageURL) {
|
||||
if (imageURL != null && imageURL.length() > 0) {
|
||||
if (imageURL.charAt(imageURL.length()-1) == '/') {
|
||||
imageURL = imageURL.substring(0, imageURL.length()-1);
|
||||
}
|
||||
}
|
||||
this.imageURL = imageURL;
|
||||
|
||||
// rebuild the image tags
|
||||
buildImageTags();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build image tags
|
||||
*/
|
||||
private void buildImageTags() {
|
||||
imgHappy = buildURL(imageHappy);
|
||||
imgSad = buildURL(imageSad);
|
||||
imgGrin = buildURL(imageGrin);
|
||||
imgLove = buildURL(imageLove);
|
||||
imgMischief = buildURL(imageMischief);
|
||||
imgCool = buildURL(imageCool);
|
||||
imgDevil = buildURL(imageDevil);
|
||||
imgSilly = buildURL(imageSilly);
|
||||
imgAngry = buildURL(imageAngry);
|
||||
imgLaugh = buildURL(imageLaugh);
|
||||
imgWink = buildURL(imageWink);
|
||||
imgBlush = buildURL(imageBlush);
|
||||
imgCry = buildURL(imageCry);
|
||||
imgConfused = buildURL(imageConfused);
|
||||
imgShocked = buildURL(imageShocked);
|
||||
imgPlain = buildURL(imagePlain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an HTML image tag using the base image URL and image name.
|
||||
*/
|
||||
private String buildURL(String imageName) {
|
||||
String tag = "<img border='0' src='" + imageURL + "/" + imageName + "'>";
|
||||
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,729 @@
|
|||
/**
|
||||
* $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;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
|
||||
import org.jivesoftware.smack.*;
|
||||
import org.jivesoftware.smack.filter.*;
|
||||
import org.jivesoftware.smack.packet.*;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* An extension of HttpServlet customized to handle transactions between N webclients
|
||||
* and M chats located on a given XMPP server. While N >= M in the case of group chats,
|
||||
* the code will currently, never the less, hold onto N connections to the XMPP server.<br>
|
||||
*
|
||||
* It is assumed that all JSP pages are in the context root. The init params should be:
|
||||
* <ul>
|
||||
* <li> host</li>
|
||||
* <li> port (optional)</li>
|
||||
* <li> SSLEnabled (optional)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Bill Lynch
|
||||
* @author loki der quaeler
|
||||
*/
|
||||
public class JiveChatServlet
|
||||
extends HttpServlet
|
||||
implements HttpSessionListener, PacketListener {
|
||||
|
||||
static public final String JIVE_WEB_CHAT_RESOURCE_NAME = "WebChat";
|
||||
|
||||
static protected long PACKET_RESPONSE_TIMEOUT_MS = 5000;
|
||||
|
||||
static protected String CHAT_LAUNCHER_URI_SUFFIX = "/chat-launcher.jsp";
|
||||
static protected String CREATE_ACCOUNT_URI = "/account_creation.jsp";
|
||||
static protected String LOGIN_URI = "/index.jsp";
|
||||
|
||||
static protected String ERRORS_ATTRIBUTE_STRING = "messenger.servlet.errors";
|
||||
static protected String NICKNAME_ATTRIBUTE_STRING = "messenger.servlet.nickname";
|
||||
static protected String ROOM_ATTRIBUTE_STRING = "messenger.servlet.room";
|
||||
|
||||
static protected String HOST_PARAM_STRING = "host";
|
||||
static protected String PORT_PARAM_STRING = "port";
|
||||
static protected String SSL_PARAM_STRING = "SSLEnabled";
|
||||
|
||||
static protected String COMMAND_PARAM_STRING = "command";
|
||||
static protected String NICKNAME_PARAM_STRING = "nickname";
|
||||
static protected String PASSWORD_PARAM_STRING = "password";
|
||||
static protected String RETYPED_PASSWORD_PARAM_STRING = "password_zwei";
|
||||
static protected String ROOM_PARAM_STRING = "room";
|
||||
static protected String USERNAME_PARAM_STRING = "username";
|
||||
|
||||
static protected String ANON_LOGIN_COMMAND_STRING = "anon_login";
|
||||
static protected String CREATE_ACCOUNT_COMMAND_STRING = "create_account";
|
||||
static protected String LOGIN_COMMAND_STRING = "login";
|
||||
static protected String LOGOUT_COMMAND_STRING = "logout";
|
||||
static protected String READ_COMMAND_STRING = "read";
|
||||
static protected String SILENCE_COMMAND_STRING = "silence";
|
||||
static protected String WRITE_COMMAND_STRING = "write";
|
||||
|
||||
static protected String MESSAGE_REQUEST_STRING = "message";
|
||||
|
||||
// is this value used elsewhere? (if not, why a string?) PENDING
|
||||
static protected String ERROR_RETURN_CODE_STRING = "error";
|
||||
static protected String SUCCESS_RETURN_CODE_STRING = "success";
|
||||
|
||||
// k/v :: S(session id) / ChatData
|
||||
static protected Map SESSION_CHATDATA_MAP = new HashMap();
|
||||
// k/v :: S(unique root of packet ids) / ChatData
|
||||
static protected Map PACKET_ROOT_CHATDATA_MAP = new HashMap();
|
||||
|
||||
static protected EmoticonFilter EMOTICONFILTER = new EmoticonFilter();
|
||||
static protected URLTranscoder URLTRANSCODER = new URLTranscoder();
|
||||
|
||||
|
||||
protected String host;
|
||||
protected int port;
|
||||
protected boolean sslEnabled;
|
||||
|
||||
public void init (ServletConfig config)
|
||||
throws ServletException {
|
||||
ServletContext context = null;
|
||||
String portParameter = null;
|
||||
|
||||
super.init(config);
|
||||
|
||||
// XMPPConnection.DEBUG_ENABLED = true;
|
||||
|
||||
context = config.getServletContext();
|
||||
|
||||
this.host = context.getInitParameter(HOST_PARAM_STRING);
|
||||
if (this.host == null) {
|
||||
throw new ServletException("Init parameter \"" + HOST_PARAM_STRING + "\" must be set.");
|
||||
}
|
||||
|
||||
this.port = -1;
|
||||
|
||||
portParameter = context.getInitParameter(PORT_PARAM_STRING);
|
||||
if (portParameter != null) {
|
||||
try {
|
||||
this.port = Integer.parseInt(portParameter);
|
||||
} catch (NumberFormatException nfe) {
|
||||
throw new ServletException("Init parameter \"" + PORT_PARAM_STRING
|
||||
+ "\" must be a valid number.", nfe);
|
||||
}
|
||||
}
|
||||
|
||||
this.sslEnabled
|
||||
= Boolean.valueOf(context.getInitParameter(SSL_PARAM_STRING)).booleanValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Take care of closing down everything we're holding on to, then bubble up the destroy
|
||||
* to our superclass.
|
||||
*/
|
||||
public void destroy () {
|
||||
synchronized (SESSION_CHATDATA_MAP) {
|
||||
for (Iterator i = SESSION_CHATDATA_MAP.values().iterator(); i.hasNext(); ) {
|
||||
ChatData chatData = (ChatData)i.next();
|
||||
|
||||
if (chatData.groupChat != null) {
|
||||
chatData.groupChat.leave();
|
||||
}
|
||||
|
||||
chatData.connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
protected void service (HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
HttpSession session = request.getSession();
|
||||
String sessionID = session.getId();
|
||||
String path = request.getContextPath();
|
||||
String command = request.getParameter(COMMAND_PARAM_STRING);
|
||||
|
||||
if (READ_COMMAND_STRING.equals(command)) {
|
||||
ChatData chatData = (ChatData)SESSION_CHATDATA_MAP.get(sessionID);
|
||||
StringBuffer reply = null;
|
||||
boolean foundData = false;
|
||||
Message message = null;
|
||||
int i = 0;
|
||||
|
||||
if (chatData == null) {
|
||||
this.writeData("Must login first.", response);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
reply = new StringBuffer();
|
||||
reply.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n");
|
||||
reply.append("<html><head><title>Chat Read Page</title>\n");
|
||||
reply.append("<meta http-equiv=\"refresh\" content=\"2\">\n");
|
||||
reply.append("<script language=\"Javascript\" src=\"common.js\"></script>");
|
||||
reply.append("<script language=\"JavaScript\" type=\"text/javascript\">\n");
|
||||
reply.append(" var nickname = \"");
|
||||
reply.append(request.getSession().getAttribute(NICKNAME_ATTRIBUTE_STRING));
|
||||
reply.append("\";\n");
|
||||
|
||||
message = chatData.groupChat.pollMessage();
|
||||
while (message != null) {
|
||||
String from = message.getFrom();
|
||||
String body = message.getBody();
|
||||
|
||||
// Get the the user's nickname
|
||||
from = StringUtils.parseResource(from);
|
||||
|
||||
// PENDING - stop using the replace method
|
||||
|
||||
// encode the HTML special characters
|
||||
body = this.replace(body, "&", "&");
|
||||
body = this.replace(body, "<", "<");
|
||||
body = this.replace(body, ">", ">");
|
||||
|
||||
// replace newlines in the body:
|
||||
body = this.replace(body, "\r", "");
|
||||
body = this.replace(body, "\n", "<br>");
|
||||
|
||||
// encode the quotes
|
||||
body = this.replace(body, "\"", """);
|
||||
|
||||
// encode the embedded urls
|
||||
body = URLTRANSCODER.encodeURLsInText(body);
|
||||
|
||||
// Apply emoticons
|
||||
body = EMOTICONFILTER.applyFilter(body);
|
||||
|
||||
if (from.length() == 0) {
|
||||
reply.append(" var body").append(i).append(" = \"").append(body);
|
||||
reply.append("\";\n addChatText(body").append(i).append(", true);\n");
|
||||
} else {
|
||||
reply.append(" var from").append(i).append(" = \"").append(from);
|
||||
reply.append("\";\n var body").append(i).append(" = \"").append(body);
|
||||
reply.append("\";\n addUserName(from").append(i);
|
||||
reply.append(");\n addChatText(body").append(i).append(", false);\n");
|
||||
}
|
||||
|
||||
message = chatData.groupChat.pollMessage();
|
||||
|
||||
foundData = true;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
synchronized (chatData.newJoins) {
|
||||
synchronized (chatData.newDepartures) {
|
||||
Iterator it = chatData.newJoins.iterator();
|
||||
|
||||
i = 0;
|
||||
|
||||
while (it.hasNext()) {
|
||||
reply.append(" var joined").append(i).append(" = \"").append(it.next());
|
||||
reply.append("\";\n userJoined(joined").append(i).append(");\n");
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
it = chatData.newDepartures.iterator();
|
||||
while (it.hasNext()) {
|
||||
reply.append(" var departed").append(i).append(" = \"").append(it.next());
|
||||
reply.append("\";\n userDeparted(departed").append(i).append(");\n");
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
chatData.newJoins.clear();
|
||||
chatData.newDepartures.clear();
|
||||
}
|
||||
}
|
||||
|
||||
reply.append("</script>\n</head><body></body></html>");
|
||||
|
||||
this.writeData(reply.toString(), response);
|
||||
} else if (WRITE_COMMAND_STRING.equals(command)) {
|
||||
String message = request.getParameter(MESSAGE_REQUEST_STRING);
|
||||
ChatData chatData = (ChatData)SESSION_CHATDATA_MAP.get(sessionID);
|
||||
|
||||
if (message == null) {
|
||||
this.writeData("Parameter \"" + MESSAGE_REQUEST_STRING + "\" is required.",
|
||||
response);
|
||||
|
||||
return;
|
||||
} else if (chatData == null) {
|
||||
this.writeData("Must login first.", response);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
StringBuffer reply = new StringBuffer();
|
||||
|
||||
chatData.groupChat.sendMessage(message.trim());
|
||||
|
||||
reply.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n");
|
||||
reply.append("<html><head>\n");
|
||||
reply.append(
|
||||
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
|
||||
reply.append("<title>Chat Form</title>");
|
||||
reply.append("</head><body>\n");
|
||||
reply.append("<form name=\"chatform\" action=\"").append(path);
|
||||
reply.append("/ChatServlet\" method=\"post\">\n");
|
||||
reply.append("<input type=\"hidden\" name=\"command\" value=\"write\">\n");
|
||||
reply.append("<input type=\"hidden\" name=\"message\" value=\"\">\n");
|
||||
reply.append("</form></body></html>");
|
||||
|
||||
this.writeData(reply.toString(), response);
|
||||
} catch (XMPPException e) {
|
||||
// PENDING - better handling
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (LOGOUT_COMMAND_STRING.equals(command)) {
|
||||
ChatData chatData = null;
|
||||
|
||||
synchronized (SESSION_CHATDATA_MAP) {
|
||||
chatData = (ChatData)SESSION_CHATDATA_MAP.remove(sessionID);
|
||||
}
|
||||
|
||||
if (chatData != null) {
|
||||
if (chatData.groupChat != null) {
|
||||
chatData.groupChat.leave();
|
||||
}
|
||||
|
||||
synchronized (PACKET_ROOT_CHATDATA_MAP) {
|
||||
Packet p = new IQ();
|
||||
String root = this.getPacketIDRoot(p);
|
||||
|
||||
PACKET_ROOT_CHATDATA_MAP.remove(root);
|
||||
}
|
||||
|
||||
chatData.connection.close();
|
||||
}
|
||||
} else if (ANON_LOGIN_COMMAND_STRING.equals(command)) {
|
||||
String returnCode = this.handleLogin(request, true);
|
||||
|
||||
if (SUCCESS_RETURN_CODE_STRING.equals(returnCode)) {
|
||||
response.sendRedirect(path + CHAT_LAUNCHER_URI_SUFFIX);
|
||||
} else {
|
||||
// error, return to the original page to display errors and allow re-attempts
|
||||
RequestDispatcher rd = request.getRequestDispatcher(LOGIN_URI);
|
||||
|
||||
rd.forward(request, response);
|
||||
}
|
||||
} else if (LOGIN_COMMAND_STRING.equals(command)) {
|
||||
String returnCode = this.handleLogin(request, false);
|
||||
|
||||
if (SUCCESS_RETURN_CODE_STRING.equals(returnCode)) {
|
||||
response.sendRedirect(path + CHAT_LAUNCHER_URI_SUFFIX);
|
||||
} else {
|
||||
// error, return to the original page to display errors and allow re-attempts
|
||||
RequestDispatcher rd = request.getRequestDispatcher(LOGIN_URI);
|
||||
|
||||
rd.forward(request, response);
|
||||
}
|
||||
} else if (CREATE_ACCOUNT_COMMAND_STRING.equals(command)) {
|
||||
String returnCode = this.createAccount(request);
|
||||
|
||||
if (SUCCESS_RETURN_CODE_STRING.equals(returnCode)) {
|
||||
response.sendRedirect(path + LOGIN_URI);
|
||||
} else {
|
||||
// error, return to the original page to display errors and allow re-attempts
|
||||
RequestDispatcher rd = request.getRequestDispatcher(CREATE_ACCOUNT_URI);
|
||||
|
||||
rd.forward(request, response);
|
||||
}
|
||||
} else if (SILENCE_COMMAND_STRING.equals(command)) {
|
||||
// do nothing
|
||||
} else if (command != null) {
|
||||
this.writeData(("Invalid command: " + command), response);
|
||||
} else {
|
||||
this.writeData("Jive Messenger Chat Servlet", response);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getPacketIDRoot (Packet p) {
|
||||
if (p == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return p.getPacketID().substring(0, 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an account for the user data specified.
|
||||
*/
|
||||
private String createAccount (HttpServletRequest request) {
|
||||
String sessionID = request.getSession().getId();
|
||||
String username = request.getParameter(USERNAME_PARAM_STRING);
|
||||
String password = request.getParameter(PASSWORD_PARAM_STRING);
|
||||
String retypedPassword = request.getParameter(RETYPED_PASSWORD_PARAM_STRING);
|
||||
Map errors = new HashMap();
|
||||
|
||||
// PENDING: validate already taken username
|
||||
|
||||
if ((username == null) || (username.trim().length() == 0)) {
|
||||
errors.put("empty_username", "");
|
||||
}
|
||||
|
||||
if ((password == null) || (password.trim().length() == 0)) {
|
||||
errors.put("empty_password", "");
|
||||
}
|
||||
|
||||
if ((retypedPassword == null) || (retypedPassword.trim().length() == 0)) {
|
||||
errors.put("empty_password_two", "");
|
||||
}
|
||||
|
||||
if ((retypedPassword != null) && (password != null)
|
||||
&& (! retypedPassword.equals(password))) {
|
||||
errors.put("mismatch_password", "");
|
||||
}
|
||||
|
||||
// If there were no errors, continue
|
||||
if (errors.size() == 0) {
|
||||
ChatData chatData = (ChatData)SESSION_CHATDATA_MAP.get(sessionID);
|
||||
|
||||
// If a connection already exists for this session, close it before creating
|
||||
// another.
|
||||
if (chatData != null) {
|
||||
if (chatData.groupChat != null) {
|
||||
chatData.groupChat.leave();
|
||||
}
|
||||
|
||||
chatData.connection.close();
|
||||
}
|
||||
|
||||
chatData = new ChatData();
|
||||
|
||||
try {
|
||||
AccountManager am = null;
|
||||
|
||||
// Create connection.
|
||||
if (! this.sslEnabled) {
|
||||
if (port != -1) {
|
||||
chatData.connection = new XMPPConnection(this.host, this.port);
|
||||
} else {
|
||||
chatData.connection = new XMPPConnection(this.host);
|
||||
}
|
||||
} else {
|
||||
if (port != -1) {
|
||||
chatData.connection = new SSLXMPPConnection(this.host, this.port);
|
||||
}
|
||||
else {
|
||||
chatData.connection = new SSLXMPPConnection(this.host);
|
||||
}
|
||||
}
|
||||
|
||||
am = chatData.connection.getAccountManager();
|
||||
|
||||
// PENDING check whether the server even supports account creation
|
||||
am.createAccount(username, password);
|
||||
} catch (XMPPException e) {
|
||||
errors.put("general", "The server reported an error in account creation: "
|
||||
+ e.getXMPPError().getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.size() > 0) {
|
||||
request.setAttribute(ERRORS_ATTRIBUTE_STRING, errors);
|
||||
|
||||
return ERROR_RETURN_CODE_STRING;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN_CODE_STRING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles login logic.
|
||||
*/
|
||||
private String handleLogin (HttpServletRequest request, boolean anonymous) {
|
||||
String sessionID = request.getSession().getId();
|
||||
String username = request.getParameter(USERNAME_PARAM_STRING);
|
||||
String password = request.getParameter(PASSWORD_PARAM_STRING);
|
||||
String room = request.getParameter(ROOM_PARAM_STRING);
|
||||
String nickname = request.getParameter(NICKNAME_PARAM_STRING);
|
||||
Map errors = new HashMap();
|
||||
|
||||
// Validate parameters
|
||||
if ((! anonymous) && ((username == null) || (username.trim().length() == 0))) {
|
||||
errors.put(USERNAME_PARAM_STRING, "");
|
||||
}
|
||||
|
||||
if ((! anonymous) && ((password == null) || (password.trim().length() == 0))) {
|
||||
errors.put(PASSWORD_PARAM_STRING, "");
|
||||
}
|
||||
|
||||
if ((room == null) || (room.trim().length() == 0)) {
|
||||
errors.put(ROOM_PARAM_STRING, "");
|
||||
}
|
||||
|
||||
if ((nickname == null) || (nickname.trim().length() == 0)) {
|
||||
errors.put(NICKNAME_PARAM_STRING, "");
|
||||
}
|
||||
|
||||
// If there were no errors, continue
|
||||
if (errors.size() == 0) {
|
||||
ChatData chatData = (ChatData)SESSION_CHATDATA_MAP.get(sessionID);
|
||||
|
||||
// If a connection already exists for this session, close it before creating
|
||||
// another.
|
||||
if (chatData != null) {
|
||||
if (chatData.groupChat != null) {
|
||||
chatData.groupChat.leave();
|
||||
}
|
||||
|
||||
chatData.connection.close();
|
||||
}
|
||||
|
||||
chatData = new ChatData();
|
||||
|
||||
try {
|
||||
// Create connection.
|
||||
if (! this.sslEnabled) {
|
||||
if (port != -1) {
|
||||
chatData.connection = new XMPPConnection(this.host, this.port);
|
||||
} else {
|
||||
chatData.connection = new XMPPConnection(this.host);
|
||||
}
|
||||
} else {
|
||||
if (port != -1) {
|
||||
chatData.connection = new SSLXMPPConnection(this.host, this.port);
|
||||
}
|
||||
else {
|
||||
chatData.connection = new SSLXMPPConnection(this.host);
|
||||
}
|
||||
}
|
||||
|
||||
if (anonymous) {
|
||||
Authentication a = new Authentication();
|
||||
PacketCollector pc = chatData.connection.createPacketCollector(
|
||||
new PacketIDFilter(a.getPacketID()));
|
||||
Authentication responsePacket = null;
|
||||
|
||||
a.setType(IQ.Type.SET);
|
||||
|
||||
chatData.connection.sendPacket(a);
|
||||
|
||||
responsePacket = (Authentication)pc.nextResult(PACKET_RESPONSE_TIMEOUT_MS);
|
||||
if (responsePacket == null) {
|
||||
// throw new XMPPException("No response from the server.");
|
||||
}
|
||||
// check for error response
|
||||
|
||||
pc.cancel();
|
||||
|
||||
// since GroupChat isn't setting the 'from' in it's message sends,
|
||||
// i can't see a problem in not doing anything with the unique resource
|
||||
// we've just been given by the server. if GroupChat starts setting the
|
||||
// from, it would probably grab the information from the XMPPConnection
|
||||
// instance it holds, and as such we would then need to introduce the
|
||||
// concept of anonymous logins to XMPPConnection, or tell GroupChat what
|
||||
// to do what username is null or blank but a resource exists... PENDING
|
||||
} else {
|
||||
chatData.connection.login(username, password, JIVE_WEB_CHAT_RESOURCE_NAME);
|
||||
}
|
||||
|
||||
chatData.connection.addPacketListener(this,
|
||||
new PacketTypeFilter(Presence.class));
|
||||
|
||||
synchronized (SESSION_CHATDATA_MAP) {
|
||||
SESSION_CHATDATA_MAP.put(sessionID, chatData);
|
||||
}
|
||||
|
||||
synchronized (PACKET_ROOT_CHATDATA_MAP) {
|
||||
Packet p = new IQ();
|
||||
String root = this.getPacketIDRoot(p);
|
||||
|
||||
// PENDING -- we won't do anything with this packet, so it will ultimately look
|
||||
// to the server as though a packet has disappeared -- is this ok with the
|
||||
// server?
|
||||
PACKET_ROOT_CHATDATA_MAP.put(root, chatData);
|
||||
}
|
||||
|
||||
// Join groupChat room.
|
||||
chatData.groupChat = chatData.connection.createGroupChat(room);
|
||||
chatData.groupChat.join(nickname);
|
||||
|
||||
// Put the user's nickname in the session - this is used by the view to correctly
|
||||
// display the user's messages in a different color:
|
||||
request.getSession().setAttribute(NICKNAME_ATTRIBUTE_STRING, nickname);
|
||||
request.getSession().setAttribute(ROOM_ATTRIBUTE_STRING, room);
|
||||
} catch (XMPPException e) {
|
||||
XMPPError err = e.getXMPPError();
|
||||
|
||||
errors.put("general", ((err != null) ? err.getMessage() : e.getMessage()));
|
||||
|
||||
if (chatData.groupChat != null) {
|
||||
chatData.groupChat.leave();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.size() > 0) {
|
||||
request.setAttribute(ERRORS_ATTRIBUTE_STRING, errors);
|
||||
|
||||
return ERROR_RETURN_CODE_STRING;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN_CODE_STRING;
|
||||
}
|
||||
|
||||
private void writeData (String data, HttpServletResponse response) {
|
||||
try {
|
||||
PrintWriter responseWriter = response.getWriter();
|
||||
|
||||
response.setContentType("text/html");
|
||||
|
||||
responseWriter.println(data);
|
||||
responseWriter.close();
|
||||
} catch (IOException ioe) {
|
||||
// PENDING
|
||||
}
|
||||
}
|
||||
|
||||
// a hack class to hold a data glom (really hacky)
|
||||
private class ChatData {
|
||||
|
||||
private XMPPConnection connection;
|
||||
private GroupChat groupChat;
|
||||
private Set newJoins = new HashSet();
|
||||
private Set newDepartures = new HashSet();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all instances of oldString with newString in string.
|
||||
*
|
||||
* PENDING - why is this final?
|
||||
* PENDING - take this out -- it fails under some cases...
|
||||
*
|
||||
* @param string the String to search to perform replacements on
|
||||
* @param oldString the String that should be replaced by newString
|
||||
* @param newString the String that will replace all instances of oldString
|
||||
*
|
||||
* @return a String will all instances of oldString replaced by newString
|
||||
*/
|
||||
static public final String replace (String string, String oldString, String newString) {
|
||||
int i = 0;
|
||||
|
||||
// MAY RETURN THIS BLOCK
|
||||
if (string == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (newString == null) {
|
||||
return string;
|
||||
}
|
||||
|
||||
// Make sure that oldString appears at least once before doing any processing.
|
||||
if (( i=string.indexOf(oldString, i)) >= 0) {
|
||||
// Use char []'s, as they are more efficient to deal with.
|
||||
char[] string2 = string.toCharArray();
|
||||
char[] newString2 = newString.toCharArray();
|
||||
int oLength = oldString.length();
|
||||
StringBuffer buf = new StringBuffer(string2.length);
|
||||
int j = 1;
|
||||
|
||||
buf.append(string2, 0, i).append(newString2);
|
||||
|
||||
i += oLength;
|
||||
|
||||
// Replace all remaining instances of oldString with newString.
|
||||
while ((i=string.indexOf(oldString, i)) > 0) {
|
||||
buf.append(string2, j, (i - j)).append(newString2);
|
||||
|
||||
i += oLength;
|
||||
j = i;
|
||||
}
|
||||
|
||||
buf.append(string2, j, (string2.length - j));
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* HttpSessionListener implementation
|
||||
*
|
||||
*/
|
||||
public void sessionCreated (HttpSessionEvent event) { }
|
||||
|
||||
public void sessionDestroyed (HttpSessionEvent event) {
|
||||
String sessionID = event.getSession().getId();
|
||||
ChatData chatData = null;
|
||||
|
||||
synchronized (SESSION_CHATDATA_MAP) {
|
||||
chatData = (ChatData)SESSION_CHATDATA_MAP.remove(sessionID);
|
||||
}
|
||||
|
||||
if (chatData != null) {
|
||||
if (chatData.groupChat != null) {
|
||||
chatData.groupChat.leave();
|
||||
}
|
||||
|
||||
synchronized (PACKET_ROOT_CHATDATA_MAP) {
|
||||
Packet p = new IQ();
|
||||
String root = this.getPacketIDRoot(p);
|
||||
|
||||
PACKET_ROOT_CHATDATA_MAP.remove(root);
|
||||
}
|
||||
|
||||
chatData.connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* PacketListener implementation
|
||||
*
|
||||
*/
|
||||
public void processPacket (Packet packet) {
|
||||
Presence presence = (Presence)packet;
|
||||
String root = null;
|
||||
ChatData chatData = null;
|
||||
String userName = null;
|
||||
|
||||
// MAY RETURN THIS BLOCK
|
||||
if (presence.getMode() == Presence.Mode.INVISIBLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
root = this.getPacketIDRoot(presence);
|
||||
chatData = (ChatData)PACKET_ROOT_CHATDATA_MAP.get(root);
|
||||
|
||||
// MAY RETURN THIS BLOCK
|
||||
if (chatData == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
userName = StringUtils.parseResource(packet.getFrom());
|
||||
|
||||
if (presence.getType() == Presence.Type.UNAVAILABLE) {
|
||||
synchronized (chatData.newDepartures) {
|
||||
synchronized (chatData.newJoins) {
|
||||
chatData.newJoins.remove(userName);
|
||||
|
||||
chatData.newDepartures.add(userName);
|
||||
}
|
||||
}
|
||||
} else if (presence.getType() == Presence.Type.AVAILABLE) {
|
||||
synchronized (chatData.newJoins) {
|
||||
synchronized (chatData.newDepartures) {
|
||||
chatData.newDepartures.remove(userName);
|
||||
|
||||
chatData.newJoins.add(userName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
/**
|
||||
* $RCSfile$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright (C) 1999-2002 CoolServlets, Inc. All rights reserved.
|
||||
*
|
||||
* This software is the proprietary information of CoolServlets, Inc.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.webchat;
|
||||
|
||||
/**
|
||||
* A Filter that replaces [b][/b], [i][/i], [u][/u], [pre][/pre] tags with their HTML
|
||||
* tag equivalents.
|
||||
*/
|
||||
public class TextStyle {
|
||||
|
||||
public String applyFilter(String string) {
|
||||
if (string == null || string.length() == 0) {
|
||||
return string;
|
||||
}
|
||||
|
||||
// To figure out how many times we've made text replacements, we
|
||||
// need to pass around integer count objects.
|
||||
int[] boldStartCount = new int[1];
|
||||
int[] italicsStartCount = new int[1];
|
||||
int[] boldEndCount = new int[1];
|
||||
int[] italicsEndCount = new int[1];
|
||||
int[] underlineStartCount = new int[1];
|
||||
int[] underlineEndCount = new int[1];
|
||||
int[] preformatStartCount = new int[1];
|
||||
int[] preformatEndCount = new int[1];
|
||||
|
||||
// Bold
|
||||
string = replaceIgnoreCase(string, "[b]", "<b>", boldStartCount);
|
||||
string = replaceIgnoreCase(string, "[/b]", "</b>", boldEndCount);
|
||||
int bStartCount = boldStartCount[0];
|
||||
int bEndCount = boldEndCount[0];
|
||||
|
||||
while (bStartCount > bEndCount) {
|
||||
string = string.concat("</b>");
|
||||
bEndCount++;
|
||||
}
|
||||
|
||||
// Italics
|
||||
string = replaceIgnoreCase(string, "[i]", "<i>", italicsStartCount);
|
||||
string = replaceIgnoreCase(string, "[/i]", "</i>", italicsEndCount);
|
||||
int iStartCount = italicsStartCount[0];
|
||||
int iEndCount = italicsEndCount[0];
|
||||
|
||||
while (iStartCount > iEndCount) {
|
||||
string = string.concat("</i>");
|
||||
iEndCount++;
|
||||
}
|
||||
|
||||
// Underline
|
||||
string = replaceIgnoreCase(string, "[u]", "<u>", underlineStartCount);
|
||||
string = replaceIgnoreCase(string, "[/u]", "</u>", underlineEndCount);
|
||||
int uStartCount = underlineStartCount[0];
|
||||
int uEndCount = underlineEndCount[0];
|
||||
|
||||
while (uStartCount > uEndCount) {
|
||||
string = string.concat("</u>");
|
||||
uEndCount++;
|
||||
}
|
||||
|
||||
// Pre
|
||||
string = replaceIgnoreCase(string, "[pre]", "<pre>", preformatStartCount);
|
||||
string = replaceIgnoreCase(string, "[/pre]", "</pre>", preformatEndCount);
|
||||
int preStartCount = preformatStartCount[0];
|
||||
int preEndCount = preformatEndCount[0];
|
||||
|
||||
while (preStartCount > preEndCount) {
|
||||
string = string.concat("</pre>");
|
||||
preEndCount++;
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces all instances of oldString with newString in line with the
|
||||
* added feature that matches of newString in oldString ignore case.
|
||||
* The count paramater is set to the number of replaces performed.
|
||||
*
|
||||
* @param line the String to search to perform replacements on
|
||||
* @param oldString the String that should be replaced by newString
|
||||
* @param newString the String that will replace all instances of oldString
|
||||
* @param count a value that will be updated with the number of replaces
|
||||
* performed.
|
||||
*
|
||||
* @return a String will all instances of oldString replaced by newString
|
||||
*/
|
||||
private static final String replaceIgnoreCase(String line, String oldString,
|
||||
String newString, int [] count)
|
||||
{
|
||||
if (line == null) {
|
||||
return null;
|
||||
}
|
||||
String lcLine = line.toLowerCase();
|
||||
String lcOldString = oldString.toLowerCase();
|
||||
int i=0;
|
||||
if ((i=lcLine.indexOf(lcOldString, i)) >= 0) {
|
||||
int counter = 1;
|
||||
char [] line2 = line.toCharArray();
|
||||
char [] newString2 = newString.toCharArray();
|
||||
int oLength = oldString.length();
|
||||
StringBuffer buf = new StringBuffer(line2.length);
|
||||
buf.append(line2, 0, i).append(newString2);
|
||||
i += oLength;
|
||||
int j = i;
|
||||
while ((i=lcLine.indexOf(lcOldString, i)) > 0) {
|
||||
counter++;
|
||||
buf.append(line2, j, i-j).append(newString2);
|
||||
i += oLength;
|
||||
j = i;
|
||||
}
|
||||
buf.append(line2, j, line2.length - j);
|
||||
count[0] = counter;
|
||||
return buf.toString();
|
||||
}
|
||||
return line;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,312 @@
|
|||
/**
|
||||
* $RCSfile$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright (C) 1999-2002 CoolServlets, Inc. All rights reserved.
|
||||
*
|
||||
* This software is the proprietary information of CoolServlets, Inc.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
|
||||
package org.jivesoftware.webchat;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A Filter that converts URL's to working HTML web links.<p>
|
||||
*
|
||||
* The default set of patterns recognized are <code>ftp://path-of-url</code>,
|
||||
* <code>http://path-of-url</code>, <code>https://path-of-url</code> but can be expanded upon.<p>
|
||||
*
|
||||
* In addition, the following patterns are also recognized.
|
||||
*
|
||||
* <code>[url path-of-url]descriptive text[/url]</code> and
|
||||
* <code>[url=path-of-url]descriptive text[/url]</code>.<p>
|
||||
*
|
||||
* The <code>[url]</code> 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("<a href='").append(block.getUrl()).append("' target='_blank'>");
|
||||
if (block.getDescription().length() > 0) {
|
||||
filtered.append(block.getDescription());
|
||||
}
|
||||
else {
|
||||
filtered.append(block.getUrl());
|
||||
}
|
||||
filtered.append("</a>");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
/**
|
||||
* $RCSfile$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*
|
||||
* Copyright (C) 1999-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;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* This is a really good example of why software development projects have frameworks, and the
|
||||
* other apps in their own modules that sit on top of the frameworks... this class should not
|
||||
* be confused with com.jivesoftware.messenger.operator.util.URLTranscoder, which does a
|
||||
* variant of the functionality found here.<br>
|
||||
*
|
||||
* The default set of patterns recognized are <code>ftp://path-of-url</code>,
|
||||
* <code>http://path-of-url</code>, <code>https://path-of-url</code> but can be expanded upon.</br>
|
||||
*
|
||||
* This was originally URLTranscoder, from CoolServlets, but that class did basically nothing that
|
||||
* i wanted, so i kept the schemes collection and that was about it.<br>
|
||||
*
|
||||
* @author loki der quaeler
|
||||
*/
|
||||
public class URLTranscoder {
|
||||
|
||||
static protected final String A_HREF_PREFIX = "<a href='";
|
||||
static protected final String A_HREF_SUFFIX = "' target=_new>";
|
||||
static protected final String A_HREF_CLOSING_TAG = "</a>";
|
||||
|
||||
|
||||
protected ArrayList schemes;
|
||||
|
||||
public URLTranscoder () {
|
||||
super();
|
||||
|
||||
this.schemes = new ArrayList();
|
||||
|
||||
this.schemes.add("http://");
|
||||
this.schemes.add("https://");
|
||||
this.schemes.add("ftp://");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current supported uri schemes.
|
||||
*
|
||||
* @param schemeCollection a collection of String instances of uri schemes.
|
||||
*/
|
||||
public synchronized void setSchemes (Collection schemeCollection) {
|
||||
// MAY EXIT THIS BLOCK
|
||||
if (schemes == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.schemes.clear();
|
||||
|
||||
this.schemes.addAll(schemeCollection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String based off the original text, but now with any a.href blocks html-ized
|
||||
* inside. (for example, supplying the string "this: http://dict.leo.org/ is a cool url"
|
||||
* returns "this: <a href='http://dict.leo.org/' target=_new>http://dict.leo.org/</a>
|
||||
* is a cool url"
|
||||
*/
|
||||
public String encodeURLsInText (String text) {
|
||||
StringBuffer rhett = null;;
|
||||
List runs = this.getURLRunsInString(text);
|
||||
Iterator it = null;
|
||||
int lastStart = 0;
|
||||
|
||||
// MAY RETURN THIS BLOCK
|
||||
if (runs.size() == 0) {
|
||||
return text;
|
||||
}
|
||||
|
||||
rhett = new StringBuffer();
|
||||
it = runs.iterator();
|
||||
while (it.hasNext()) {
|
||||
URLRun run = (URLRun)it.next();
|
||||
String url = text.substring(run.getStartIndex(), run.getEndIndex());
|
||||
|
||||
if (lastStart < run.getStartIndex()) {
|
||||
rhett.append(text.substring(lastStart, run.getStartIndex()));
|
||||
|
||||
lastStart += run.getEndIndex();
|
||||
}
|
||||
|
||||
rhett.append(A_HREF_PREFIX).append(url).append(A_HREF_SUFFIX).append(url);
|
||||
rhett.append(A_HREF_CLOSING_TAG);
|
||||
}
|
||||
|
||||
if (lastStart < text.length()) {
|
||||
rhett.append(text.substring(lastStart, text.length()));
|
||||
}
|
||||
|
||||
return rhett.toString();
|
||||
}
|
||||
|
||||
protected List getURLRunsInString (String text) {
|
||||
ArrayList rhett = new ArrayList();
|
||||
Vector vStarts = new Vector();
|
||||
Iterator sIt = this.schemes.iterator();
|
||||
Integer[] iStarts = null;
|
||||
char[] tArray = null;
|
||||
|
||||
while (sIt.hasNext()) {
|
||||
String scheme = (String)sIt.next();
|
||||
int index = text.indexOf(scheme);
|
||||
|
||||
while (index != -1) {
|
||||
vStarts.add(new Integer(index));
|
||||
|
||||
index = text.indexOf(scheme, (index + 1));
|
||||
}
|
||||
}
|
||||
|
||||
// MAY RETURN THIS BLOCK
|
||||
if (vStarts.size() == 0) {
|
||||
return rhett;
|
||||
}
|
||||
|
||||
iStarts = (Integer[])vStarts.toArray(new Integer[0]);
|
||||
Arrays.sort(iStarts);
|
||||
|
||||
tArray = text.toCharArray();
|
||||
|
||||
for (int i = 0; i < iStarts.length; i++) {
|
||||
int start = iStarts[i].intValue();
|
||||
int end = start + 1;
|
||||
|
||||
while ((end < tArray.length) && (! this.characterIsURLTerminator(tArray[end]))) {
|
||||
end++;
|
||||
}
|
||||
|
||||
if (end == tArray.length) {
|
||||
end--;
|
||||
}
|
||||
|
||||
rhett.add(new URLRun(start, end));
|
||||
}
|
||||
|
||||
return rhett;
|
||||
}
|
||||
|
||||
protected boolean characterIsURLTerminator (char c) {
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '\n':
|
||||
case '(':
|
||||
case ')':
|
||||
case '>':
|
||||
case '\t':
|
||||
case '\r': return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
protected class URLRun {
|
||||
|
||||
protected int start;
|
||||
protected int end;
|
||||
|
||||
protected URLRun (int s, int e) {
|
||||
super();
|
||||
|
||||
this.start = s;
|
||||
this.end = e;
|
||||
}
|
||||
|
||||
protected int getStartIndex () {
|
||||
return this.start;
|
||||
}
|
||||
|
||||
protected int getEndIndex () {
|
||||
return this.end;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
116
CopyOftrunk/apps/webchat/source/web/account_creation.jsp
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
<%--
|
||||
-
|
||||
-
|
||||
--%>
|
||||
|
||||
<%@ page import="java.util.*" %>
|
||||
|
||||
<% // Get error map as a request attribute:
|
||||
Map errors = (Map)request.getAttribute("messenger.servlet.errors");
|
||||
if (errors == null) { errors = new HashMap(); }
|
||||
%>
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Create an account</title>
|
||||
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
|
||||
type="text/css">
|
||||
</head>
|
||||
|
||||
<body class="deffr">
|
||||
|
||||
<table width="100%" height="100%" cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<h3>Jive Account Creation</h3>
|
||||
|
||||
<% if (errors.get("general") != null) { %>
|
||||
<p>
|
||||
<span class="error-text">
|
||||
Error creating account. <%= errors.get("general") %>
|
||||
</span>
|
||||
</p>
|
||||
<br>
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<form action="<%= request.getContextPath() %>/ChatServlet"
|
||||
method="post" name="createform">
|
||||
<input type="hidden" name="command" value="create_account">
|
||||
|
||||
<table cellpadding="2" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td>Desired username:</td>
|
||||
<td>
|
||||
<input type="text" size="40" name="username"
|
||||
class="text">
|
||||
<% if (errors.get("empty_username") != null) { %>
|
||||
<span class="error-text"><br>
|
||||
Please enter a username.
|
||||
</span>
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Desired password:</td>
|
||||
<td>
|
||||
<input type="password" size="40" name="password"
|
||||
class="text">
|
||||
<% if (errors.get("empty_password") != null) { %>
|
||||
<span class="error-text"><br>
|
||||
Please enter a password.
|
||||
</span>
|
||||
<% } %>
|
||||
<% if (errors.get("mismatch_password") != null) { %>
|
||||
<span class="error-text"><br>
|
||||
Your passwords did not match.
|
||||
</span>
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Retype your password:</td>
|
||||
<td>
|
||||
<input type="password" size="40" name="password_zwei"
|
||||
class="text">
|
||||
<% if (errors.get("empty_password_two") != null) { %>
|
||||
<span class="error-text"><br>
|
||||
You must retype your password.
|
||||
</span>
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<br>
|
||||
<input type="submit" name="" value="Create account"
|
||||
class="submit">
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<br><a href="index.jsp">Click here to return to the login page.</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<script language="JavaScript" type="text/javascript">
|
||||
document.createform.username.focus();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
19
CopyOftrunk/apps/webchat/source/web/chat-hiddenform.jsp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>Chat Form</title>
|
||||
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
|
||||
type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<form name="chatform" action="<%= request.getContextPath() %>/ChatServlet" method="post">
|
||||
<input type="hidden" name="command" value="write">
|
||||
<input type="hidden" name="message" value="">
|
||||
</form>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
39
CopyOftrunk/apps/webchat/source/web/chat-launcher.jsp
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
|
||||
<title>Web Chat Session</title>
|
||||
<script language="JavaScript" type="text/javascript">
|
||||
|
||||
function launchWin() {
|
||||
var newWin = window.open("frame_master.jsp", "chatWin",
|
||||
"location=no,status=no,toolbar=no,personalbar=no,menubar=no,width=650,height=430");
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
|
||||
type="text/css">
|
||||
</head>
|
||||
|
||||
<body class="deffr" onload="launchWin();">
|
||||
|
||||
<h3>Chat Session Options</h3>
|
||||
|
||||
Your chat session should have already started. If for some reason it did
|
||||
not, click <a href="#" onclick="launchWin(); return false;">this link</a>
|
||||
to start your chat session.
|
||||
|
||||
<br><br>
|
||||
|
||||
Other options:
|
||||
|
||||
<ul>
|
||||
<li><a href="email" onclick="alert('Coming soon'); return false;">Email Transcript</a>
|
||||
<li><a href="index.jsp">Return to the login page.</a>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
182
CopyOftrunk/apps/webchat/source/web/common.js
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
function addChatText (someText, isAnnouncement) {
|
||||
var yakDiv = window.parent.frames['yak'].document.getElementById('ytext');
|
||||
var children = yakDiv.childNodes.length;
|
||||
var appendFailed = false;
|
||||
var spanElement = document.createElement("span");
|
||||
|
||||
if (! isAnnouncement) {
|
||||
spanElement.setAttribute("class", "chat_text");
|
||||
} else {
|
||||
spanElement.setAttribute("class", "chat_announcement");
|
||||
}
|
||||
// it's easier to dump the possibily html-containing text into the innerHTML
|
||||
// of the span element than deciphering and building sub-elements.
|
||||
spanElement.innerHTML = someText;
|
||||
|
||||
try {
|
||||
// various versions of IE crash out on this, and safari
|
||||
yakDiv.appendChild(spanElement);
|
||||
} catch (exception) {
|
||||
appendFailed = true;
|
||||
}
|
||||
|
||||
if (! appendFailed) {
|
||||
// really make sure the browser appended
|
||||
appendFailed = (children == yakDiv.childNodes.length);
|
||||
}
|
||||
|
||||
if (appendFailed) {
|
||||
// try this, the only way left
|
||||
var inn = yakDiv.innerHTML;
|
||||
|
||||
inn += "<span class=\"";
|
||||
inn += (isAnnouncement ? "chat_announcement\">" : "chat_text\">");
|
||||
inn += someText + "</span><br>";
|
||||
|
||||
yakDiv.innerHTML = inn;
|
||||
} else {
|
||||
yakDiv.appendChild(document.createElement("br"));
|
||||
}
|
||||
|
||||
scrollYakToEnd();
|
||||
}
|
||||
|
||||
function addUserName (userName) {
|
||||
var yakDiv = window.parent.frames['yak'].document.getElementById('ytext');
|
||||
var children = yakDiv.childNodes.length;
|
||||
var appendFailed = false;
|
||||
var spanElement = document.createElement("span");
|
||||
var userIsClientOwner = false;
|
||||
var announcement = false;
|
||||
|
||||
if (userName == "") {
|
||||
announcement = true;
|
||||
|
||||
spanElement.setAttribute("class", "chat_announcement");
|
||||
|
||||
userName = "room announcement";
|
||||
} else if (userName == nickname) {
|
||||
userIsClientOwner = true;
|
||||
|
||||
spanElement.setAttribute("class", "chat_owner");
|
||||
} else {
|
||||
spanElement.setAttribute("class", "chat_participant");
|
||||
}
|
||||
|
||||
try {
|
||||
spanElement.appendChild(document.createTextNode(userName + ": "));
|
||||
|
||||
// various versions of IE crash out on this, and safari
|
||||
yakDiv.appendChild(spanElement);
|
||||
} catch (exception) {
|
||||
appendFailed = true;
|
||||
}
|
||||
|
||||
if (! appendFailed) {
|
||||
// really make sure the browser appended
|
||||
appendFailed = (children == yakDiv.childNodes.length);
|
||||
}
|
||||
|
||||
if (appendFailed) {
|
||||
// try this, the only way left
|
||||
var inn = yakDiv.innerHTML
|
||||
|
||||
inn += "<span class=\"";
|
||||
|
||||
if (announcement) {
|
||||
inn += "chat_announcement"
|
||||
} else if (userIsClientOwner) {
|
||||
inn += "chat_owner";
|
||||
} else {
|
||||
inn += "chat_participant";
|
||||
}
|
||||
|
||||
inn += "\">" + userName + ": </span>";
|
||||
|
||||
yakDiv.innerHTML = inn;
|
||||
}
|
||||
}
|
||||
|
||||
function scrollYakToEnd () {
|
||||
var endDiv = window.parent.frames['yak'].document.getElementById('enddiv');
|
||||
|
||||
window.parent.frames['yak'].window.scrollTo(0, endDiv.offsetTop);
|
||||
}
|
||||
|
||||
function userJoined (username) {
|
||||
var parentDIV = window.parent.frames['participants'].document.getElementById('par__list');
|
||||
var children = parentDIV.childNodes.length;
|
||||
var appendFailed = false;
|
||||
var divElement = document.createElement("div");
|
||||
|
||||
divElement.setAttribute("id", username);
|
||||
|
||||
try {
|
||||
divElement.appendChild(document.createTextNode(username));
|
||||
divElement.appendChild(document.createElement("br"));
|
||||
|
||||
parentDIV.appendChild(divElement);
|
||||
} catch (exception) {
|
||||
appendFailed = true;
|
||||
}
|
||||
|
||||
if (! appendFailed) {
|
||||
// really make sure the browser appended
|
||||
appendFailed = (children == parentDIV.childNodes.length);
|
||||
}
|
||||
|
||||
if (appendFailed) {
|
||||
// try this, the only way left
|
||||
var inn = parentDIV.innerHTML;
|
||||
|
||||
inn += "<div id=\"" + username + "\"> · " + username + "<br></div>";
|
||||
|
||||
parentDIV.innerHTML = inn;
|
||||
}
|
||||
}
|
||||
|
||||
function userDeparted (username) {
|
||||
var partDoc = window.parent.frames['participants'].document;
|
||||
var parentDIV = partDoc.getElementById('par__list');
|
||||
var userDIV = partDoc.getElementById(username);
|
||||
var children = parentDIV.childNodes.length;
|
||||
var removeFailed = false;
|
||||
|
||||
// MAY RETURN THIS BLOCK
|
||||
if (userDIV == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
parentDIV.removeChild(userDIV);
|
||||
} catch (exception) {
|
||||
removeFailed = true;
|
||||
}
|
||||
|
||||
if (! removeFailed) {
|
||||
// really make sure the browser appended
|
||||
removeFailed = (children == parentDIV.childNodes.length);
|
||||
}
|
||||
|
||||
if (removeFailed) {
|
||||
// try this, the only way left
|
||||
var inn = parentDIV.innerHTML;
|
||||
var openingTag = "<div id=\"" + username + "\">";
|
||||
var index = inn.toLowerCase().indexOf(openingTag);
|
||||
var patchedHTML = inn.substring(0, index);
|
||||
var secondIndex = openingTag.length + username.length + 13;
|
||||
|
||||
patchedHTML += inn.substring(secondIndex, (inn.length));
|
||||
|
||||
parentDIV.innerHTML = inn;
|
||||
}
|
||||
}
|
||||
|
||||
function writeDate () {
|
||||
var msg = "This frame loaded at: ";
|
||||
var now = new Date();
|
||||
|
||||
msg += now + "<br><hr>";
|
||||
|
||||
document.write(msg);
|
||||
}
|
||||
33
CopyOftrunk/apps/webchat/source/web/frame_master.jsp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<html>
|
||||
<head>
|
||||
<title><%= request.getSession().getAttribute("messenger.servlet.room") %>
|
||||
- Jive Web Chat Client</title>
|
||||
|
||||
<script>
|
||||
|
||||
function frameSetLoaded () {
|
||||
window.frames['poller'].location.href
|
||||
= "<%= request.getContextPath() %>/ChatServlet?command=read";
|
||||
}
|
||||
|
||||
function attemptLogout () {
|
||||
window.frames['participants'].document.logout.submit();
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
|
||||
type="text/css">
|
||||
</head>
|
||||
|
||||
<frameset cols="*, 125" border="0" frameborder="0" framespacing="0"
|
||||
onLoad="frameSetLoaded();" onUnload="attemptLogout();">
|
||||
<frameset rows="0, 200, *, 0" border="0" frameborder="0" framespacing="0">
|
||||
<frame name="submitter" src="chat-hiddenform.jsp" frameborder="0">
|
||||
<frame name="yak" src="transcript_frame.html" frameborder="0">
|
||||
<frame name="input" src="input_frame.jsp" frameborder="0">
|
||||
<frame name="poller" src="" frameborder="0">
|
||||
</frameset>
|
||||
<frame name="participants" src="participants_frame.jsp" class="bordered_left">
|
||||
</frameset>
|
||||
</html>
|
||||
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/angry.gif
Normal file
|
After Width: | Height: | Size: 692 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/blush.gif
Normal file
|
After Width: | Height: | Size: 688 B |
|
After Width: | Height: | Size: 688 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/cool.gif
Normal file
|
After Width: | Height: | Size: 687 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/cry.gif
Normal file
|
After Width: | Height: | Size: 693 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/devil.gif
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/grin.gif
Normal file
|
After Width: | Height: | Size: 680 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/happy.gif
Normal file
|
After Width: | Height: | Size: 675 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/laugh.gif
Normal file
|
After Width: | Height: | Size: 670 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/love.gif
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 693 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/plain.gif
Normal file
|
After Width: | Height: | Size: 678 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/sad.gif
Normal file
|
After Width: | Height: | Size: 694 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/shocked.gif
Normal file
|
After Width: | Height: | Size: 688 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/silly.gif
Normal file
|
After Width: | Height: | Size: 685 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/wink.gif
Normal file
|
After Width: | Height: | Size: 634 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/logo.gif
Normal file
|
After Width: | Height: | Size: 925 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/logout-16x16.gif
Normal file
|
After Width: | Height: | Size: 325 B |
164
CopyOftrunk/apps/webchat/source/web/index.jsp
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
<%--
|
||||
-
|
||||
-
|
||||
--%>
|
||||
|
||||
<%@ page import="java.util.*" %>
|
||||
|
||||
<% // Get error map as a request attribute:
|
||||
Map errors = (Map)request.getAttribute("messenger.servlet.errors");
|
||||
boolean allowAnonymous = true;
|
||||
boolean allowAccountCreate = true;
|
||||
boolean allowLogin = true;
|
||||
String param = null;
|
||||
if (errors == null) { errors = new HashMap(); }
|
||||
param = application.getInitParameter("allowAnonymous");
|
||||
if ((param != null) && (param.equalsIgnoreCase("false"))) {
|
||||
allowAnonymous = false;
|
||||
}
|
||||
param = application.getInitParameter("allowAccountCreation");
|
||||
if ((param != null) && (param.equalsIgnoreCase("false"))) {
|
||||
allowAccountCreate = false;
|
||||
}
|
||||
param = application.getInitParameter("allowLogin");
|
||||
if ((param != null) && (param.equalsIgnoreCase("false"))) {
|
||||
allowLogin = false;
|
||||
}
|
||||
%>
|
||||
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Jive Web Chat Client Login</title>
|
||||
|
||||
<script language="JavaScript" type="text/javascript">
|
||||
function submitForm (el) {
|
||||
el.form.submit();
|
||||
}
|
||||
|
||||
function anonClick () {
|
||||
document.loginform.command.value = "anon_login";
|
||||
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
|
||||
type="text/css">
|
||||
</head>
|
||||
|
||||
<body class="deffr">
|
||||
|
||||
<table width="100%" height="100%" cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<h3>Welcome to the Jive Web Chat Client - Please Login</h3>
|
||||
<% if (errors.get("general") != null) { %>
|
||||
<p class="error-text">
|
||||
Error logging in. Make sure your username and
|
||||
password are correct. <%= errors.get("general") %>
|
||||
</p>
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<form action="<%= request.getContextPath() %>/ChatServlet"
|
||||
method="post" name="loginform">
|
||||
<input type="hidden" name="command" value="login">
|
||||
|
||||
<table cellpadding="2" cellspacing="0" border="0">
|
||||
<% if (allowLogin) { %>
|
||||
<tr>
|
||||
<td>Username:</td>
|
||||
<td>
|
||||
<input type="text" size="40" name="username"
|
||||
class="text">
|
||||
<% if (errors.get("username") != null) { %>
|
||||
<span class="error-text"><br>
|
||||
Please enter a valid username.
|
||||
</span>
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password:</td>
|
||||
<td>
|
||||
<input type="password" size="40" name="password"
|
||||
class="text">
|
||||
<% if (errors.get("password") != null) { %>
|
||||
<span class="error-text"><br>
|
||||
Please enter a valid password.
|
||||
</span>
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
<tr>
|
||||
<td>Nickname:</td>
|
||||
<td>
|
||||
<input type="text" size="40" name="nickname"
|
||||
class="text">
|
||||
<% if (errors.get("nickname") != null) { %>
|
||||
<span class="error-text"><br>
|
||||
Please enter a nickname.
|
||||
</span>
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Room:</td>
|
||||
<td>
|
||||
<input type="text" size="40" name="room"
|
||||
value="test@chat.jivesoftware.com" class="text">
|
||||
<% if (errors.get("room") != null) { %>
|
||||
<span class="error-text"><br>
|
||||
Please enter a valid room.
|
||||
</span>
|
||||
<% } %>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<br>
|
||||
<% if (allowLogin) { %>
|
||||
<input type="submit" name="" value="Login and Chat"
|
||||
class="submit">
|
||||
<% } %>
|
||||
<% if (allowAnonymous) { %>
|
||||
<input type="submit" name="" value="Anonymously Chat"
|
||||
onClick="return anonClick();" class="submit">
|
||||
<% } %>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<% if (allowAccountCreate) { %>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<br>Don't have an account and would like to create one?
|
||||
<a href="account_creation.jsp">Click here.</a>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<script language="JavaScript" type="text/javascript">
|
||||
<% if (allowLogin) { %>
|
||||
document.loginform.username.focus();
|
||||
<% } else { %>
|
||||
document.loginform.nickname.focus();
|
||||
<% } %>
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
75
CopyOftrunk/apps/webchat/source/web/input_frame.jsp
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
<%@ page import="javax.servlet.*" %>
|
||||
|
||||
<% // Get error map as a request attribute:
|
||||
String logoFilename = application.getInitParameter("logoFilename");
|
||||
if (logoFilename == null) {
|
||||
logoFilename = "images/logo.gif";
|
||||
}
|
||||
%>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="expires" content="0">
|
||||
|
||||
<script>
|
||||
function updateButtonState (textAreaElement) {
|
||||
if (textAreaElement.value != '') {
|
||||
textAreaElement.form.send.disabled = false;
|
||||
} else {
|
||||
textAreaElement.form.send.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
function handleKeyEvent (event, textAreaElement) {
|
||||
var form = textAreaElement.form;
|
||||
var keyCode = event.keyCode;
|
||||
|
||||
if (keyCode == null) {
|
||||
keyCode = event.which;
|
||||
}
|
||||
|
||||
if (keyCode == 13) {
|
||||
submitForm(form);
|
||||
|
||||
form.message.value = '';
|
||||
}
|
||||
|
||||
updateButtonState(textAreaElement);
|
||||
}
|
||||
|
||||
function submitForm (formElement) {
|
||||
var textAreaElement = formElement.message;
|
||||
var text = textAreaElement.value;
|
||||
var sForm = window.parent.frames['submitter'].document.chatform;
|
||||
|
||||
sForm.message.value = text;
|
||||
sForm.submit();
|
||||
|
||||
textAreaElement.value = '';
|
||||
|
||||
updateButtonState(textAreaElement);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
|
||||
type="text/css">
|
||||
</head>
|
||||
|
||||
<body class="deffr">
|
||||
<center>
|
||||
<form name="chat" onsubmit="return submitForm(this);">
|
||||
<textarea name="message"
|
||||
onkeyup="handleKeyEvent(event, this);"
|
||||
onchange="updateButtonState(this);"></textarea>
|
||||
<br>
|
||||
<input type="submit" name="send" value="Send" class="submit_right" disabled>
|
||||
</form>
|
||||
</center>
|
||||
|
||||
<img src="<%= logoFilename %>" class="logo">
|
||||
</body>
|
||||
|
||||
</html>
|
||||
46
CopyOftrunk/apps/webchat/source/web/participants_frame.jsp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="expires" content="0">
|
||||
|
||||
<script>
|
||||
|
||||
function verifyLogout () {
|
||||
if (confirm("Are you sure you'd like to logout")) {
|
||||
// hacky solution to avoid logging out twice due to parent frame's onUnload
|
||||
try {
|
||||
document.logout.command.value = "silence";
|
||||
} catch (e) { }
|
||||
|
||||
window.parent.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
|
||||
type="text/css">
|
||||
</head>
|
||||
|
||||
<body class="deffr">
|
||||
<center>In the room:</center>
|
||||
<br>
|
||||
<hr width=67%>
|
||||
|
||||
<div id="par__list"> </div>
|
||||
|
||||
<form name="logout" action="<%= request.getContextPath() %>/ChatServlet" method="post">
|
||||
<input type="hidden" name="command" value="logout">
|
||||
</form>
|
||||
|
||||
<span class="logout">
|
||||
<a href="<%= request.getContextPath() %>/ChatServlet?command=logout"
|
||||
onclick="return verifyLogout();" >
|
||||
<img src="images/logout-16x16.gif" border="0" class="logout"> Logout</a></span>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
132
CopyOftrunk/apps/webchat/source/web/style_sheet.jsp
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
<% // Set the content type of the this page to be CSS
|
||||
String contentType = "text/css";
|
||||
String chatAnnouncementColor = application.getInitParameter("chat.announcement-color");
|
||||
String chatOwnerLabelColor = application.getInitParameter("chat.owner-label-color");
|
||||
String chatParticipantLabelColor = application.getInitParameter("chat.participant-label-color");
|
||||
String chatTextColor = application.getInitParameter("chat.text-color");
|
||||
String errorTextColor = application.getInitParameter("error.text-color");
|
||||
String linkColor = application.getInitParameter("link.color");
|
||||
String linkHoverColor = application.getInitParameter("link.hover-color");
|
||||
String linkVisitedColor = application.getInitParameter("link.visited-color");
|
||||
String bodyBGColor = application.getInitParameter("body.background-color");
|
||||
String bodyTextColor = application.getInitParameter("body.text-color");
|
||||
String frameDividerColor = application.getInitParameter("frame.divider-color");
|
||||
String buttonColor = application.getInitParameter("button.color");
|
||||
String buttonTextColor = application.getInitParameter("button.text-color");
|
||||
String textFieldColor = application.getInitParameter("textfield.color");
|
||||
String textFieldTextColor = application.getInitParameter("textfield.text-color");
|
||||
response.setContentType(contentType);
|
||||
if (chatAnnouncementColor == null) {
|
||||
chatAnnouncementColor = "#009d00";
|
||||
}
|
||||
if (chatOwnerLabelColor == null) {
|
||||
chatOwnerLabelColor = "#aa0000";
|
||||
}
|
||||
if (chatParticipantLabelColor == null) {
|
||||
chatParticipantLabelColor = "#0000aa";
|
||||
}
|
||||
if (chatTextColor == null) {
|
||||
chatTextColor = "#434343";
|
||||
}
|
||||
if (errorTextColor == null) {
|
||||
errorTextColor = "#ff0000";
|
||||
}
|
||||
if (linkColor == null) {
|
||||
linkColor = "#045d30";
|
||||
}
|
||||
if (linkHoverColor == null) {
|
||||
linkHoverColor = "#350000";
|
||||
}
|
||||
if (linkVisitedColor == null) {
|
||||
linkVisitedColor = "#3b3757";
|
||||
}
|
||||
if (bodyBGColor == null) {
|
||||
bodyBGColor = "#ffffff";
|
||||
}
|
||||
if (bodyTextColor == null) {
|
||||
bodyTextColor = "#362f2d";
|
||||
}
|
||||
if (frameDividerColor == null) {
|
||||
frameDividerColor = "#83272b";
|
||||
}
|
||||
if (buttonColor == null) {
|
||||
buttonColor = "#d6dfdf";
|
||||
}
|
||||
if (buttonTextColor == null) {
|
||||
buttonTextColor = "#333333";
|
||||
}
|
||||
if (textFieldColor == null) {
|
||||
textFieldColor = "#f7f7fb";
|
||||
}
|
||||
if (textFieldTextColor == null) {
|
||||
textFieldTextColor = "#333333";
|
||||
}
|
||||
%>
|
||||
|
||||
BODY, TD, TH { font-family : Tahoma, Arial, Verdana, sans serif; font-size: 13px; }
|
||||
|
||||
H3 { font-size : 1.2em; }
|
||||
|
||||
.error-text { color : <%= errorTextColor %>; }
|
||||
|
||||
|
||||
/* default unvisited, visited and hover link presentation */
|
||||
A:link { background: transparent; color: <%= linkColor %>;
|
||||
text-decoration: none; }
|
||||
A:visited { background: transparent; color: <%= linkVisitedColor %>;
|
||||
text-decoration: none; }
|
||||
A:hover { background: transparent; color: <%= linkHoverColor %>;
|
||||
text-decoration: underline; }
|
||||
|
||||
/**
|
||||
* site wide BODY style rule; the scrollbar stuff only works in IE for windows,
|
||||
* but doesn't seem to hurt on other browsers..
|
||||
*/
|
||||
BODY.deffr { background-color: <%= bodyBGColor %>; color: <%= bodyTextColor %>;
|
||||
scrollbar-face-color: <%= bodyBGColor %>;
|
||||
scrollbar-shadow-color: <%= bodyTextColor %>;
|
||||
scrollbar-highlight-color: <%= bodyBGColor %>;
|
||||
scrollbar-darkshadow-color: <%= bodyBGColor %>;
|
||||
scrollbar-track-color: <%= bodyBGColor %>;
|
||||
scrollbar-arrow-color: <%= bodyTextColor %>; }
|
||||
|
||||
|
||||
FRAME.bordered_left { border-left: 3px solid <%= frameDividerColor %>; }
|
||||
|
||||
|
||||
IMG.logo { position: absolute; bottom: 12px; left: 10px; }
|
||||
|
||||
IMG.logout { vertical-align: middle; }
|
||||
|
||||
|
||||
INPUT.submit { background-color: <%= buttonColor %>; color: <%= buttonTextColor %>;
|
||||
font-size: 12px; font-family: Arial, Verdana, sans serif;
|
||||
border-style: ridge; margin: 1px 5px 1px 5px; }
|
||||
|
||||
INPUT.submit_right { background-color: <%= buttonColor %>; color: <%= buttonTextColor %>;
|
||||
font-size: 12px; font-family: Arial, Verdana, sans serif;
|
||||
border-style: ridge; margin: 1px 5px 1px 5px;
|
||||
position: absolute; right: 10px; }
|
||||
|
||||
INPUT.text { background-color: <%= textFieldColor %>; color: <%= textFieldTextColor %>;
|
||||
font: normal 12px Arial, Verdana, sans serif; height: 20px; width: 271px;
|
||||
border-style: groove; margin-left: 10px; }
|
||||
|
||||
|
||||
SPAN.chat_text { font: normal 11px Arial, Verdana, sans serif;
|
||||
color: <%= chatTextColor %>; }
|
||||
|
||||
SPAN.chat_announcement { font: italic 11px Arial, Verdana, sans serif;
|
||||
color: <%= chatAnnouncementColor %>; }
|
||||
|
||||
SPAN.chat_owner { font: bold 11px Arial, Verdana, sans serif;
|
||||
color: <%= chatOwnerLabelColor %>; }
|
||||
|
||||
SPAN.chat_participant { font: bold 11px Arial, Verdana, sans serif;
|
||||
color: <%= chatParticipantLabelColor %>; }
|
||||
|
||||
SPAN.logout { position: absolute; bottom: 12px; right: 15px; }
|
||||
|
||||
|
||||
TEXTAREA { color: <%= textFieldTextColor %>; font: normal 12px Arial, Verdana, sans serif;
|
||||
width: 500px; height: 130px; }
|
||||
13
CopyOftrunk/apps/webchat/source/web/transcript_frame.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="expires" content="0">
|
||||
|
||||
<link rel="stylesheet" href="style_sheet.jsp" type="text/css" media="screen">
|
||||
</head>
|
||||
|
||||
<body class="deffr">
|
||||
<div id="ytext"> <br></div><div id="enddiv"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||