2018-06-09 15:27:16 +02:00
import java.io.BufferedReader ;
2017-07-01 01:06:09 +02:00
import java.io.File ;
2018-06-09 15:27:16 +02:00
import java.io.FileNotFoundException ;
import java.io.FileOutputStream ;
import java.io.FileReader ;
import java.io.IOException ;
import java.io.PrintWriter ;
2017-07-01 01:06:09 +02:00
import java.util.ArrayList ;
import java.util.List ;
import java.util.Scanner ;
2017-04-22 21:17:23 +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.chat.Chat ;
import org.jivesoftware.smack.chat.ChatManager ;
import org.jivesoftware.smack.packet.Message ;
import org.jivesoftware.smack.packet.Presence ;
2018-01-17 14:36:03 +01:00
import org.jivesoftware.smack.packet.Stanza ;
2017-04-22 21:17:23 +02:00
import org.jivesoftware.smack.roster.Roster ;
import org.jivesoftware.smack.roster.RosterEntry ;
import org.jivesoftware.smack.tcp.XMPPTCPConnection ;
import org.jivesoftware.smackx.carbons.CarbonManager ;
2018-01-17 14:36:03 +01:00
import org.jivesoftware.smackx.carbons.packet.CarbonExtension ;
2017-04-22 21:17:23 +02:00
import org.jivesoftware.smackx.muc.MultiUserChat ;
import org.jivesoftware.smackx.muc.MultiUserChatException ;
import org.jivesoftware.smackx.muc.MultiUserChatManager ;
2017-05-08 15:28:01 +02:00
import org.jivesoftware.smackx.omemo.OmemoConfiguration ;
2017-04-22 21:17:23 +02:00
import org.jivesoftware.smackx.omemo.OmemoManager ;
2018-01-17 14:36:03 +01:00
import org.jivesoftware.smackx.omemo.OmemoMessage ;
2017-05-08 15:28:01 +02:00
import org.jivesoftware.smackx.omemo.exceptions.UndecidedOmemoIdentityException ;
2018-01-17 14:36:03 +01:00
import org.jivesoftware.smackx.omemo.internal.OmemoCachedDeviceList ;
2017-05-08 15:28:01 +02:00
import org.jivesoftware.smackx.omemo.internal.OmemoDevice ;
2017-04-22 21:17:23 +02:00
import org.jivesoftware.smackx.omemo.listener.OmemoMessageListener ;
import org.jivesoftware.smackx.omemo.listener.OmemoMucMessageListener ;
2018-01-17 14:36:03 +01:00
import org.jivesoftware.smackx.omemo.signal.SignalCachingOmemoStore ;
2017-04-22 21:17:23 +02:00
import org.jivesoftware.smackx.omemo.signal.SignalFileBasedOmemoStore ;
import org.jivesoftware.smackx.omemo.signal.SignalOmemoService ;
2018-01-17 14:36:03 +01:00
import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint ;
import org.jivesoftware.smackx.omemo.trust.OmemoTrustCallback ;
import org.jivesoftware.smackx.omemo.trust.TrustState ;
2017-07-01 01:06:09 +02:00
2017-05-08 15:28:01 +02:00
import org.jline.reader.EndOfFileException ;
import org.jline.reader.LineReader ;
import org.jline.reader.LineReaderBuilder ;
import org.jline.reader.UserInterruptException ;
import org.jline.terminal.Terminal ;
import org.jline.terminal.TerminalBuilder ;
2017-04-22 21:17:23 +02:00
import org.jxmpp.jid.BareJid ;
import org.jxmpp.jid.EntityBareJid ;
import org.jxmpp.jid.impl.JidCreate ;
import org.jxmpp.jid.parts.Resourcepart ;
import org.jxmpp.stringprep.XmppStringprepException ;
import org.whispersystems.libsignal.IdentityKey ;
/ * *
2018-06-09 20:12:05 +02:00
* Command Line OMEMO Chat Client .
* This client was developed for testing purposes . It can easily crash for unexpected inputs . Use with that in mind .
*
2017-04-22 21:17:23 +02:00
* Created by vanitas on 28 . 11 . 16 .
* /
public class Main {
private AbstractXMPPConnection connection ;
private OmemoManager omemoManager ;
2018-06-09 15:27:16 +02:00
private final static File storePath = new File ( " store " ) ;
2018-06-09 20:12:05 +02:00
private Main ( ) {
/ *
2017-04-22 21:17:23 +02:00
SmackConfiguration . DEBUG = true ;
/ * /
SmackConfiguration . DEBUG = false ;
//*/
2017-05-25 14:39:09 +02:00
OmemoConfiguration . setAddOmemoHintBody ( false ) ;
2017-04-22 21:17:23 +02:00
}
public void start ( ) throws Exception {
2017-04-23 12:11:11 +02:00
Terminal terminal = TerminalBuilder . terminal ( ) ;
LineReader reader = LineReaderBuilder . builder ( )
2017-05-08 15:28:01 +02:00
. terminal ( terminal )
. build ( ) ;
2017-04-23 12:11:11 +02:00
String prompt = " > " ;
2017-04-22 21:17:23 +02:00
Scanner scanner = new Scanner ( System . in ) ;
String jidname = null , password = null ;
while ( jidname = = null ) {
System . out . println ( " Enter username: " ) ;
jidname = scanner . nextLine ( ) ;
}
while ( password = = null ) {
System . out . println ( " Enter password: " ) ;
password = scanner . nextLine ( ) ;
}
connection = new XMPPTCPConnection ( jidname , password ) ;
2017-07-01 01:06:09 +02:00
SignalOmemoService . acknowledgeLicense ( ) ;
2017-05-11 22:17:49 +02:00
SignalOmemoService . setup ( ) ;
2018-01-17 14:36:03 +01:00
SignalOmemoService service = ( SignalOmemoService ) SignalOmemoService . getInstance ( ) ;
2018-06-09 15:27:16 +02:00
service . setOmemoStoreBackend ( new SignalCachingOmemoStore ( new SignalFileBasedOmemoStore ( storePath ) ) ) ;
2018-01-17 14:36:03 +01:00
2017-05-11 22:17:49 +02:00
omemoManager = OmemoManager . getInstanceFor ( connection ) ;
2018-01-17 14:36:03 +01:00
omemoManager . setTrustCallback ( new OmemoTrustCallback ( ) {
@Override
public TrustState getTrust ( OmemoDevice device , OmemoFingerprint fingerprint ) {
2018-06-09 15:27:16 +02:00
try {
return Main . this . getTrust ( omemoManager . getOwnDevice ( ) , device , fingerprint ) ;
} catch ( IOException e ) {
System . out . println ( " Could not get Trust of device " + device . toString ( ) + " : " + e . getMessage ( ) ) ;
return TrustState . undecided ;
}
2018-01-17 14:36:03 +01:00
}
@Override
public void setTrust ( OmemoDevice device , OmemoFingerprint fingerprint , TrustState state ) {
2018-06-09 15:27:16 +02:00
try {
Main . this . storeTrust ( omemoManager . getOwnDevice ( ) , device , fingerprint , state ) ;
} catch ( IOException e ) {
System . out . println ( " Could not set Trust of device " + device . toString ( ) + " : " + e . getMessage ( ) ) ;
}
2018-01-17 14:36:03 +01:00
}
} ) ;
2018-06-09 15:27:16 +02:00
connection . setReplyTimeout ( 10000 ) ;
2017-04-22 21:17:23 +02:00
connection = connection . connect ( ) ;
connection . login ( ) ;
2018-01-17 14:36:03 +01:00
omemoManager . initialize ( ) ;
2017-05-08 15:28:01 +02:00
2017-04-22 21:17:23 +02:00
System . out . println ( " Logged in. Begin setting up OMEMO... " ) ;
2017-05-11 22:17:49 +02:00
OmemoMessageListener messageListener = new OmemoMessageListener ( ) {
@Override
2018-01-17 14:36:03 +01:00
public void onOmemoMessageReceived ( Stanza stanza , OmemoMessage . Received received ) {
BareJid sender = stanza . getFrom ( ) . asBareJid ( ) ;
if ( received . isKeyTransportMessage ( ) ) {
return ;
}
String decryptedBody = received . getBody ( ) ;
2017-05-11 22:17:49 +02:00
if ( sender ! = null & & decryptedBody ! = null ) {
reader . callWidget ( LineReader . CLEAR ) ;
2018-01-17 14:36:03 +01:00
reader . getTerminal ( ) . writer ( ) . println ( " \ 033[34m " + sender + " : " + decryptedBody ) ;
2017-05-11 22:17:49 +02:00
reader . callWidget ( LineReader . REDRAW_LINE ) ;
reader . callWidget ( LineReader . REDISPLAY ) ;
reader . getTerminal ( ) . writer ( ) . flush ( ) ;
}
}
@Override
2018-01-17 14:36:03 +01:00
public void onOmemoCarbonCopyReceived ( CarbonExtension . Direction direction , Message carbonCopy , Message wrappingMessage , OmemoMessage . Received decryptedCarbonCopy ) {
2017-04-22 21:17:23 +02:00
}
} ;
2018-01-17 14:36:03 +01:00
OmemoMucMessageListener mucMessageListener = ( multiUserChat , stanza , received ) - > {
BareJid bareJid = received . getSenderDevice ( ) . getJid ( ) ;
if ( received . isKeyTransportMessage ( ) ) {
return ;
2017-05-11 22:17:49 +02:00
}
2018-01-17 14:36:03 +01:00
String s = received . getBody ( ) ;
if ( multiUserChat ! = null & & bareJid ! = null & & s ! = null ) {
2017-04-23 12:11:11 +02:00
reader . callWidget ( LineReader . CLEAR ) ;
2018-01-17 14:36:03 +01:00
reader . getTerminal ( ) . writer ( ) . println ( " \ 033[36m " + multiUserChat . getRoom ( ) + " : " + bareJid + " : " + s ) ;
2017-04-23 12:11:11 +02:00
reader . callWidget ( LineReader . REDRAW_LINE ) ;
reader . callWidget ( LineReader . REDISPLAY ) ;
reader . getTerminal ( ) . writer ( ) . flush ( ) ;
2017-04-22 21:17:23 +02:00
}
} ;
2018-06-09 20:12:05 +02:00
// Carbon Copies
2017-04-22 21:17:23 +02:00
CarbonManager . getInstanceFor ( connection ) . enableCarbons ( ) ;
omemoManager . addOmemoMessageListener ( messageListener ) ;
omemoManager . addOmemoMucMessageListener ( mucMessageListener ) ;
2018-06-09 20:12:05 +02:00
// Contact list
2017-04-22 21:17:23 +02:00
Roster roster = Roster . getInstanceFor ( connection ) ;
roster . setSubscriptionMode ( Roster . SubscriptionMode . accept_all ) ;
2018-06-09 20:12:05 +02:00
// Single Chats
2017-04-22 21:17:23 +02:00
ChatManager cm = ChatManager . getInstanceFor ( connection ) ;
cm . addChatListener ( ( chat , b ) - > chat . addMessageListener ( ( chat1 , message ) - > {
if ( message . getBody ( ) ! = null & & chat1 ! = null ) {
System . out . println ( " Message received: " + chat1 . getParticipant ( ) . toString ( ) + " : " + message . getBody ( ) ) ;
}
} ) ) ;
2018-06-09 20:12:05 +02:00
// Group Chats
2017-04-22 21:17:23 +02:00
MultiUserChatManager mucm = MultiUserChatManager . getInstanceFor ( connection ) ;
mucm . setAutoJoinOnReconnect ( true ) ;
mucm . addInvitationListener ( ( xmppConnection , multiUserChat , entityFullJid , s , s1 , message , invite ) - > {
try {
multiUserChat . join ( Resourcepart . from ( " OMEMO " ) ) ;
multiUserChat . addMessageListener ( message1 - > {
System . out . println ( " MUC: " + message1 . getFrom ( ) + " : " + message1 . getBody ( ) ) ;
} ) ;
System . out . println ( " Joined Room " + multiUserChat . getRoom ( ) . asBareJid ( ) . toString ( ) ) ;
} catch ( SmackException . NoResponseException | XMPPException . XMPPErrorException | InterruptedException | MultiUserChatException . NotAMucServiceException | SmackException . NotConnectedException | XmppStringprepException e ) {
e . printStackTrace ( ) ;
}
} ) ;
System . out . println ( " OMEMO setup complete. You can now start chatting. " ) ;
Chat current = null ;
boolean omemo = false ;
2018-06-09 20:12:05 +02:00
// Begin REPL
2017-04-23 12:11:11 +02:00
while ( true ) {
String line = null ;
try {
line = reader . readLine ( prompt ) ;
} catch ( UserInterruptException e ) {
// Ignore
} catch ( EndOfFileException e ) {
return ;
}
2017-04-22 21:17:23 +02:00
String [ ] split = line . split ( " " ) ;
2018-06-09 20:12:05 +02:00
// Send unencrypted chat message
2017-04-22 21:17:23 +02:00
if ( line . startsWith ( " /chat " ) ) {
String l = line . substring ( " /chat " . length ( ) ) ;
if ( l . length ( ) = = 0 ) {
System . out . println ( current ! = null ? current . getParticipant ( ) : " null " ) ;
} else {
String id = split [ 1 ] ;
BareJid jid = getJid ( id ) ;
if ( jid ! = null ) {
current = cm . createChat ( jid . asEntityJidIfPossible ( ) ) ;
current . sendMessage ( l . substring ( id . length ( ) + 1 ) ) ;
}
}
2018-06-09 20:12:05 +02:00
}
// Exit the client
else if ( line . startsWith ( " /quit " ) ) {
2017-04-22 21:17:23 +02:00
scanner . close ( ) ;
connection . disconnect ( new Presence ( Presence . Type . unavailable , " Smack is still alive :D " , 100 , Presence . Mode . away ) ) ;
break ;
2018-06-09 20:12:05 +02:00
}
// Add contacts
else if ( line . startsWith ( " /add " ) ) {
2017-04-22 21:17:23 +02:00
String jid = split . length = = 4 ? split [ 1 ] : null ;
if ( jid ! = null ) {
BareJid b = JidCreate . bareFrom ( jid ) ;
roster . createEntry ( b , split [ 2 ] , new String [ ] { split [ 3 ] } ) ;
} else {
System . out . println ( " Usage: /add jid@server nick group " ) ;
}
2018-06-09 20:12:05 +02:00
}
// Remove contact
else if ( line . startsWith ( " /remove " ) ) {
2017-04-22 21:17:23 +02:00
if ( split . length = = 2 ) {
BareJid b = getJid ( split [ 1 ] ) ;
roster . removeEntry ( roster . getEntry ( b ) ) ;
System . out . println ( " Removed contact from roster " ) ;
}
2018-06-09 20:12:05 +02:00
}
// List available contacts/groups or device list of selected contact
else if ( line . startsWith ( " /list " ) ) {
2017-04-22 21:17:23 +02:00
if ( split . length = = 1 ) {
for ( RosterEntry r : roster . getEntries ( ) ) {
System . out . println ( r . getName ( ) + " ( " + r . getJid ( ) + " ) Can I see? " + r . canSeeHisPresence ( ) + " . Can they see? " + r . canSeeMyPresence ( ) + " . Online? " + roster . getPresence ( r . getJid ( ) ) . isAvailable ( ) ) ;
}
for ( EntityBareJid r : mucm . getJoinedRooms ( ) ) {
System . out . println ( r . asBareJid ( ) . toString ( ) ) ;
}
2018-06-09 20:12:05 +02:00
}
// List presences of one contact, as well as OMEMO fingerprints
else {
2017-04-22 21:17:23 +02:00
BareJid jid = getJid ( split [ 1 ] ) ;
try {
List < Presence > presences = roster . getAllPresences ( jid ) ;
for ( Presence p : presences ) {
2018-01-17 14:36:03 +01:00
System . out . println ( p . getFrom ( ) ) ;
2017-04-22 21:17:23 +02:00
}
} catch ( Exception e ) { }
2017-04-23 23:46:44 +02:00
omemoManager . requestDeviceListUpdateFor ( jid ) ;
2018-01-17 14:36:03 +01:00
OmemoCachedDeviceList list = service . getOmemoStoreBackend ( ) . loadCachedDeviceList ( omemoManager . getOwnDevice ( ) , jid ) ;
2017-04-22 21:17:23 +02:00
if ( list = = null ) {
2018-01-17 14:36:03 +01:00
list = new OmemoCachedDeviceList ( ) ;
2017-04-22 21:17:23 +02:00
}
ArrayList < String > fps = new ArrayList < > ( ) ;
for ( int id : list . getActiveDevices ( ) ) {
OmemoDevice d = new OmemoDevice ( jid , id ) ;
2018-01-17 14:36:03 +01:00
IdentityKey idk = service . getOmemoStoreBackend ( ) . loadOmemoIdentityKey ( omemoManager . getOwnDevice ( ) , d ) ;
2017-04-22 21:17:23 +02:00
if ( idk = = null ) {
2017-05-25 14:39:09 +02:00
System . out . println ( " No identityKey for " + d ) ;
} else {
2018-01-17 14:36:03 +01:00
OmemoFingerprint fp = service . getOmemoStoreBackend ( ) . getFingerprint ( omemoManager . getOwnDevice ( ) , d ) ;
if ( fp ! = null ) {
fps . add ( fp . blocksOf8Chars ( ) ) ;
}
2017-04-22 21:17:23 +02:00
}
}
for ( int i = 0 ; i < fps . size ( ) ; i + + ) {
System . out . println ( i + " : " + fps . get ( i ) ) ;
}
}
2018-06-09 20:12:05 +02:00
}
// Make trust decisions for keys of a user
else if ( line . startsWith ( " /trust " ) ) {
2017-04-22 21:17:23 +02:00
if ( split . length = = 2 ) {
System . out . println ( " Usage: \ n0: Untrusted, 1: Trusted, otherwise: Undecided " ) ;
BareJid jid = getJid ( split [ 1 ] ) ;
2017-05-08 15:28:01 +02:00
if ( jid = = null ) {
continue ;
}
2018-01-17 14:36:03 +01:00
System . out . println ( jid ) ;
2017-05-08 15:28:01 +02:00
omemoManager . requestDeviceListUpdateFor ( jid ) ;
2018-01-17 14:36:03 +01:00
for ( OmemoDevice device : omemoManager . getDevicesOf ( jid ) ) {
OmemoFingerprint fp = omemoManager . getFingerprint ( device ) ;
if ( omemoManager . isDecidedOmemoIdentity ( device , fp ) ) {
if ( omemoManager . isTrustedOmemoIdentity ( device , fp ) ) {
2017-05-08 15:28:01 +02:00
System . out . println ( " Status: Trusted " ) ;
2017-04-22 21:17:23 +02:00
} else {
2017-05-08 15:28:01 +02:00
System . out . println ( " Status: Untrusted " ) ;
2017-04-22 21:17:23 +02:00
}
2017-05-08 15:28:01 +02:00
} else {
System . out . println ( " Status: Undecided " ) ;
}
2018-01-17 14:36:03 +01:00
System . out . println ( fp . blocksOf8Chars ( ) ) ;
2017-05-08 15:28:01 +02:00
String decision = scanner . nextLine ( ) ;
if ( decision . equals ( " 0 " ) ) {
2018-01-17 14:36:03 +01:00
omemoManager . distrustOmemoIdentity ( device , fp ) ;
2017-05-08 15:28:01 +02:00
System . out . println ( " Identity has been untrusted. " ) ;
} else if ( decision . equals ( " 1 " ) ) {
2018-01-17 14:36:03 +01:00
omemoManager . trustOmemoIdentity ( device , fp ) ;
2017-05-08 15:28:01 +02:00
System . out . println ( " Identity has been trusted. " ) ;
}
2018-01-17 14:36:03 +01:00
}
2017-04-22 21:17:23 +02:00
}
2018-06-09 20:12:05 +02:00
}
// Delete foreign OMEMO devices from own device list
else if ( line . startsWith ( " /purge " ) ) {
2018-01-17 14:36:03 +01:00
omemoManager . purgeDeviceList ( ) ;
2017-04-22 21:17:23 +02:00
System . out . println ( " Purge successful. " ) ;
2018-01-17 14:36:03 +01:00
// } else if(line.startsWith("/regenerate")) {
// omemoManager.regenerateIdentity();
// System.out.println("Regeneration successful.");
2018-06-09 20:12:05 +02:00
}
// Write encrypted OMEMO message to single chat
else if ( line . startsWith ( " /omemo " ) ) {
2017-04-22 21:17:23 +02:00
if ( split . length = = 1 ) {
} else {
BareJid recipient = getJid ( split [ 1 ] ) ;
if ( recipient ! = null ) {
String message = " " ;
for ( int i = 2 ; i < split . length ; i + + ) {
message + = split [ i ] + " " ;
}
2018-01-17 14:36:03 +01:00
OmemoMessage . Sent encrypted = null ;
2017-04-22 21:17:23 +02:00
try {
2017-05-25 14:39:09 +02:00
encrypted = omemoManager . encrypt ( recipient , message . trim ( ) ) ;
2017-04-22 21:17:23 +02:00
} catch ( UndecidedOmemoIdentityException e ) {
System . out . println ( " There are undecided identities: " ) ;
2018-01-17 14:36:03 +01:00
for ( OmemoDevice d : e . getUndecidedDevices ( ) ) {
2017-04-22 21:17:23 +02:00
System . out . println ( d . toString ( ) ) ;
}
2017-05-25 14:39:09 +02:00
}
if ( encrypted ! = null ) {
current = cm . createChat ( recipient . asEntityJidIfPossible ( ) ) ;
2018-01-17 14:36:03 +01:00
Message m = new Message ( ) ;
m . addExtension ( encrypted . getElement ( ) ) ;
current . sendMessage ( m ) ;
2017-04-22 21:17:23 +02:00
}
}
}
omemo = true ;
}
2018-06-09 20:12:05 +02:00
// Send encrypted OMEMO message to group chat
2017-04-22 21:17:23 +02:00
else if ( line . startsWith ( " /mucomemo " ) ) {
if ( split . length > = 3 ) {
BareJid mucJid = getJid ( split [ 1 ] ) ;
if ( mucJid ! = null ) {
String message = " " ;
for ( int i = 2 ; i < split . length ; i + + ) {
message + = split [ i ] + " " ;
}
MultiUserChat muc = mucm . getMultiUserChat ( mucJid . asEntityBareJidIfPossible ( ) ) ;
2018-01-17 14:36:03 +01:00
OmemoMessage . Sent encrypted = null ;
2017-05-25 14:39:09 +02:00
try {
encrypted = omemoManager . encrypt ( muc , message . trim ( ) ) ;
} catch ( UndecidedOmemoIdentityException e ) {
System . out . println ( " There are undecided identities: " ) ;
2018-01-17 14:36:03 +01:00
for ( OmemoDevice d : e . getUndecidedDevices ( ) ) {
2017-05-25 14:39:09 +02:00
System . out . println ( d . toString ( ) ) ;
}
}
if ( encrypted ! = null ) {
2018-01-17 14:36:03 +01:00
Message m = new Message ( ) ;
m . addExtension ( encrypted . getElement ( ) ) ;
muc . sendMessage ( m ) ;
2017-05-25 14:39:09 +02:00
}
2017-04-22 21:17:23 +02:00
}
}
2018-06-09 20:12:05 +02:00
}
// Display own fingerprint
else if ( line . startsWith ( " /fingerprint " ) ) {
2018-01-17 14:36:03 +01:00
OmemoFingerprint fingerprint = omemoManager . getOwnFingerprint ( ) ;
System . out . println ( fingerprint . blocksOf8Chars ( ) ) ;
2018-06-09 20:12:05 +02:00
}
// Display help text
else if ( line . startsWith ( " /help " ) ) {
2017-04-22 21:17:23 +02:00
if ( split . length = = 1 ) {
System . out . println ( " Available options: \ n " +
" /chat <Nickname/Jid> <Message>: Send a normal unencrypted chat message to a user. \ n " +
" /omemo <Nickname/Jid> <Message>: Send an OMEMO encrypted message to a user. \ n " +
" /mucomemo <MUC-Jid> <Message>: Send an OMEMO encrypted message to a group chat. \ n " +
" /list: List your roster. \ n " +
" /list <Nickname/Jid>: List all devices of a user. \ n " +
" /fingerprint: Show your OMEMO fingerprint. \ n " +
" /purge: Remove all other devices from your list of active devices. \ n " +
" /regenerate: Create a new OMEMO identity. \ n " +
" /add <jid> <Nickname> <group>: Add a new contact to your roster. \ n " +
" /remove <jid>: Remove a contact from your roster. \ n " +
" /quit: Quit the application. " ) ;
}
2018-01-17 14:36:03 +01:00
// } else if(line.startsWith("/mam")) {
// MamManager mamManager = MamManager.getInstanceFor(connection);
// MamManager.MamQueryResult result = mamManager.queryArchive(new Date(System.currentTimeMillis()-1000*60*60*24), new Date(System.currentTimeMillis()));
// for(ClearTextMessage d : omemoManager.decryptMamQueryResult(result)) {
// messageListener.onOmemoMessageReceived(d.getBody(), d.getOriginalMessage(), null, d.getMessageInformation());
// }
// System.out.println("Query finished");
2018-06-09 20:12:05 +02:00
}
// Send ratchet update message to repair/forward session with contact
else if ( line . startsWith ( " /ratchetUpdate " ) ) {
2017-05-25 14:39:09 +02:00
if ( split . length = = 2 ) {
BareJid jid = getJid ( split [ 1 ] ) ;
2018-01-17 14:36:03 +01:00
OmemoCachedDeviceList cachedDeviceList = service . getOmemoStoreBackend ( ) . loadCachedDeviceList ( omemoManager . getOwnDevice ( ) , jid ) ;
2017-05-25 14:39:09 +02:00
for ( int id : cachedDeviceList . getActiveDevices ( ) ) {
OmemoDevice d = new OmemoDevice ( jid , id ) ;
omemoManager . sendRatchetUpdateMessage ( d ) ;
}
}
2017-04-22 21:17:23 +02:00
}
2018-06-09 20:12:05 +02:00
// If no command is entered, assume chat with contact is still active -> send message
2017-04-23 19:45:18 +02:00
else {
2017-04-22 21:17:23 +02:00
if ( current ! = null ) {
if ( ! omemo ) {
current . sendMessage ( line ) ;
} else {
try {
2018-01-17 14:36:03 +01:00
OmemoMessage . Sent e = omemoManager . encrypt ( current . getParticipant ( ) . asEntityBareJid ( ) , line . trim ( ) ) ;
Message m = new Message ( ) ;
m . addExtension ( e . getElement ( ) ) ;
current . sendMessage ( m ) ;
2017-04-22 21:17:23 +02:00
} catch ( UndecidedOmemoIdentityException e ) {
System . out . println ( " There are undecided identities: " ) ;
2018-01-17 14:36:03 +01:00
for ( OmemoDevice d : e . getUndecidedDevices ( ) ) {
2017-04-22 21:17:23 +02:00
System . out . println ( d . toString ( ) ) ;
}
}
}
2018-06-09 20:12:05 +02:00
} else {
2017-04-22 21:17:23 +02:00
System . out . println ( " please open a chat " ) ;
2018-06-09 20:12:05 +02:00
}
2017-04-23 19:45:18 +02:00
}
2017-04-22 21:17:23 +02:00
}
}
public static void main ( String [ ] args ) {
try {
Main main = new Main ( ) ;
main . start ( ) ;
} catch ( Exception ignored ) {
ignored . printStackTrace ( ) ;
}
}
2018-06-09 20:12:05 +02:00
/ * *
* Translate Nick to JID .
*
* @param user Nick or Jid of a contact as String
* @return BareJid of the contact or null , if jid cannot be determined .
* /
private BareJid getJid ( String user ) {
2017-04-22 21:17:23 +02:00
Roster roster = Roster . getInstanceFor ( connection ) ;
RosterEntry r = null ;
for ( RosterEntry s : roster . getEntries ( ) ) {
if ( s . getName ( ) ! = null & & s . getName ( ) . equals ( user ) ) {
r = s ;
break ;
}
}
if ( r ! = null ) {
return r . getJid ( ) ;
} else {
try {
return JidCreate . bareFrom ( user ) ;
} catch ( XmppStringprepException e ) {
e . printStackTrace ( ) ;
return null ;
}
}
}
2018-06-09 15:27:16 +02:00
2018-06-09 20:12:05 +02:00
/ * *
* Store a trust decision in persistent storage .
* This particular method mimics the behaviour of the { @link SignalFileBasedOmemoStore } .
*
* @param userDevice our own OMEMO device
* @param contactsDevice OMEMO device of the contact in question
* @param fingerprint the contacts devices fingerprint
* @param trustState the new trust state .
*
* @throws IOException IO is dangerous ( we write to a file )
* /
private void storeTrust ( OmemoDevice userDevice , OmemoDevice contactsDevice , OmemoFingerprint fingerprint , TrustState trustState )
2018-06-09 15:27:16 +02:00
throws IOException {
File target = new File ( storePath , " OMEMO_Store " + File . separator +
userDevice . getJid ( ) . toString ( ) + File . separator +
userDevice . getDeviceId ( ) + File . separator +
" contacts " + File . separator +
contactsDevice . getJid ( ) . toString ( ) + File . separator +
contactsDevice . getDeviceId ( ) + File . separator +
" trust " ) ;
if ( ! target . exists ( ) ) {
target . getParentFile ( ) . mkdirs ( ) ;
target . createNewFile ( ) ;
}
try ( PrintWriter out = new PrintWriter ( target ) ) {
out . write ( fingerprint . toString ( ) + " " + trustState ) ;
} catch ( FileNotFoundException e ) {
throw new AssertionError ( e ) ;
}
}
2018-06-09 20:12:05 +02:00
/ * *
* Retrieves a trust decision from persistent storage .
* If no trust record was found , return undecided .
* If a trust record for that device with a different fingerprint was found , return untrusted .
* This particular method mimics the behaviour of the { @link SignalFileBasedOmemoStore } .
*
* @param userDevice our own OMEMO device
* @param contactsDevice OMEMO device of the contact in question
* @param fingerprint contacts devices fingerprint .
* @return trust state
*
* @throws IOException IO is dangerous ( we read from a file )
* /
private TrustState getTrust ( OmemoDevice userDevice , OmemoDevice contactsDevice , OmemoFingerprint fingerprint )
2018-06-09 15:27:16 +02:00
throws IOException {
File target = new File ( storePath , " OMEMO_Store " + File . separator +
userDevice . getJid ( ) . toString ( ) + File . separator +
userDevice . getDeviceId ( ) + File . separator +
" contacts " + File . separator +
contactsDevice . getJid ( ) . toString ( ) + File . separator +
contactsDevice . getDeviceId ( ) + File . separator +
" trust " ) ;
if ( ! target . exists ( ) ) {
return TrustState . undecided ;
}
try ( BufferedReader in = new BufferedReader ( new FileReader ( target ) ) ) {
String line = in . readLine ( ) ;
String [ ] split = line . split ( " " ) ;
if ( split . length ! = 2 ) {
return TrustState . undecided ;
}
OmemoFingerprint f = new OmemoFingerprint ( split [ 0 ] ) ;
TrustState t = TrustState . valueOf ( split [ 1 ] ) ;
if ( f . equals ( fingerprint ) ) {
return t ;
}
return TrustState . untrusted ;
} catch ( FileNotFoundException e ) {
throw new AssertionError ( e ) ;
}
}
2017-04-22 21:17:23 +02:00
}