/** * Remove the roster item from the sender's roster (and possibly the recipient's). Actual roster * removal is done in the removeItem(Roster,RosterItem) method. * * @param roster The sender's roster. * @param sender The JID of the sender of the removal request * @param item The removal item element */ private void removeItem( org.jivesoftware.openfire.roster.Roster roster, JID sender, org.xmpp.packet.Roster.Item item) throws SharedGroupException { JID recipient = item.getJID(); // Remove recipient from the sender's roster roster.deleteRosterItem(item.getJID(), true); // Forward set packet to the subscriber if (localServer.isLocal(recipient)) { // Recipient is local so let's handle it here try { Roster recipientRoster = userManager.getUser(recipient.getNode()).getRoster(); recipientRoster.deleteRosterItem(sender, true); } catch (UserNotFoundException e) { // Do nothing } } else { // Recipient is remote so we just forward the packet to them String serverDomain = localServer.getServerInfo().getXMPPDomain(); // Check if the recipient may be hosted by this server if (!recipient.getDomain().contains(serverDomain)) { // TODO Implete when s2s is implemented } else { Packet removePacket = createRemoveForward(sender, recipient); router.route(removePacket); } } }
public void initialize(XMPPServer server) { super.initialize(server); messageStrategy = server.getOfflineMessageStrategy(); routingTable = server.getRoutingTable(); sessionManager = server.getSessionManager(); serverName = server.getServerInfo().getName(); }
/** * Forwards the received message to the list of users defined in the property * <b>xmpp.forward.admins</b>. The property may include bare JIDs or just usernames separated by * commas or white spaces. When using bare JIDs the target user may belong to a remote server. * * <p>If the property <b>xmpp.forward.admins</b> was not defined then the message will be sent to * all the users allowed to enter the admin console. * * @param packet the message to forward. */ private void sendMessageToAdmins(Message packet) { String jids = JiveGlobals.getProperty("xmpp.forward.admins"); if (jids != null && jids.trim().length() > 0) { // Forward the message to the users specified in the "xmpp.forward.admins" property StringTokenizer tokenizer = new StringTokenizer(jids, ", "); while (tokenizer.hasMoreTokens()) { String username = tokenizer.nextToken(); Message forward = packet.createCopy(); if (username.contains("@")) { // Use the specified bare JID address as the target address forward.setTo(username); } else { forward.setTo(username + "@" + serverName); } route(forward); } } else { // Forward the message to the users allowed to log into the admin console for (JID jid : XMPPServer.getInstance().getAdmins()) { Message forward = packet.createCopy(); forward.setTo(jid); route(forward); } } }
/** * The packet is a typical 'set' or 'get' update targeted at the server. Notice that the set could * be a roster removal in which case we have to generate a local roster removal update as well as * a new roster removal to send to the the roster item's owner. * * @param packet The packet that triggered this update * @return Either a response to the roster update or null if the packet is corrupt and the session * was closed down */ private IQ manageRoster(org.xmpp.packet.Roster packet) throws UnauthorizedException, UserAlreadyExistsException, SharedGroupException { IQ returnPacket = null; JID sender = packet.getFrom(); IQ.Type type = packet.getType(); try { if ((sender.getNode() == null || !RosterManager.isRosterServiceEnabled() || !userManager.isRegisteredUser(sender.getNode())) && IQ.Type.get == type) { // If anonymous user asks for his roster or roster service is disabled then // return an empty roster IQ reply = IQ.createResultIQ(packet); reply.setChildElement("query", "jabber:iq:roster"); return reply; } if (!localServer.isLocal(sender)) { // Sender belongs to a remote server so discard this IQ request Log.warn("Discarding IQ roster packet of remote user: " + packet); return null; } Roster cachedRoster = userManager.getUser(sender.getNode()).getRoster(); if (IQ.Type.get == type) { returnPacket = cachedRoster.getReset(); returnPacket.setType(IQ.Type.result); returnPacket.setTo(sender); returnPacket.setID(packet.getID()); // Force delivery of the response because we need to trigger // a presence probe from all contacts deliverer.deliver(returnPacket); returnPacket = null; } else if (IQ.Type.set == type) { for (org.xmpp.packet.Roster.Item item : packet.getItems()) { if (item.getSubscription() == org.xmpp.packet.Roster.Subscription.remove) { removeItem(cachedRoster, packet.getFrom(), item); } else { if (cachedRoster.isRosterItem(item.getJID())) { // existing item RosterItem cachedItem = cachedRoster.getRosterItem(item.getJID()); cachedItem.setAsCopyOf(item); cachedRoster.updateRosterItem(cachedItem); } else { // new item cachedRoster.createRosterItem(item); } } } returnPacket = IQ.createResultIQ(packet); } } catch (UserNotFoundException e) { throw new UnauthorizedException(e); } return returnPacket; }
/** * Adds a message to this message store. Messages will be stored and made available for later * delivery. * * @param message the message to store. */ public void addMessage(Message message) { if (message == null) { return; } if (!shouldStoreMessage(message)) { return; } JID recipient = message.getTo(); String username = recipient.getNode(); // If the username is null (such as when an anonymous user), don't store. if (username == null || !UserManager.getInstance().isRegisteredUser(recipient)) { return; } else if (!XMPPServer.getInstance() .getServerInfo() .getXMPPDomain() .equals(recipient.getDomain())) { // Do not store messages sent to users of remote servers return; } long messageID = SequenceManager.nextID(JiveConstants.OFFLINE); // Get the message in XML format. String msgXML = message.getElement().asXML(); Connection con = null; PreparedStatement pstmt = null; try { con = DbConnectionManager.getConnection(); pstmt = con.prepareStatement(INSERT_OFFLINE); pstmt.setString(1, username); pstmt.setLong(2, messageID); pstmt.setString(3, StringUtils.dateToMillis(new java.util.Date())); pstmt.setInt(4, msgXML.length()); pstmt.setString(5, msgXML); pstmt.executeUpdate(); } catch (Exception e) { Log.error(LocaleUtils.getLocalizedString("admin.error"), e); } finally { DbConnectionManager.closeConnection(pstmt, con); } // Update the cached size if it exists. if (sizeCache.containsKey(username)) { int size = sizeCache.get(username); size += msgXML.length(); sizeCache.put(username, size); } }
/** * Returns the offline message of the specified user with the given creation date. The returned * message will NOT be deleted from the database. * * @param username the username of the user who's message you'd like to receive. * @param creationDate the date when the offline message was stored in the database. * @return the offline message of the specified user with the given creation stamp. */ public OfflineMessage getMessage(String username, Date creationDate) { OfflineMessage message = null; Connection con = null; PreparedStatement pstmt = null; ResultSet rs = null; SAXReader xmlReader = null; try { // Get a sax reader from the pool xmlReader = xmlReaders.take(); con = DbConnectionManager.getConnection(); pstmt = con.prepareStatement(LOAD_OFFLINE_MESSAGE); pstmt.setString(1, username); pstmt.setString(2, StringUtils.dateToMillis(creationDate)); rs = pstmt.executeQuery(); while (rs.next()) { String msgXML = rs.getString(1); message = new OfflineMessage( creationDate, xmlReader.read(new StringReader(msgXML)).getRootElement()); // Add a delayed delivery (XEP-0203) element to the message. Element delay = message.addChildElement("delay", "urn:xmpp:delay"); delay.addAttribute("from", XMPPServer.getInstance().getServerInfo().getXMPPDomain()); delay.addAttribute("stamp", XMPPDateTimeFormat.format(creationDate)); } } catch (Exception e) { Log.error( "Error retrieving offline messages of username: "******" creationDate: " + creationDate, e); } finally { // Return the sax reader to the pool if (xmlReader != null) { xmlReaders.add(xmlReader); } DbConnectionManager.closeConnection(rs, pstmt, con); } return message; }
public void initialize(XMPPServer server) { super.initialize(server); localServer = server; userManager = server.getUserManager(); router = server.getPacketRouter(); }
/** * Returns the instance of <tt>OfflineMessageStore</tt> being used by the XMPPServer. * * @return the instance of <tt>OfflineMessageStore</tt> being used by the XMPPServer. */ public static OfflineMessageStore getInstance() { return XMPPServer.getInstance().getOfflineMessageStore(); }
/** * Returns a Collection of all messages in the store for a user. Messages may be deleted after * being selected from the database depending on the delete param. * * @param username the username of the user who's messages you'd like to receive. * @param delete true if the offline messages should be deleted. * @return An iterator of packets containing all offline messages. */ public Collection<OfflineMessage> getMessages(String username, boolean delete) { List<OfflineMessage> messages = new ArrayList<>(); SAXReader xmlReader = null; Connection con = null; PreparedStatement pstmt = null; ResultSet rs = null; try { // Get a sax reader from the pool xmlReader = xmlReaders.take(); con = DbConnectionManager.getConnection(); pstmt = con.prepareStatement(LOAD_OFFLINE); pstmt.setString(1, username); rs = pstmt.executeQuery(); while (rs.next()) { String msgXML = rs.getString(1); Date creationDate = new Date(Long.parseLong(rs.getString(2).trim())); OfflineMessage message; try { message = new OfflineMessage( creationDate, xmlReader.read(new StringReader(msgXML)).getRootElement()); } catch (DocumentException e) { // Try again after removing invalid XML chars (e.g. ) Matcher matcher = pattern.matcher(msgXML); if (matcher.find()) { msgXML = matcher.replaceAll(""); } try { message = new OfflineMessage( creationDate, xmlReader.read(new StringReader(msgXML)).getRootElement()); } catch (DocumentException de) { Log.error("Failed to route packet (offline message): " + msgXML, de); continue; // skip and process remaining offline messages } } // if there is already a delay stamp, we shouldn't add another. Element delaytest = message.getChildElement("delay", "urn:xmpp:delay"); if (delaytest == null) { // Add a delayed delivery (XEP-0203) element to the message. Element delay = message.addChildElement("delay", "urn:xmpp:delay"); delay.addAttribute("from", XMPPServer.getInstance().getServerInfo().getXMPPDomain()); delay.addAttribute("stamp", XMPPDateTimeFormat.format(creationDate)); } messages.add(message); } // Check if the offline messages loaded should be deleted, and that there are // messages to delete. if (delete && !messages.isEmpty()) { PreparedStatement pstmt2 = null; try { pstmt2 = con.prepareStatement(DELETE_OFFLINE); pstmt2.setString(1, username); pstmt2.executeUpdate(); removeUsernameFromSizeCache(username); } catch (Exception e) { Log.error("Error deleting offline messages of username: "******"Error retrieving offline messages of username: " + username, e); } finally { DbConnectionManager.closeConnection(rs, pstmt, con); // Return the sax reader to the pool if (xmlReader != null) { xmlReaders.add(xmlReader); } } return messages; }