]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/Main.java
Split commands into separate classes
[signal-cli] / src / main / java / org / asamk / signal / Main.java
1 /*
2 Copyright (C) 2015-2018 AsamK
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17 package org.asamk.signal;
18
19 import net.sourceforge.argparse4j.ArgumentParsers;
20 import net.sourceforge.argparse4j.impl.Arguments;
21 import net.sourceforge.argparse4j.inf.*;
22 import org.apache.http.util.TextUtils;
23 import org.asamk.Signal;
24 import org.asamk.signal.commands.*;
25 import org.asamk.signal.manager.BaseConfig;
26 import org.asamk.signal.manager.Manager;
27 import org.freedesktop.dbus.DBusConnection;
28 import org.freedesktop.dbus.exceptions.DBusException;
29 import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
30
31 import java.io.File;
32 import java.security.Security;
33 import java.util.Map;
34
35 public class Main {
36
37 public static void main(String[] args) {
38 // Workaround for BKS truststore
39 Security.insertProviderAt(new org.bouncycastle.jce.provider.BouncyCastleProvider(), 1);
40
41 Namespace ns = parseArgs(args);
42 if (ns == null) {
43 System.exit(1);
44 }
45
46 int res = handleCommands(ns);
47 System.exit(res);
48 }
49
50 private static int handleCommands(Namespace ns) {
51 final String username = ns.getString("username");
52 Manager m;
53 Signal ts;
54 DBusConnection dBusConn = null;
55 try {
56 if (ns.getBoolean("dbus") || ns.getBoolean("dbus_system")) {
57 try {
58 m = null;
59 int busType;
60 if (ns.getBoolean("dbus_system")) {
61 busType = DBusConnection.SYSTEM;
62 } else {
63 busType = DBusConnection.SESSION;
64 }
65 dBusConn = DBusConnection.getConnection(busType);
66 ts = dBusConn.getRemoteObject(
67 DbusConfig.SIGNAL_BUSNAME, DbusConfig.SIGNAL_OBJECTPATH,
68 Signal.class);
69 } catch (UnsatisfiedLinkError e) {
70 System.err.println("Missing native library dependency for dbus service: " + e.getMessage());
71 return 1;
72 } catch (DBusException e) {
73 e.printStackTrace();
74 if (dBusConn != null) {
75 dBusConn.disconnect();
76 }
77 return 3;
78 }
79 } else {
80 String settingsPath = ns.getString("config");
81 if (TextUtils.isEmpty(settingsPath)) {
82 settingsPath = System.getProperty("user.home") + "/.config/signal";
83 if (!new File(settingsPath).exists()) {
84 String legacySettingsPath = System.getProperty("user.home") + "/.config/textsecure";
85 if (new File(legacySettingsPath).exists()) {
86 settingsPath = legacySettingsPath;
87 }
88 }
89 }
90
91 m = new Manager(username, settingsPath);
92 ts = m;
93 try {
94 m.init();
95 } catch (Exception e) {
96 System.err.println("Error loading state file: " + e.getMessage());
97 return 2;
98 }
99 }
100
101 String commandKey = ns.getString("command");
102 final Map<String, Command> commands = Commands.getCommands();
103 if (commands.containsKey(commandKey)) {
104 Command command = commands.get(commandKey);
105
106 if (dBusConn != null) {
107 if (command instanceof ExtendedDbusCommand) {
108 return ((ExtendedDbusCommand) command).handleCommand(ns, ts, dBusConn);
109 } else if (command instanceof DbusCommand) {
110 return ((DbusCommand) command).handleCommand(ns, ts);
111 } else {
112 System.err.println(commandKey + " is not yet implemented via dbus");
113 return 1;
114 }
115 } else {
116 if (command instanceof LocalCommand) {
117 return ((LocalCommand) command).handleCommand(ns, m);
118 } else if (command instanceof DbusCommand) {
119 return ((DbusCommand) command).handleCommand(ns, ts);
120 } else {
121 System.err.println(commandKey + " is only works via dbus");
122 return 1;
123 }
124 }
125 }
126 return 0;
127 } finally {
128 if (dBusConn != null) {
129 dBusConn.disconnect();
130 }
131 }
132 }
133
134 private static Namespace parseArgs(String[] args) {
135 ArgumentParser parser = ArgumentParsers.newFor("signal-cli")
136 .build()
137 .defaultHelp(true)
138 .description("Commandline interface for Signal.")
139 .version(BaseConfig.PROJECT_NAME + " " + BaseConfig.PROJECT_VERSION);
140
141 parser.addArgument("-v", "--version")
142 .help("Show package version.")
143 .action(Arguments.version());
144 parser.addArgument("--config")
145 .help("Set the path, where to store the config (Default: $HOME/.config/signal).");
146
147 MutuallyExclusiveGroup mut = parser.addMutuallyExclusiveGroup();
148 mut.addArgument("-u", "--username")
149 .help("Specify your phone number, that will be used for verification.");
150 mut.addArgument("--dbus")
151 .help("Make request via user dbus.")
152 .action(Arguments.storeTrue());
153 mut.addArgument("--dbus-system")
154 .help("Make request via system dbus.")
155 .action(Arguments.storeTrue());
156
157 Subparsers subparsers = parser.addSubparsers()
158 .title("subcommands")
159 .dest("command")
160 .description("valid subcommands")
161 .help("additional help");
162
163 final Map<String, Command> commands = Commands.getCommands();
164 for (Map.Entry<String, Command> entry : commands.entrySet()) {
165 Subparser subparser = subparsers.addParser(entry.getKey());
166 entry.getValue().attachToSubparser(subparser);
167 }
168
169 Namespace ns;
170 try {
171 ns = parser.parseArgs(args);
172 } catch (ArgumentParserException e) {
173 parser.handleError(e);
174 return null;
175 }
176
177 if ("link".equals(ns.getString("command"))) {
178 if (ns.getString("username") != null) {
179 parser.printUsage();
180 System.err.println("You cannot specify a username (phone number) when linking");
181 System.exit(2);
182 }
183 } else if (!ns.getBoolean("dbus") && !ns.getBoolean("dbus_system")) {
184 if (ns.getString("username") == null) {
185 parser.printUsage();
186 System.err.println("You need to specify a username (phone number)");
187 System.exit(2);
188 }
189 if (!PhoneNumberFormatter.isValidNumber(ns.getString("username"))) {
190 System.err.println("Invalid username (phone number), make sure you include the country code.");
191 System.exit(2);
192 }
193 }
194 if (ns.getList("recipient") != null && !ns.getList("recipient").isEmpty() && ns.getString("group") != null) {
195 System.err.println("You cannot specify recipients by phone number and groups a the same time");
196 System.exit(2);
197 }
198 return ns;
199 }
200 }