Skip to content

Adding support for private MUC messages to MAM #144

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Dec 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions changelog.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,17 @@ <h1>
<ul>
<li>[<a href='https://issues.igniterealtime.org/browse/OF-2157'>OF-2157</a>] - SequenceManager generated IDs are unreliable whilst clustering.</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/19'>Issue #19</a>] - Monitoring / Archive plugin fails to reconstruct archived stanza</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/133'>Issue #133</a>] - Allow PMs to be returned when querying MUC archives</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/137'>Issue #137</a>] - MUC messages duplicated as one-on-one messages</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/138'>Issue #138</a>] - Stanzas not always stored for one-to-one messages whilst clustered</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/139'>Issue #139</a>] - Reduce code complexity</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/141'>Issue #141</a>] - Make Archiver configuration configurable</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/142'>Issue #142</a>] - Do not require plugin restart after config change</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/145'>Issue #145</a>] - Replace deprecated API usage</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/146'>Issue #146</a>] - Allow database used for MUC MAM to be configurable</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/147'>Issue #147</a>] - Allow how MUC PMs are stored to be configurable</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/148'>Issue #148</a>] - Database errors should cause an XMPP error</li>
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/152'>Issue #152</a>] - Update iText library to 7.1.13</li>
</ul>

<p><b>2.1.0</b> -- September 10, 2020</p>
Expand Down
2 changes: 1 addition & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<minServerVersion>4.4.0</minServerVersion>
<minJavaVersion>1.8</minJavaVersion>
<databaseKey>monitoring</databaseKey>
<databaseVersion>6</databaseVersion>
<databaseVersion>7</databaseVersion>

<adminconsole>
<tab id="tab-server">
Expand Down
13 changes: 9 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,15 @@
<version>8.4.0</version>
</dependency>
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<!-- NB. Later versions are available at com.itextpdf:itextpdf but require code changes -->
<version>2.0.8</version>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.1.13</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.orsonpdf</groupId>
<artifactId>orsonpdf</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.picocontainer</groupId>
Expand Down
10 changes: 6 additions & 4 deletions src/database/monitoring_db2.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

INSERT INTO ofVersion (name, version) VALUES ('monitoring', 6);
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 7);

CREATE TABLE ofConversation (
conversationID INTEGER NOT NULL,
Expand Down Expand Up @@ -34,17 +34,19 @@ CREATE TABLE ofMessageArchive (
toJIDResource VARCHAR(255) NULL,
sentDate BIGINT NOT NULL,
stanza LONG VARCHAR NULL,
body LONG VARCHAR
body LONG VARCHAR NULL,
isPMforJID VARCHAR(1024) NULL
);
CREATE INDEX ofMessageArchive_con_idx ON ofMessageArchive (conversationID);
CREATE INDEX ofMessageArchive_fromjid_idx ON ofMessageArchive (fromJID);
CREATE INDEX ofMessageArchive_tojid_idx ON ofMessageArchive (toJID);
CREATE INDEX ofMessageArchive_sent_idx ON ofMessageArchive (sentDate);
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);

CREATE TABLE ofRRDs (
id VARCHAR(100) NOT NULL,
updatedDate BIGINT NOT NULL,
bytes BLOB,
updatedDate BIGINT NOT NULL,
bytes BLOB NULL,
CONSTRAINT ofRRDs_pk PRIMARY KEY (id)
);

8 changes: 5 additions & 3 deletions src/database/monitoring_hsqldb.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

INSERT INTO ofVersion (name, version) VALUES ('monitoring', 6);
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 7);

CREATE TABLE ofConversation (
conversationID BIGINT NOT NULL,
Expand Down Expand Up @@ -34,17 +34,19 @@ CREATE TABLE ofMessageArchive (
toJIDResource VARCHAR(255) NULL,
sentDate BIGINT NOT NULL,
stanza LONGVARCHAR NULL,
body LONGVARCHAR
body LONGVARCHAR NULL,
isPMforJID VARCHAR(1024) NULL
);
CREATE INDEX ofMessageArchive_con_idx ON ofMessageArchive (conversationID);
CREATE INDEX ofMessageArchive_fromjid_idx ON ofMessageArchive (fromJID);
CREATE INDEX ofMessageArchive_tojid_idx ON ofMessageArchive (toJID);
CREATE INDEX ofMessageArchive_sent_idx ON ofMessageArchive (sentDate);
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);

CREATE TABLE ofRRDs (
id VARCHAR(100) NOT NULL,
updatedDate BIGINT NOT NULL,
bytes BLOB NULL,
bytes BLOB NULL,
CONSTRAINT ofRRDs_pk PRIMARY KEY (id)
);

