private void sendOfflineMessage(JID receipient, OfflineMessage offlineMessage) {
   Element offlineInfo = offlineMessage.addChildElement("offline", NAMESPACE);
   offlineInfo
       .addElement("item")
       .addAttribute("node", XMPPDateTimeFormat.format(offlineMessage.getCreationDate()));
   routingTable.routePacket(receipient, offlineMessage, true);
 }
  public Iterator<DiscoItem> getItems(String name, String node, JID senderJID) {
    // Mark that offline messages shouldn't be sent when the user becomes available
    stopOfflineFlooding(senderJID);
    List<DiscoItem> answer = new ArrayList<DiscoItem>();
    for (OfflineMessage offlineMessage : messageStore.getMessages(senderJID.getNode(), false)) {
      answer.add(
          new DiscoItem(
              senderJID.asBareJID(),
              offlineMessage.getFrom().toString(),
              XMPPDateTimeFormat.format(offlineMessage.getCreationDate()),
              null));
    }

    return answer.iterator();
  }
  @Override
  public IQ handleIQ(IQ packet) throws UnauthorizedException {
    IQ reply = IQ.createResultIQ(packet);
    Element offlineRequest = packet.getChildElement();

    JID from = packet.getFrom();
    if (offlineRequest.element("purge") != null) {
      // User requested to delete all offline messages
      messageStore.deleteMessages(from.getNode());
    } else if (offlineRequest.element("fetch") != null) {
      // Mark that offline messages shouldn't be sent when the user becomes available
      stopOfflineFlooding(from);
      // User requested to receive all offline messages
      for (OfflineMessage offlineMessage : messageStore.getMessages(from.getNode(), false)) {
        sendOfflineMessage(from, offlineMessage);
      }
    } else {
      for (Iterator it = offlineRequest.elementIterator("item"); it.hasNext(); ) {
        Element item = (Element) it.next();
        Date creationDate = null;
        try {
          creationDate = xmppDateTime.parseString(item.attributeValue("node"));
        } catch (ParseException e) {
          Log.error("Error parsing date", e);
        }
        if ("view".equals(item.attributeValue("action"))) {
          // User requested to receive specific message
          OfflineMessage offlineMsg = messageStore.getMessage(from.getNode(), creationDate);
          if (offlineMsg != null) {
            sendOfflineMessage(from, offlineMsg);
          }
        } else if ("remove".equals(item.attributeValue("action"))) {
          // User requested to delete specific message
          if (messageStore.getMessage(from.getNode(), creationDate) != null) {
            messageStore.deleteMessage(from.getNode(), creationDate);
          } else {
            // If the requester is authorized but the node does not exist, the server MUST return a
            // <item-not-found/> error.
            reply.setError(PacketError.Condition.item_not_found);
          }
        }
      }
    }
    return reply;
  }
예제 #4
0
 /**
  * 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;
 }
예제 #5
0
  private void populate(Element copy, Date delay, JID delayFrom) {

    copy.setQName(QName.get("message", "jabber:client"));

    for (Object element : copy.elements()) {
      if (element instanceof Element) {
        Element el = (Element) element;
        // Only set the "jabber:client" namespace if the namespace is empty (otherwise the resulting
        // xml would look like <body xmlns=""/>)
        if ("".equals(el.getNamespace().getStringValue())) {
          el.setQName(QName.get(el.getName(), "jabber:client"));
        }
      }
    }
    if (delay != null) {
      Element delayInfo = element.addElement("delay", "urn:xmpp:delay");
      delayInfo.addAttribute("stamp", XMPPDateTimeFormat.format(delay));
      if (delayFrom != null) {
        // Set the Full JID as the "from" attribute
        delayInfo.addAttribute("from", delayFrom.toString());
      }
    }
    element.add(copy);
  }
예제 #6
0
  /**
   * 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. &#12;)
          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;
  }