@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;
  }
  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();
  }
  public DataForm getExtendedInfo(String name, String node, JID senderJID) {
    // Mark that offline messages shouldn't be sent when the user becomes available
    stopOfflineFlooding(senderJID);

    final DataForm dataForm = new DataForm(DataForm.Type.result);

    final FormField field1 = dataForm.addField();
    field1.setVariable("FORM_TYPE");
    field1.setType(FormField.Type.hidden);
    field1.addValue(NAMESPACE);

    final FormField field2 = dataForm.addField();
    field2.setVariable("number_of_messages");
    field2.addValue(String.valueOf(messageStore.getMessages(senderJID.getNode(), false).size()));

    return dataForm;
  }