8 changes: 5 additions & 3 deletions src/database/monitoring_mysql.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

INSERT INTO ofVersion (name, version) VALUES ('monitoring', 6);
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 7);

CREATE TABLE ofConversation (
conversationID BIGINT NOT NULL,
Expand Down Expand Up @@ -34,11 +34,13 @@ CREATE TABLE ofMessageArchive (
toJIDResource VARCHAR(100) NULL,
sentDate BIGINT NOT NULL,
stanza TEXT NULL,
body TEXT,
body TEXT NULL,
isPMforJID VARCHAR(255) NOT NULL,
INDEX ofMessageArchive_con_idx (conversationID),
INDEX ofMessageArchive_fromjid_idx (fromJID),
INDEX ofMessageArchive_tojid_idx (toJID),
INDEX ofMessageArchive_sent_idx (sentDate)
INDEX ofMessageArchive_sent_idx (sentDate),
INDEX ofMessageArchive_pm_idx (isPMforJID)
);

CREATE TABLE ofRRDs (
Expand Down
6 changes: 4 additions & 2 deletions src/database/monitoring_oracle.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

INSERT INTO ofVersion (name, version) VALUES ('monitoring', 6);
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 7);

CREATE TABLE ofConversation (
conversationID INTEGER NOT NULL,
Expand Down Expand Up @@ -34,12 +34,14 @@ CREATE TABLE ofMessageArchive (
toJIDResource VARCHAR2(255) NULL,
sentDate INTEGER NOT NULL,
stanza CLOB NULL,
body CLOB
body CLOB NULL,
isPMforJID VARCHAR2(1024) NULL
);
CREATE INDEX ofMessageArchive_con_idx ON ofMessageArchive (conversationID);
CREATE INDEX ofMessageArchive_fromjid_idx ON ofMessageArchive (fromJID);
CREATE INDEX ofMessageArchive_tojid_idx ON ofMessageArchive (toJID);
CREATE INDEX ofMessageArchive_sent_idx ON ofMessageArchive (sentDate);
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);

CREATE TABLE ofRRDs (
id VARCHAR2(100) NOT NULL,
Expand Down
6 changes: 4 additions & 2 deletions src/database/monitoring_postgresql.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

INSERT INTO ofVersion (name, version) VALUES ('monitoring', 6);
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 7);

CREATE TABLE ofConversation (
conversationID INTEGER NOT NULL,
Expand Down Expand Up @@ -34,12 +34,14 @@ CREATE TABLE ofMessageArchive (
toJIDResource VARCHAR(1024) NULL,
sentDate BIGINT NOT NULL,
stanza TEXT NULL,
body TEXT
body TEXT NULL,
isPMforJID VARCHAR(1024) NULL
);
CREATE INDEX ofMessageArchive_con_idx ON ofMessageArchive (conversationID);
CREATE INDEX ofMessageArchive_fromjid_idx ON ofMessageArchive (fromJID);
CREATE INDEX ofMessageArchive_tojid_idx ON ofMessageArchive (toJID);
CREATE INDEX ofMessageArchive_sent_idx ON ofMessageArchive (sentDate);
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);

CREATE TABLE ofRRDs (
id VARCHAR(100) NOT NULL,
Expand Down
6 changes: 4 additions & 2 deletions src/database/monitoring_sqlserver.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

INSERT INTO ofVersion (name, version) VALUES ('monitoring', 6);
INSERT INTO ofVersion (name, version) VALUES ('monitoring', 7);

CREATE TABLE ofConversation (
conversationID BIGINT NOT NULL,
Expand Down Expand Up @@ -34,12 +34,14 @@ CREATE TABLE ofMessageArchive (
toJIDResource NVARCHAR(1024) NULL,
sentDate BIGINT NOT NULL,
stanza NVARCHAR(MAX) NULL,
body NVARCHAR(MAX)
body NVARCHAR(MAX) NULL,
isPMforJID NVARCHAR(1024) NULL
);
CREATE INDEX ofMessageArchive_con_idx ON ofMessageArchive (conversationID);
CREATE INDEX ofMessageArchive_fromjid_idx ON ofMessageArchive (fromJID);
CREATE INDEX ofMessageArchive_tojid_idx ON ofMessageArchive (toJID);
CREATE INDEX ofMessageArchive_sent_idx ON ofMessageArchive (sentDate);
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);

CREATE TABLE ofRRDs (
id NVARCHAR(100) NOT NULL,
Expand Down
5 changes: 5 additions & 0 deletions src/database/upgrade/7/monitoring_db2.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ALTER TABLE ofMessageArchive ADD COLUMN isPMforJID VARCHAR(1024) NULL;
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);

-- Update database version
UPDATE ofVersion SET version = 7 WHERE name = 'monitoring';
5 changes: 5 additions & 0 deletions src/database/upgrade/7/monitoring_hsqldb.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ALTER TABLE ofMessageArchive ADD COLUMN isPMforJID VARCHAR(1024) NULL;
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);

-- Update database version
UPDATE ofVersion SET version = 7 WHERE name = 'monitoring';
5 changes: 5 additions & 0 deletions src/database/upgrade/7/monitoring_mysql.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ALTER TABLE ofMessageArchive ADD COLUMN isPMforJID VARCHAR(255) NULL;
ALTER TABLE ofMessageArchive ADD INDEX ofMessageArchive_pm_idx (isPMforJID);

-- Update database version
UPDATE ofVersion SET version = 7 WHERE name = 'monitoring';
5 changes: 5 additions & 0 deletions src/database/upgrade/7/monitoring_oracle.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ALTER TABLE ofMessageArchive ADD isPMforJID VARCHAR2(1024) NULL;
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);

-- Update database version
UPDATE ofVersion SET version = 7 WHERE name = 'monitoring';
5 changes: 5 additions & 0 deletions src/database/upgrade/7/monitoring_postgresql.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ALTER TABLE ofMessageArchive ADD COLUMN isPMforJID VARCHAR(1024) NULL;
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);

-- Update database version
UPDATE ofVersion SET version = 7 WHERE name = 'monitoring';
5 changes: 5 additions & 0 deletions src/database/upgrade/7/monitoring_sqlserver.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
ALTER TABLE ofMessageArchive ADD isPMforJID NVARCHAR(1024) NULL;
CREATE INDEX ofMessageArchive_pm_idx ON ofMessageArchive (isPMforJID);

-- Update database version
UPDATE ofVersion SET version = 7 WHERE name = 'monitoring';
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.reucon.openfire.plugin.archive;

import com.reucon.openfire.plugin.archive.impl.DataRetrievalException;
import com.reucon.openfire.plugin.archive.model.ArchivedMessage;
import com.reucon.openfire.plugin.archive.model.Conversation;
import com.reucon.openfire.plugin.archive.xep0059.XmppResultSet;
Expand Down Expand Up @@ -29,16 +30,17 @@ public interface PersistenceManager
/**
* Searches for messages.
*
* @param startDate earliest start date of the message to find or <code>null</code> for any.
* @param endDate latest end date of the message to find or <code>null</code> for any.
* @param owner bare jid of the owner of the message to find or <code>null</code> for any.
* @param with jid of the communication partner or <code>null</code> for any. This is either
* the jid of another XMPP user or the jid of a group chat.
* @param query A query string, typically representing keywords or a partial text, or <code>null</code>.
* @param useStableID true if MAM2 or another protocol is used that depends on XEP-0359.
* @param startDate earliest start date of the message to find or <code>null</code> for any.
* @param endDate latest end date of the message to find or <code>null</code> for any.
* @param archiveOwner bare jid of the owner of the archive in which to find messages or <code>null</code> for any.
* @param messageOwner bare jid of the owner of the message to find or <code>null</code> for any.
* @param with jid of the communication partner or <code>null</code> for any. This is either
* the jid of another XMPP user or the jid of a group chat.
* @param query A query string, typically representing keywords or a partial text, or <code>null</code>.
* @param useStableID true if MAM2 or another protocol is used that depends on XEP-0359.
* @return the messages that matched search criteria (possibly empty, never null).
*/
Collection<ArchivedMessage> findMessages( Date startDate, Date endDate, JID owner, JID with, String query, XmppResultSet xmppResultSet, boolean useStableID) throws NotFoundException;
Collection<ArchivedMessage> findMessages( Date startDate, Date endDate, JID archiveOwner, JID messageOwner, JID with, String query, XmppResultSet xmppResultSet, boolean useStableID) throws NotFoundException, DataRetrievalException;

/**
* Returns the conversation with the given owner, with and start time including participants and messages.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2020 Ignite Realtime Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.reucon.openfire.plugin.archive.impl;

/**
* Used when data could not be retrieved from persistent storage.
*/
public class DataRetrievalException extends Exception
{
public DataRetrievalException() {
super();
}

public DataRetrievalException(String message) {
super(message);
}

public DataRetrievalException(String message, Throwable cause) {
super(message, cause);
}

public DataRetrievalException(Throwable cause) {
super(cause);
}

protected DataRetrievalException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import com.reucon.openfire.plugin.archive.model.ArchivedMessage.Direction;
import com.reucon.openfire.plugin.archive.model.Conversation;
import com.reucon.openfire.plugin.archive.model.Participant;
import com.reucon.openfire.plugin.archive.util.StanzaIDUtil;
import com.reucon.openfire.plugin.archive.xep0059.XmppResultSet;
import org.dom4j.*;
import org.jivesoftware.database.DbConnectionManager;
Expand All @@ -15,7 +14,6 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.JID;
import org.xmpp.packet.Message;

import java.sql.Connection;
import java.sql.PreparedStatement;
Expand All @@ -24,7 +22,7 @@
import java.util.*;

/**
* Manages database persistence.
* Manages database interactions to work with 'personal archives' for messages.
*/
public class JdbcPersistenceManager implements PersistenceManager {
private static final Logger Log = LoggerFactory.getLogger( JdbcPersistenceManager.class );
Expand Down Expand Up @@ -277,8 +275,10 @@ private int bindConversationParameters(Date startDate, Date endDate, JID owner,
}

@Override
public Collection<ArchivedMessage> findMessages(Date startDate, Date endDate, JID owner, JID with, String query, XmppResultSet xmppResultSet, boolean useStableID) {

public Collection<ArchivedMessage> findMessages(Date startDate, Date endDate, JID owner, JID messageOwner, JID with, String query, XmppResultSet xmppResultSet, boolean useStableID) throws DataRetrievalException {
if ( !owner.equals(messageOwner)) {
throw new IllegalArgumentException("A personal archive can't be queried for messages of a different owner than the archive. Supplied archive owner: " + owner + ", supplied message owner: " + messageOwner);
}
Log.debug( "Finding messages of owner '{}' with start date '{}', end date '{}' with '{}' and resultset '{}', useStableId '{}'.", owner, startDate, endDate, with, xmppResultSet, useStableID );

if (startDate == null) {
Expand Down Expand Up @@ -467,7 +467,7 @@ public Conversation getConversation(JID owner, JID with, Date start) {
while (rs.next()) {
ArchivedMessage message;

message = extractMessage(rs);
message = extractMessage(owner, rs);
conversation.addMessage(message);
}
} catch (SQLException | DocumentException sqle) {
Expand Down Expand Up @@ -538,18 +538,17 @@ private Collection<Participant> extractParticipant(ResultSet rs) throws SQLExcep
return participants;
}

static ArchivedMessage extractMessage(ResultSet rs) throws SQLException, DocumentException {
static ArchivedMessage extractMessage(final JID owner, ResultSet rs) throws SQLException, DocumentException {
Date time = millisToDate(rs.getLong("sentDate"));
String body = rs.getString("body");
String stanza = rs.getString("stanza");
String bareJid = rs.getString("bareJID");
String fromJid = rs.getString("fromJID");
String fromJIDResource = rs.getString("fromJIDResource");
String toJid = rs.getString("toJID");
String toJIDResource = rs.getString("toJIDResource");
Long id = rs.getLong( "messageID" );

return asArchivedMessage( new JID(bareJid), fromJid, fromJIDResource, toJid, toJIDResource, time, body, stanza, id );
return asArchivedMessage( owner, fromJid, fromJIDResource, toJid, toJIDResource, time, body, stanza, id );
}

/**
Expand All @@ -566,7 +565,7 @@ public static ArchivedMessage getArchivedMessage( long messageId, JID owner )
ResultSet rs = null;
try {
connection = DbConnectionManager.getConnection();
final String query = "SELECT DISTINCT ofMessageArchive.fromJID, ofMessageArchive.fromJIDResource, ofMessageArchive.toJID, ofMessageArchive.toJIDResource, ofMessageArchive.sentDate, ofMessageArchive.body, ofMessageArchive.stanza, ofMessageArchive.messageID "
final String query = "SELECT ofMessageArchive.fromJID, ofMessageArchive.fromJIDResource, ofMessageArchive.toJID, ofMessageArchive.toJIDResource, ofMessageArchive.sentDate, ofMessageArchive.body, ofMessageArchive.stanza, ofMessageArchive.messageID "
+ "FROM ofMessageArchive "
+ "INNER JOIN ofConParticipant ON ofMessageArchive.conversationID = ofConParticipant.conversationID "
+ "WHERE (ofMessageArchive.stanza IS NOT NULL OR ofMessageArchive.body IS NOT NULL) "
Expand Down
Loading