xmpp_sync/src/main/java/de/vanitasvitae/sync_client/Main.java

244 lines
11 KiB
Java
Raw Normal View History

2017-08-11 13:47:54 +02:00
package de.vanitasvitae.sync_client;
import java.io.IOException;
2017-08-15 17:44:02 +02:00
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.HashMap;
2017-08-11 13:47:54 +02:00
import java.util.List;
import java.util.Scanner;
2017-08-15 17:44:02 +02:00
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
2017-08-11 13:47:54 +02:00
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.roster.Roster;
import org.jivesoftware.smack.roster.RosterEntry;
2017-08-15 17:44:02 +02:00
import org.jivesoftware.smackx.omemo.OmemoFingerprint;
import org.jivesoftware.smackx.omemo.OmemoManager;
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
2017-08-11 13:47:54 +02:00
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.FullJid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.stringprep.XmppStringprepException;
public class Main {
private static Options prepareOptions() {
Options options = new Options();
2017-08-17 22:48:51 +02:00
Option username = Option.builder("u").longOpt("username").required().argName("user@server.tld").hasArg().desc("Barejid of the XMPP account.").build();
Option password = Option.builder("p").longOpt("password").required().argName("swordfish").hasArg().desc("Password of the XMPP account.").build();
Option debug = Option.builder("d").longOpt("debug").desc("Print debug messages to the console.").build();
Option directory = Option.builder("D").longOpt("directory").hasArg().required().desc("Directory which will be synced.").build();
Option master = Option.builder("m").longOpt("master").desc("Start in master mode. When this flag is missing, the client will be started in slave mode.").build();
Option help = Option.builder("h").longOpt("help").desc("Display this help text.").build();
2017-08-11 13:47:54 +02:00
options.addOption(username);
options.addOption(password);
options.addOption(debug);
options.addOption(directory);
options.addOption(master);
2017-08-15 17:53:50 +02:00
options.addOption(help);
2017-08-11 13:47:54 +02:00
return options;
}
2017-08-15 17:44:02 +02:00
public static Slave slave(String username, String password, String dir) throws IOException, InterruptedException,
XMPPException, SmackException, NoSuchPaddingException, CorruptedOmemoKeyException, InvalidKeyException,
NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, NoSuchProviderException,
InvalidAlgorithmParameterException {
2017-08-11 13:47:54 +02:00
return new Slave(username, password, dir);
}
2017-08-15 17:44:02 +02:00
public static Master master(String username, String password, String dir) throws IOException, InterruptedException,
XMPPException, SmackException, CorruptedOmemoKeyException, InvalidKeyException, NoSuchAlgorithmException,
NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, NoSuchProviderException,
InvalidAlgorithmParameterException {
2017-08-11 13:47:54 +02:00
return new Master(username, password, dir);
}
public static void main(String[] args) throws Exception {
Options options = prepareOptions();
HelpFormatter formatter = new HelpFormatter();
CommandLineParser parser = new DefaultParser();
CommandLine cmd = null;
try {
cmd = parser.parse(options, args);
} catch (ParseException e) {
formatter.printHelp("client", options, true);
return;
}
2017-08-15 17:53:50 +02:00
if (cmd.hasOption('h')) {
formatter.printHelp("client", options, true);
return;
}
2017-08-11 13:47:54 +02:00
String username = cmd.getOptionValue('u');
String password = cmd.getOptionValue('p');
String dir = cmd.getOptionValue('D');
if (cmd.hasOption('d')) {
SmackConfiguration.DEBUG = true;
}
Client client;
if (cmd.hasOption('m')) {
client = master(username, password, dir);
} else {
client = slave(username, password, dir);
}
client.login();
System.out.println("Ready!");
Scanner scanner = new Scanner(System.in);
outerloop: while (true) {
String line = scanner.nextLine();
if (line == null || line.isEmpty()) {
continue;
}
String[] split = line.split(" ");
if (split.length == 0) {
continue;
}
Roster roster = Roster.getInstanceFor(client.connection);
2017-08-15 17:44:02 +02:00
OmemoManager omemoManager = OmemoManager.getInstanceFor(client.connection);
2017-08-11 13:47:54 +02:00
switch (split[0]) {
case "/add":
if (split.length != 2) {
System.out.println("Usage: /add user@server.tld");
for (RosterEntry r : roster.getEntries()) {
System.out.println(r.getJid());
}
continue outerloop;
}
try {
BareJid bareJid = getJid(split[1]);
roster.createEntry(getJid(split[1]), bareJid.getLocalpartOrNull().toString(), null);
} catch (XmppStringprepException e) {
System.out.println("Illegal BareJid.");
}
break;
case "/sync":
if (split.length != 2) {
System.out.println("Usage: /sync user@server.tld");
for (FullJid fullJid : client.remotes) {
System.out.println(fullJid.toString());
}
continue outerloop;
}
List<Presence> presences = roster.getPresences(getJid(split[1]));
if (presences.size() == 0) {
System.out.println("No device online!");
continue outerloop;
} else if (presences.size() == 1) {
client.addRemote(presences.get(0).getFrom().asFullJidOrThrow());
} else {
while (true) {
System.out.println("Please select a resource:");
for (int i = 0; i < presences.size(); i++) {
System.out.println(i + " " + presences.get(i).getFrom().asFullJidOrThrow().toString());
}
int selection = Integer.parseInt(scanner.nextLine());
if (selection < 0 || selection >= presences.size()) {
System.out.println("Invalid selection.");
continue;
}
client.addRemote(presences.get(selection).getFrom().asFullJidOrThrow());
continue outerloop;
}
}
break;
2017-08-15 17:44:02 +02:00
case "/trust":
if (split.length != 2) {
System.out.println("Usage: /trust user@server.tld");
continue outerloop;
}
BareJid jid = getJid(split[1]);
omemoManager.requestDeviceListUpdateFor(jid);
omemoManager.requestDeviceListUpdateFor(client.connection.getUser().asBareJid());
HashMap<OmemoDevice, OmemoFingerprint> theirFPs = omemoManager.getActiveFingerprints(jid);
HashMap<OmemoDevice, OmemoFingerprint> ourFPs = omemoManager.getActiveFingerprints(client.connection.getUser().asBareJid());
System.out.println("Their fingerprints: <deviceId>: <fingerprint>: <trusted>");
for (OmemoDevice d : theirFPs.keySet()) {
OmemoFingerprint f = theirFPs.get(d);
System.out.println(d.getDeviceId() + ": " + f + ": " + omemoManager.isTrustedOmemoIdentity(d, f));
System.out.println("Trust? (y/n)");
String a = scanner.nextLine();
if (a.isEmpty()) {
continue;
} else if (a.toLowerCase().equals("y")) {
omemoManager.trustOmemoIdentity(d, f);
System.out.println("Trusted.");
} else {
omemoManager.distrustOmemoIdentity(d, f);
System.out.println("Distrusted.");
}
}
System.out.println("Our fingerprints: <deviceId>: <fingerprint>: <trusted>");
for (OmemoDevice d : ourFPs.keySet()) {
OmemoFingerprint f = ourFPs.get(d);
System.out.println(d.getDeviceId() + ": " + f + ": " + omemoManager.isTrustedOmemoIdentity(d, f));
System.out.println("Trust? (y/n)");
String a = scanner.nextLine();
if (a.isEmpty()) {
continue;
} else if (a.toLowerCase().equals("y")) {
omemoManager.trustOmemoIdentity(d, f);
System.out.println("Trusted.");
} else {
omemoManager.distrustOmemoIdentity(d, f);
System.out.println("Distrusted.");
}
}
break;
2017-08-15 17:53:50 +02:00
case "/help":
System.out.println("Available commands: \n" +
"/add <user@server.tld>: Add user to roster, or display current roster.\n" +
"/sync <user@server.tld>: Add a users device to synced devices or display currently synced devices.\n" +
"/trust user@sever.tld: Trust a users OMEMO identities.\n" +
"/help: Show this help text.\n" +
"/quit: Quit the application.");
break;
2017-08-11 13:47:54 +02:00
case "/quit":
((AbstractXMPPConnection) client.connection).disconnect(new Presence(Presence.Type.unavailable, "Shutdown", 100, Presence.Mode.away));
break outerloop;
}
}
scanner.close();
System.exit(0);
}
public static BareJid getJid(String string) throws XmppStringprepException {
return JidCreate.bareFrom(string);
}
}