From 5cacf94ecca5b45ffdaba0d85506d64117643fd8 Mon Sep 17 00:00:00 2001 From: steckbrief Date: Sun, 12 Nov 2017 14:22:01 +0100 Subject: Initial commit --- .classpath | 23 ++++ .gitignore | 3 + .project | 17 +++ build.xml | 45 +++++++ libs/3rdParty/jxmpp-core-0.5.0.jar | Bin 0 -> 25250 bytes libs/3rdParty/jxmpp-jid-0.5.0.jar | Bin 0 -> 23565 bytes libs/3rdParty/jxmpp-util-cache-0.5.0.jar | Bin 0 -> 7896 bytes libs/3rdParty/libidn-1.15.jar | Bin 0 -> 111731 bytes libs/3rdParty/minidns-core-0.2.4.jar | Bin 0 -> 129232 bytes libs/3rdParty/minidns-dnssec-0.2.4.jar | Bin 0 -> 52065 bytes libs/3rdParty/minidns-hla-0.2.4.jar | Bin 0 -> 7268 bytes libs/3rdParty/minidns-iterative-resolver-0.2.4.jar | Bin 0 -> 18979 bytes libs/3rdParty/smack/smack-core-4.2.1.jar | Bin 0 -> 356202 bytes libs/3rdParty/smack/smack-experimental-4.2.1.jar | Bin 0 -> 279488 bytes libs/3rdParty/smack/smack-extensions-4.2.1.jar | Bin 0 -> 702466 bytes libs/3rdParty/smack/smack-im-4.2.1.jar | Bin 0 -> 71650 bytes libs/3rdParty/smack/smack-java7-4.2.1.jar | Bin 0 -> 21621 bytes .../smack/smack-resolver-minidns-4.2.1.jar | Bin 0 -> 7936 bytes libs/3rdParty/smack/smack-sasl-javax-4.2.1.jar | Bin 0 -> 8656 bytes libs/3rdParty/smack/smack-tcp-4.2.1.jar | Bin 0 -> 59695 bytes libs/3rdParty/xmlpull-1.1.3.1.jar | Bin 0 -> 7188 bytes libs/3rdParty/xpp3_min-1.1.4c.jar | Bin 0 -> 24956 bytes .../thedevstack/xmpp/mamloader/MamLoadClient.java | 121 ++++++++++++++++++ src/de/thedevstack/xmpp/mamloader/MamLoader.java | 135 +++++++++++++++++++++ src/de/thedevstack/xmpp/mamloader/SSLHelper.java | 46 +++++++ 25 files changed, 390 insertions(+) create mode 100644 .classpath create mode 100644 .gitignore create mode 100644 .project create mode 100644 build.xml create mode 100644 libs/3rdParty/jxmpp-core-0.5.0.jar create mode 100644 libs/3rdParty/jxmpp-jid-0.5.0.jar create mode 100644 libs/3rdParty/jxmpp-util-cache-0.5.0.jar create mode 100644 libs/3rdParty/libidn-1.15.jar create mode 100644 libs/3rdParty/minidns-core-0.2.4.jar create mode 100644 libs/3rdParty/minidns-dnssec-0.2.4.jar create mode 100644 libs/3rdParty/minidns-hla-0.2.4.jar create mode 100644 libs/3rdParty/minidns-iterative-resolver-0.2.4.jar create mode 100644 libs/3rdParty/smack/smack-core-4.2.1.jar create mode 100644 libs/3rdParty/smack/smack-experimental-4.2.1.jar create mode 100644 libs/3rdParty/smack/smack-extensions-4.2.1.jar create mode 100644 libs/3rdParty/smack/smack-im-4.2.1.jar create mode 100644 libs/3rdParty/smack/smack-java7-4.2.1.jar create mode 100644 libs/3rdParty/smack/smack-resolver-minidns-4.2.1.jar create mode 100644 libs/3rdParty/smack/smack-sasl-javax-4.2.1.jar create mode 100644 libs/3rdParty/smack/smack-tcp-4.2.1.jar create mode 100644 libs/3rdParty/xmlpull-1.1.3.1.jar create mode 100644 libs/3rdParty/xpp3_min-1.1.4c.jar create mode 100644 src/de/thedevstack/xmpp/mamloader/MamLoadClient.java create mode 100644 src/de/thedevstack/xmpp/mamloader/MamLoader.java create mode 100644 src/de/thedevstack/xmpp/mamloader/SSLHelper.java diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..4a08052 --- /dev/null +++ b/.classpath @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84960ac --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +bin +.settings +dist diff --git a/.project b/.project new file mode 100644 index 0000000..b8d3538 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + MamHistoryLoader + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..fab966f --- /dev/null +++ b/build.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libs/3rdParty/jxmpp-core-0.5.0.jar b/libs/3rdParty/jxmpp-core-0.5.0.jar new file mode 100644 index 0000000..ce5f193 Binary files /dev/null and b/libs/3rdParty/jxmpp-core-0.5.0.jar differ diff --git a/libs/3rdParty/jxmpp-jid-0.5.0.jar b/libs/3rdParty/jxmpp-jid-0.5.0.jar new file mode 100644 index 0000000..e65dee7 Binary files /dev/null and b/libs/3rdParty/jxmpp-jid-0.5.0.jar differ diff --git a/libs/3rdParty/jxmpp-util-cache-0.5.0.jar b/libs/3rdParty/jxmpp-util-cache-0.5.0.jar new file mode 100644 index 0000000..724629a Binary files /dev/null and b/libs/3rdParty/jxmpp-util-cache-0.5.0.jar differ diff --git a/libs/3rdParty/libidn-1.15.jar b/libs/3rdParty/libidn-1.15.jar new file mode 100644 index 0000000..79a44f9 Binary files /dev/null and b/libs/3rdParty/libidn-1.15.jar differ diff --git a/libs/3rdParty/minidns-core-0.2.4.jar b/libs/3rdParty/minidns-core-0.2.4.jar new file mode 100644 index 0000000..bed0382 Binary files /dev/null and b/libs/3rdParty/minidns-core-0.2.4.jar differ diff --git a/libs/3rdParty/minidns-dnssec-0.2.4.jar b/libs/3rdParty/minidns-dnssec-0.2.4.jar new file mode 100644 index 0000000..85436bb Binary files /dev/null and b/libs/3rdParty/minidns-dnssec-0.2.4.jar differ diff --git a/libs/3rdParty/minidns-hla-0.2.4.jar b/libs/3rdParty/minidns-hla-0.2.4.jar new file mode 100644 index 0000000..9f7ec99 Binary files /dev/null and b/libs/3rdParty/minidns-hla-0.2.4.jar differ diff --git a/libs/3rdParty/minidns-iterative-resolver-0.2.4.jar b/libs/3rdParty/minidns-iterative-resolver-0.2.4.jar new file mode 100644 index 0000000..176fa04 Binary files /dev/null and b/libs/3rdParty/minidns-iterative-resolver-0.2.4.jar differ diff --git a/libs/3rdParty/smack/smack-core-4.2.1.jar b/libs/3rdParty/smack/smack-core-4.2.1.jar new file mode 100644 index 0000000..8026a4f Binary files /dev/null and b/libs/3rdParty/smack/smack-core-4.2.1.jar differ diff --git a/libs/3rdParty/smack/smack-experimental-4.2.1.jar b/libs/3rdParty/smack/smack-experimental-4.2.1.jar new file mode 100644 index 0000000..2949d80 Binary files /dev/null and b/libs/3rdParty/smack/smack-experimental-4.2.1.jar differ diff --git a/libs/3rdParty/smack/smack-extensions-4.2.1.jar b/libs/3rdParty/smack/smack-extensions-4.2.1.jar new file mode 100644 index 0000000..858bbd0 Binary files /dev/null and b/libs/3rdParty/smack/smack-extensions-4.2.1.jar differ diff --git a/libs/3rdParty/smack/smack-im-4.2.1.jar b/libs/3rdParty/smack/smack-im-4.2.1.jar new file mode 100644 index 0000000..6e9c61a Binary files /dev/null and b/libs/3rdParty/smack/smack-im-4.2.1.jar differ diff --git a/libs/3rdParty/smack/smack-java7-4.2.1.jar b/libs/3rdParty/smack/smack-java7-4.2.1.jar new file mode 100644 index 0000000..15f12b3 Binary files /dev/null and b/libs/3rdParty/smack/smack-java7-4.2.1.jar differ diff --git a/libs/3rdParty/smack/smack-resolver-minidns-4.2.1.jar b/libs/3rdParty/smack/smack-resolver-minidns-4.2.1.jar new file mode 100644 index 0000000..788dc91 Binary files /dev/null and b/libs/3rdParty/smack/smack-resolver-minidns-4.2.1.jar differ diff --git a/libs/3rdParty/smack/smack-sasl-javax-4.2.1.jar b/libs/3rdParty/smack/smack-sasl-javax-4.2.1.jar new file mode 100644 index 0000000..54295bc Binary files /dev/null and b/libs/3rdParty/smack/smack-sasl-javax-4.2.1.jar differ diff --git a/libs/3rdParty/smack/smack-tcp-4.2.1.jar b/libs/3rdParty/smack/smack-tcp-4.2.1.jar new file mode 100644 index 0000000..b09eed4 Binary files /dev/null and b/libs/3rdParty/smack/smack-tcp-4.2.1.jar differ diff --git a/libs/3rdParty/xmlpull-1.1.3.1.jar b/libs/3rdParty/xmlpull-1.1.3.1.jar new file mode 100644 index 0000000..cbc149d Binary files /dev/null and b/libs/3rdParty/xmlpull-1.1.3.1.jar differ diff --git a/libs/3rdParty/xpp3_min-1.1.4c.jar b/libs/3rdParty/xpp3_min-1.1.4c.jar new file mode 100644 index 0000000..813a9a8 Binary files /dev/null and b/libs/3rdParty/xpp3_min-1.1.4c.jar differ diff --git a/src/de/thedevstack/xmpp/mamloader/MamLoadClient.java b/src/de/thedevstack/xmpp/mamloader/MamLoadClient.java new file mode 100644 index 0000000..66e8969 --- /dev/null +++ b/src/de/thedevstack/xmpp/mamloader/MamLoadClient.java @@ -0,0 +1,121 @@ +package de.thedevstack.xmpp.mamloader; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +import org.jivesoftware.smack.AbstractXMPPConnection; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.SmackException.NoResponseException; +import org.jivesoftware.smack.SmackException.NotConnectedException; +import org.jivesoftware.smack.SmackException.NotLoggedInException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.XMPPException.XMPPErrorException; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.tcp.XMPPTCPConnection; +import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; +import org.jivesoftware.smackx.forward.packet.Forwarded; +import org.jivesoftware.smackx.mam.MamManager; +import org.jivesoftware.smackx.mam.MamManager.MamQueryResult; +import org.jxmpp.jid.BareJid; +import org.jxmpp.jid.Jid; +import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; + +public class MamLoadClient { + private static final int LIMIT_PER_REQUEST = 50; + private AbstractXMPPConnection connection; + private MamManager mamManager; + private boolean debug; + + public MamLoadClient(boolean debug) { + this.debug = debug; + } + + public void connectAndLogin(String username, String password) throws SmackException, IOException, XMPPException, InterruptedException { + BareJid userJid = JidCreate.bareFrom(username); + this.connectAndLogin(userJid.getLocalpartOrThrow().toString(), password, userJid.getDomain().toString()); + } + + private void connectAndLogin(String username, String password, String host) throws SmackException, IOException, XMPPException, InterruptedException { + XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder() + .setUsernameAndPassword(username, password) + .setXmppDomain(host) + .setHost(host) + .setDebuggerEnabled(this.debug) + //.setCustomSSLContext(SSLHelper.createNaiveSSLContext()) + .setResource("MAMLoader_" + UUID.randomUUID()) + .setSendPresence(false) + .build(); + connection = new XMPPTCPConnection(config); + connection.connect(); + connection.login(); + + mamManager = MamManager.getInstanceFor(connection); + } + + public void disconnect() { + this.connection.disconnect(); + } + + public List loadHistory(String jid) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException { + return this.loadHistory(jid, null, null); + } + + public List loadHistory(String jid, Date start) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException { + return this.loadHistory(jid, start, null); + } + + public List loadHistory(String jid, Date start, Date end) throws XmppStringprepException, NoResponseException, XMPPErrorException, NotConnectedException, NotLoggedInException, InterruptedException { + List allMessages = new ArrayList<>(); + if (mamManager.isSupported()) { + Jid withJid = JidCreate.bareFrom(jid); + MamQueryResult archive = mamManager.queryArchive(null, start, end, withJid, null); + allMessages.addAll(archive.forwardedMessages); + while (!archive.mamFin.isComplete()) { + archive = mamManager.pageNext(archive, LIMIT_PER_REQUEST); + allMessages.addAll(archive.forwardedMessages); + } + + allMessages = this.filterAndSort(allMessages); + } + + return allMessages; + } + + public List loadHistory(String jid, int limit) throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException, NotLoggedInException, XmppStringprepException { + List allMessages = new ArrayList<>(); + if (mamManager.isSupported()) { + Jid withJid = JidCreate.bareFrom(jid); + MamQueryResult archive = mamManager.mostRecentPage(withJid, LIMIT_PER_REQUEST); + + allMessages.addAll(archive.forwardedMessages); + while (!archive.mamFin.isComplete() && limit > allMessages.size()) { + int requestLimit = limit - allMessages.size(); + archive = mamManager.pagePrevious(archive, (requestLimit < LIMIT_PER_REQUEST ? requestLimit : LIMIT_PER_REQUEST)); + allMessages.addAll(archive.forwardedMessages); + } + + allMessages = this.filterAndSort(allMessages); + } + + return allMessages; + } + + private List filterAndSort(List messages) { + return messages.stream() + .filter(forwarded -> forwarded.getForwardedStanza() instanceof Message + && ((Message)forwarded.getForwardedStanza()).getBody() != null) + .sorted(new Comparator() { + @Override + public int compare(Forwarded o1, Forwarded o2) { + return o1.getDelayInformation().getStamp().compareTo(o2.getDelayInformation().getStamp()); + } + }) + .collect(Collectors.toList()); + } +} diff --git a/src/de/thedevstack/xmpp/mamloader/MamLoader.java b/src/de/thedevstack/xmpp/mamloader/MamLoader.java new file mode 100644 index 0000000..f60c91a --- /dev/null +++ b/src/de/thedevstack/xmpp/mamloader/MamLoader.java @@ -0,0 +1,135 @@ +package de.thedevstack.xmpp.mamloader; + +import java.io.BufferedReader; +import java.io.Console; +import java.io.IOException; +import java.io.InputStreamReader; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.Stanza; +import org.jivesoftware.smackx.forward.packet.Forwarded; + +public class MamLoader { + private static final SimpleDateFormat SDF = new SimpleDateFormat("dd.MM.YYYY HH:mm:ss"); + private static final SimpleDateFormat INPUT = new SimpleDateFormat("dd.MM.YYYY"); + + public static void main(String[] args) throws InterruptedException, SmackException, IOException, XMPPException { + if (2 > args.length) { + System.err.println("Your JID and the JID of your chatpartner is needed."); + System.exit(1); + } + String myjid = args[0]; + String jid = args[1]; + String password; + boolean debug = false; + Date start = null; + Date end = null; + int limit = -1; + + for (int i = 2; i < args.length; i++) { + switch (args[i]) { + case "-debug": + debug = true; + break; + case "-from": + start = parseDate(args[++i]); + break; + case "-to": + end = parseDate(args[++i]); + break; + case "-limit": + limit = Integer.parseInt(args[++i]); + break; + } + } + + if (null != end && null == start) { + System.err.println("End without start not supported."); + System.exit(1); + } else if (null != start && -1 < limit) { + System.err.println("Limit not supported if start date is given."); + System.exit(1); + } else if (null == jid || null == myjid) { + System.err.println("Your JID and the JID of your chatpartner is needed."); + System.exit(1); + } + + Console console = System.console(); + if (null == console) { + System.out.println("Testenvironment!"); + System.out.println("Warning: Password will be shown."); + System.out.print("Password: "); + BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); + password = reader.readLine(); + } else { + password = String.valueOf(console.readPassword("Password: ")); + } + + System.out.println("Loading history for chats with " + jid); + MamLoadClient mlc = new MamLoadClient(debug); + try { + mlc.connectAndLogin(myjid, password); +// mlc.loadHistory(jid, Date.from(LocalDate.of(2017, 11, 8).atStartOfDay().toInstant(ZoneOffset.UTC)), Date.from(LocalDate.of(2017, 11, 9).atStartOfDay().toInstant(ZoneOffset.UTC))); +// mlc.loadHistory(jid); + List messages = null; + + if (start == null && -1 == limit) { + messages = mlc.loadHistory(jid); + } else if (start == null && -1 < limit) { + messages = mlc.loadHistory(jid, limit); + } else if (start != null && end == null) { + messages = mlc.loadHistory(jid, start); + } else { + messages = mlc.loadHistory(jid, start, end); + } + + + System.out.println(messages.size() + " messages found"); + printMessagesWithBody(messages, jid); + } finally { + mlc.disconnect(); + } + } + + private static Date parseDate(String dateToParse) { + try { + return INPUT.parse(dateToParse); + } catch (ParseException e) { + System.err.println("Could not parse date: " + dateToParse); + System.err.println("Needed format: dd.MM.YYYY"); + System.exit(1); + + return null; + } + } + + private static void printMessagesWithBody(List messages, String withJid) { + for (Forwarded f : messages) { + Stanza stanza = f.getForwardedStanza(); + if (stanza instanceof Message) { + StringBuilder sb = new StringBuilder(); + Message message = (Message) stanza; + + if (null != message.getBody()) { + if (withJid.equals(message.getFrom().asBareJid().toString())) { + sb.append("<"); + } else { + sb.append(">"); + } + sb.append(" "); + sb.append(SDF.format(f.getDelayInformation().getStamp())); + sb.append(": "); + sb.append(message.getBody()); + System.out.println(sb.toString()); + } + } + } + } + +} diff --git a/src/de/thedevstack/xmpp/mamloader/SSLHelper.java b/src/de/thedevstack/xmpp/mamloader/SSLHelper.java new file mode 100644 index 0000000..8108f2c --- /dev/null +++ b/src/de/thedevstack/xmpp/mamloader/SSLHelper.java @@ -0,0 +1,46 @@ +package de.thedevstack.xmpp.mamloader; + +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +public final class SSLHelper { + + + public static final SSLContext createNaiveSSLContext() { + SSLContext sslContext = null; + try { + sslContext = SSLContext.getInstance("TLS"); + // Create a trust manager that does not validate certificate chains + TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { + + @Override + public X509Certificate[] getAcceptedIssuers() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + System.out.println(arg0[0].getSubjectDN()); + } + + @Override + public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { + System.out.println(arg0[0].getSubjectDN()); + } + } }; + sslContext.init(null, trustAllCerts, new SecureRandom()); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return sslContext; + } +} -- cgit v1.2.3