Commit 1bad1502 authored by Gaston Dombiak's avatar Gaston Dombiak Committed by gato

Changing name to Wildfire (initial work).

git-svn-id: http://svn.igniterealtime.org/svn/repos/messenger/trunk@3208 b35dd754-fafc-0310-a699-88a17e54d16e
parent bb8e15b8
/**
* $RCSfile$
* $Revision: 1594 $
* $Date: 2005-07-04 14:08:42 -0300 (Mon, 04 Jul 2005) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.plugin;
import org.xmpp.packet.Message;
import java.util.ArrayList;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Filters message content using regular expressions. If a content mask is
* provided message content will be altered.
*
* @author Conor Hayes
*/
public class ContentFilter {
private String patterns;
private Collection<Pattern> compiledPatterns = new ArrayList<Pattern>();
private String mask;
/**
* A default instance will allow all message content.
*
* @see #setPatterns(String)
* @see #setMask(String)
*/
public ContentFilter() {
}
/**
* Set the patterns to use for searching content.
*
* @param regExps a comma separated String of regular expressions
*/
public void setPatterns(String patterns) {
if (patterns != null) {
this.patterns = patterns;
String[] data = patterns.split(",");
compiledPatterns.clear();
for (int i = 0; i < data.length; i++) {
compiledPatterns.add(Pattern.compile(data[i]));
}
}
else {
clearPatterns();
}
}
public String getPatterns() {
return this.patterns;
}
/**
* Clears all patterns. Calling this method means that all message content
* will be allowed.
*/
public void clearPatterns() {
patterns = null;
compiledPatterns.clear();
}
/**
* Set the content replacement mask.
*
* @param mask the mask to use when replacing content
*/
public void setMask(String mask) {
this.mask = mask;
}
/**
* @return the current mask or null if none has been set
*/
public String getMask() {
return mask;
}
/**
* Clears the content mask.
*
* @see #filter(Message)
*/
public void clearMask() {
mask = null;
}
/**
* @return true if the filter is currently masking content, false otherwise
*/
public boolean isMaskingContent() {
return mask != null;
}
/**
* Filters message content.
*
* @param msg the message to filter, its subject/body may be altered if there
* are content matches and a content mask is set
* @return true if the msg content matched up, false otherwise
*/
public boolean filter(Message msg) {
boolean hasMatch = false;
if (msg.getSubject() != null) {
if (hasMatch(msg.getSubject())) {
hasMatch = true;
if (isMaskingContent()) {
String newSubject = replaceContent(msg.getSubject());
msg.setSubject(newSubject);
}
}
}
if (msg.getBody() != null) {
if (hasMatch(msg.getBody())) {
hasMatch = true;
if (isMaskingContent()) {
String newBody = replaceContent(msg.getBody());
msg.setBody(newBody);
}
}
}
return hasMatch;
}
private String replaceContent(String content) {
for (Pattern pattern : compiledPatterns) {
Matcher m = pattern.matcher(content);
content = m.replaceAll(mask);
}
return content;
}
/**
* Performs sequential search for any pattern match.
*
* @param content the content to search against
* @return true if a match is found, false otherwise
*/
private boolean hasMatch(String content) {
boolean hasMatch = false;
for (Pattern pattern : compiledPatterns) {
Matcher m = pattern.matcher(content);
if (m.find()) {
hasMatch = true;
break;
}
}
return hasMatch;
}
}
\ No newline at end of file
/**
* $RCSfile$
* $Revision: 1722 $
* $Date: 2005-07-28 19:19:16 -0300 (Thu, 28 Jul 2005) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.plugin;
import org.jivesoftware.wildfire.container.Plugin;
import org.jivesoftware.wildfire.container.PluginManager;
import org.jivesoftware.wildfire.user.UserManager;
import org.jivesoftware.wildfire.user.UserNotFoundException;
import org.jivesoftware.wildfire.user.User;
import org.jivesoftware.wildfire.PresenceManager;
import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.util.JiveGlobals;
import org.xmpp.packet.Presence;
import org.xmpp.packet.JID;
import java.io.File;
/**
* Plugin that includes a servlet that provides information about the presence type of the
* users in the server. For security reasons, the XMPP spec does not allow anyone to see
* the presence of any user. Only the users that are subscribed to the presence of other
* users may see their presences.<p>
*
* However, in order to make the servlet more useful it is possible to configure this plugin
* so that anyone or only the users that are subscribed to a user presence may see the presence
* of other users.<p>
*
* Currently, the servlet provides information about user presences in two formats. In XML format
* or using images.
*
* @author Gaston Dombiak
*/
public class PresencePlugin implements Plugin {
private UserManager userManager;
private PresenceManager presenceManager;
private String hostname;
public void initializePlugin(PluginManager manager, File pluginDirectory) {
XMPPServer server = XMPPServer.getInstance();
userManager = server.getUserManager();
presenceManager = server.getPresenceManager();
hostname = server.getServerInfo().getName();
}
public void destroyPlugin() {
userManager = null;
presenceManager = null;
}
/**
* Returns true if anyone is allowed to see the presence of other users. False means that
* only the users that are subscribed to a user presence will be able to get information
* about the user. By default, presence information is not publicly available.
*
* @return true if anyone is allowed to see the presence of other users.
*/
public boolean isPresencePublic() {
return JiveGlobals.getBooleanProperty("plugin.presence.public", false);
}
/**
* Sets if anyone is allowed to see the presence of other users. A false value means that
* only the users that are subscribed to a user presence will be able to get information
* about the user. By default, presence information is not publicly available.
*
* @param presencesPublic if anyone is allowed to see the presence of other users.
*/
public void setPresencePublic(boolean presencesPublic) {
JiveGlobals.setProperty("plugin.presence.public", presencesPublic ? "true" : "false");
}
/**
* Returns the presence of the requested user or <tt>null</tt> if the user is offline. If
* presences are not public then the user presence will be returned if and only if the sender
* of the request is subscribed to the user presence.
*
* @param sender the bare JID of the user making the request.
* @param jid the bare JID of the entity whose presence is being probed.
* @return the presence of the requested user.
* @throws UserNotFoundException If presences are not public and the sender is null or the
* sender cannot probe the presence of the requested user. Or if the requested user
* does not exist in the local server.
*/
public Presence getPresence(String sender, String jid) throws UserNotFoundException {
JID targetJID = new JID(jid);
// Check that the sender is not requesting information of a remote server entity
if (targetJID.getDomain() == null || XMPPServer.getInstance().isRemote(targetJID)) {
throw new UserNotFoundException("Domain does not matches local server domain");
}
if (!hostname.equals(targetJID.getDomain())) {
// Sender is requesting information about component presence
// TODO Implement this
throw new UserNotFoundException("Presence of components not supported yet!");
}
if (targetJID.getNode() == null) {
// Sender is requesting presence information of an anonymous user
throw new UserNotFoundException("Username is null");
}
if (!isPresencePublic()) {
if (sender == null) {
throw new UserNotFoundException("Sender is null");
}
else if (!presenceManager.canProbePresence(new JID(sender), targetJID.getNode())) {
throw new UserNotFoundException("Sender is not allowed to probe this user");
}
}
User user = userManager.getUser(targetJID.getNode());
return presenceManager.getPresence(user);
}
}
/**
* $RCSfile$
* $Revision: 1682 $
* $Date: 2005-07-22 18:13:38 -0300 (Fri, 22 Jul 2005) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.plugin.presence;
import org.jivesoftware.util.Log;
import org.xmpp.packet.Presence;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
/**
* The ImagePresenceProvider provides information about the users presence by returning
* images. There are many ways to specify the images to use.
*
* <ul>
* <li>Use a single parameter in the URL - Use the <b>images</b> parameter that will include a
* --IMAGE-- token. The --IMAGE-- token would be filtered and would be replaced with
* codes like "dnd", "offline", "away", etc.</li>
* <li>Use a parameter for each possible presence type - Possible parameters are: <b>offline</b>,
* <b>available</b>, <b>away</b>, <b>chat</b>, <b>dnd</b>, <b>xa</b> and <b>forbidden</b>. If
* the parameter was not passed then the default image will be used.</li>
* <li>Do not pass any parameter - When no parameter was passed the default images will be
* used.</li>
* </ul>
*
* If the required user was not found or the user making the request is not allowed to see the
* user presence then the image specified in the <b>forbidden</b> parameter will be used.
* However, if the request does not include the <b>forbidden</b> parameter then the default
* image for user offline will be used.
*
* @author Gaston Dombiak
*
*/
class ImagePresenceProvider extends PresenceInfoProvider {
private PresenceStatusServlet servlet;
private Map<String, byte[]> imageCache = new HashMap<String, byte[]>();
private Map<String, String> imageTypeCache = new HashMap<String, String>();
public ImagePresenceProvider(PresenceStatusServlet servlet) {
this.servlet = servlet;
}
public void sendInfo(HttpServletRequest request,
HttpServletResponse response, Presence presence) throws IOException {
if (presence == null) {
writeImageContent(request, response, "offline", servlet.offline);
}
else if (presence.getShow() == null) {
writeImageContent(request, response, "available", servlet.available);
}
else if (presence.getShow().equals(org.xmpp.packet.Presence.Show.away)) {
writeImageContent(request, response, "away", servlet.away);
}
else if (presence.getShow().equals(org.xmpp.packet.Presence.Show.chat)) {
writeImageContent(request, response, "chat", servlet.chat);
}
else if (presence.getShow().equals(org.xmpp.packet.Presence.Show.dnd)) {
writeImageContent(request, response, "dnd", servlet.dnd);
}
else if (presence.getShow().equals(org.xmpp.packet.Presence.Show.xa)) {
writeImageContent(request, response, "xa", servlet.xa);
}
}
public void sendUserNotFound(HttpServletRequest request, HttpServletResponse response)
throws IOException {
writeImageContent(request, response, "forbidden", servlet.offline);
}
private void writeImageContent(HttpServletRequest request, HttpServletResponse response,
String presenceType, byte[] defaultImage) throws IOException {
String images = request.getParameter("images");
if (request.getParameter(presenceType) != null) {
writeImageContent(request.getParameter(presenceType), defaultImage, response);
}
else if (images != null) {
writeImageContent(images.replace("--IMAGE--", presenceType), defaultImage, response);
}
else {
writeImageContent(null, defaultImage, response);
}
}
private void writeImageContent(String url, byte[] defaultContent, HttpServletResponse response)
throws IOException {
ServletOutputStream os = response.getOutputStream();
byte[] imageContent = defaultContent;
String contentType = "image/gif";
if (url != null) {
try {
byte[] cachedContent = imageCache.get(url);
if (cachedContent == null) {
URLConnection connection = new URL(url).openConnection();
InputStream in = connection.getInputStream();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
byte buffer[] = new byte[1024 * 4];
int last_read_bytes = 0;
while ((last_read_bytes = in.read(buffer)) != -1) {
bytes.write(buffer, 0, last_read_bytes);
}
if (bytes.size() > 0) {
imageCache.put(url, bytes.toByteArray());
imageTypeCache.put(url, connection.getContentType());
}
}
if (imageTypeCache.get(url) != null) {
contentType = imageTypeCache.get(url);
imageContent = imageCache.get(url);
}
}
catch (IOException e) {
Log.error(e);
}
}
response.setContentType(contentType);
os.write(imageContent);
os.flush();
os.close();
}
}
/**
* $RCSfile$
* $Revision: 1660 $
* $Date: 2005-07-21 00:05:27 -0300 (Thu, 21 Jul 2005) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.plugin.presence;
import org.xmpp.packet.Presence;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Abstract class for the different ways to provide information about user presences.
*
* @author Gaston Dombiak
*/
abstract class PresenceInfoProvider {
/**
* Sends information to the sender of the http request about the presence of a user.
*
* @param httpServletRequest the http request.
* @param httpServletResponse the http response.
* @param presence the presence of the user or <tt>null</tt> if the user is offline.
* @throws IOException If an error occured while sending the information.
*/
public abstract void sendInfo(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Presence presence) throws IOException;
/**
* Informs the sender of the http request that the user presence is not available. This may
* happen if the user does not exist or if the user that made the request is not allowed to
* see the presence of the requested user.
*
* @param httpServletRequest the http request.
* @param httpServletResponse the http response.
* @throws IOException If an error occured while sending the information.
*/
public abstract void sendUserNotFound(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws IOException;
}
/**
* $RCSfile$
* $Revision: 1710 $
* $Date: 2005-07-26 15:56:14 -0300 (Tue, 26 Jul 2005) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.plugin.presence;
import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.plugin.PresencePlugin;
import org.jivesoftware.wildfire.user.UserNotFoundException;
import org.jivesoftware.util.Log;
import org.jivesoftware.admin.AuthCheckFilter;
import org.xmpp.packet.Presence;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Servlet that provides information about the presence status of the users in the system.
* The information may be provided in XML format or in graphical mode. Use the <b>type</b>
* parameter to specify the type of information to get. Possible values are <b>image</b> and
* <b>xml</b>. If no type was defined then an image representation is assumed.<p>
* <p/>
* The request <b>MUST</b> include the <b>jid</b> parameter. This parameter will be used
* to locate the local user in the server. If this parameter is missing from the request then
* an error will be logged and nothing will be returned.
*
* @author Gaston Dombiak
*/
public class PresenceStatusServlet extends HttpServlet {
private PresencePlugin plugin;
private XMLPresenceProvider xmlProvider;
private ImagePresenceProvider imageProvider;
byte available[];
byte away[];
byte chat[];
byte dnd[];
byte offline[];
byte xa[];
public void init(ServletConfig servletConfig) throws ServletException {
super.init(servletConfig);
plugin =
(PresencePlugin) XMPPServer.getInstance().getPluginManager().getPlugin("presence");
xmlProvider = new XMLPresenceProvider();
imageProvider = new ImagePresenceProvider(this);
available = loadResource("/images/user-green-16x16.gif");
away = loadResource("/images/user-yellow-16x16.gif");
chat = loadResource("/images/user-green-16x16.gif");
dnd = loadResource("/images/user-red-16x16.gif");
offline = loadResource("/images/user-clear-16x16.gif");
xa = loadResource("/images/user-yellow-16x16.gif");
// Exclude this servlet from requering the user to login
AuthCheckFilter.addExclude("presence/status");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String sender = request.getParameter("req_jid");
String jid = request.getParameter("jid");
String type = request.getParameter("type");
type = type == null ? "image" : type;
try {
Presence presence = plugin.getPresence(sender, jid);
if ("image".equals(type)) {
imageProvider.sendInfo(request, response, presence);
}
else if ("xml".equals(type)) {
xmlProvider.sendInfo(request, response, presence);
}
else {
Log.warn("The presence servlet received an invalid request of type: " + type);
// TODO Do something
}
}
catch (UserNotFoundException e) {
if ("image".equals(type)) {
imageProvider.sendUserNotFound(request, response);
}
else if ("xml".equals(type)) {
xmlProvider.sendUserNotFound(request, response);
}
else {
Log.warn("The presence servlet received an invalid request of type: " + type);
// TODO Do something
}
}
catch (IllegalArgumentException e) {
if ("image".equals(type)) {
imageProvider.sendUserNotFound(request, response);
}
else if ("xml".equals(type)) {
xmlProvider.sendUserNotFound(request, response);
}
else {
Log.warn("The presence servlet received an invalid request of type: " + type);
// TODO Do something
}
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
public void destroy() {
super.destroy();
available = null;
away = null;
chat = null;
dnd = null;
offline = null;
xa = null;
// Release the excluded URL
AuthCheckFilter.removeExclude("presence/status");
}
private byte[] loadResource(String path) {
ServletContext context = getServletContext();
InputStream in = context.getResourceAsStream(path);
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
for (int i = in.read(); i > -1; i = in.read()) {
out.write(i);
}
}
catch (IOException e) {
Log.error("error loading:" + path);
}
return out.toByteArray();
}
}
/**
* $RCSfile$
* $Revision: 1680 $
* $Date: 2005-07-22 17:49:46 -0300 (Fri, 22 Jul 2005) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.plugin.presence;
import org.jivesoftware.wildfire.XMPPServer;
import org.jivesoftware.wildfire.user.User;
import org.jivesoftware.wildfire.user.UserNotFoundException;
import org.xmpp.packet.JID;
import org.xmpp.packet.PacketError;
import org.xmpp.packet.Presence;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* The XMLPresenceProvider provides information about the users presence in XML format.
* The returned XML will include the last known presence of the user. If the user is offline
* then the unavailable presence will be recreated with the last known presence status.
*
* @author Gaston Dombiak
*/
class XMLPresenceProvider extends PresenceInfoProvider {
public void sendInfo(HttpServletRequest request, HttpServletResponse response,
Presence presence) throws IOException {
response.setContentType("text/xml");
PrintWriter out = response.getWriter();
if (presence == null) {
// Recreate the unavailable presence with the last known status
JID targetJID = new JID(request.getParameter("jid"));
presence = new Presence(Presence.Type.unavailable);
XMPPServer server = XMPPServer.getInstance();
try {
User user = server.getUserManager().getUser(targetJID.getNode());
String status = server.getPresenceManager().getLastPresenceStatus(user);
if (status != null) {
presence.setStatus(status);
}
}
catch (UserNotFoundException e) {}
presence.setFrom(targetJID);
}
out.println(presence.toXML());
out.flush();
}
public void sendUserNotFound(HttpServletRequest request, HttpServletResponse response)
throws IOException {
response.setContentType("text/xml");
PrintWriter out = response.getWriter();
// Send a forbidden presence
Presence presence = new Presence();
presence.setError(PacketError.Condition.forbidden);
try {
presence.setFrom(new JID(request.getParameter("jid")));
}
catch (Exception e) {}
try {
presence.setTo(new JID(request.getParameter("req_jid")));
}
catch (Exception e) {}
out.println(presence.toXML());
out.flush();
}
}
package org.jivesoftware.wildfire.plugin;
import com.sun.msv.reader.util.GrammarLoader;
import com.sun.msv.reader.util.IgnoreController;
import com.sun.msv.verifier.DocumentDeclaration;
import com.sun.msv.verifier.Verifier;
import org.apache.commons.fileupload.FileItem;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.dom4j.io.SAXWriter;
import org.jivesoftware.util.Log;
import org.xml.sax.ContentHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXParseException;
import java.io.IOException;
import java.net.URL;
import javax.xml.parsers.SAXParserFactory;
public class UserSchemaValidator {
private Document doc;
private String schema;
UserSchemaValidator(FileItem usersFile, String schemaFile) throws DocumentException, IOException {
SAXReader reader = new SAXReader();
doc = reader.read(usersFile.getInputStream());
URL schemaURL = this.getClass().getClassLoader().getResource(schemaFile);
schema = schemaURL.toExternalForm();
}
boolean validate() {
try {
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
saxFactory.setNamespaceAware(true);
DocumentDeclaration docDeclaration = GrammarLoader.loadVGM(schema, new IgnoreController() {
public void error(Locator[] locations,
String message,
Exception exception) {
Log.error("ERROR: " + message);
}
public void error(Locator[] locations, String message) {
Log.error("WARNING: " + message);
}
}, saxFactory);
ValidatorErrorHandler validatorErrorHandler = new ValidatorErrorHandler();
Verifier verifier = new Verifier(docDeclaration, validatorErrorHandler);
SAXWriter writer = new SAXWriter((ContentHandler) verifier);
writer.setErrorHandler(validatorErrorHandler);
writer.write(doc);
if (verifier.isValid()) {
return true;
} else {
Log.error(doc.getName() + " is invalid.");
return false;
}
} catch (Exception e) {
Log.error(e);
return false;
}
}
private class ValidatorErrorHandler implements ErrorHandler {
public void error(SAXParseException e) {
Log.error("ERROR:" + e);
}
public void fatalError(SAXParseException e) {
Log.error("Fatal:" + e);
}
public void warning(SAXParseException e) {
Log.error("Warning:" + e);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment