1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2025-12-05 20:51:07 +01:00

smack_1_5_1

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@2639 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Gaston Dombiak 2005-08-12 21:09:32 +00:00 committed by gato
parent aa32e12164
commit 7ae75258be
276 changed files with 40430 additions and 0 deletions

View 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>

View file

@ -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;
}
}

View file

@ -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, "&", "&amp;");
body = this.replace(body, "<", "&lt;");
body = this.replace(body, ">", "&gt;");
// replace newlines in the body:
body = this.replace(body, "\r", "");
body = this.replace(body, "\n", "<br>");
// encode the quotes
body = this.replace(body, "\"", "&quot;");
// 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);
}
}
}
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

View 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>

View 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>

View 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>

View 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 + "\"> &middot; " + 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);
}

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

View 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>

View 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>

View 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>

View 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; }

View 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>