123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 |
- /*
- * Copyright (c) 2006-2014 DMDirc Developers
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
- package com.dmdirc.addons.dcc;
-
- import com.dmdirc.FrameContainer;
- import com.dmdirc.actions.ActionManager;
- import com.dmdirc.addons.dcc.actions.DCCActions;
- import com.dmdirc.addons.dcc.io.DCC;
- import com.dmdirc.addons.dcc.io.DCCChat;
- import com.dmdirc.addons.dcc.io.DCCTransfer;
- import com.dmdirc.addons.dcc.kde.KFileChooser;
- import com.dmdirc.addons.ui_swing.MainFrame;
- import com.dmdirc.addons.ui_swing.UIUtilities;
- import com.dmdirc.commandparser.BaseCommandInfo;
- import com.dmdirc.commandparser.CommandArguments;
- import com.dmdirc.commandparser.CommandInfo;
- import com.dmdirc.commandparser.CommandType;
- import com.dmdirc.commandparser.commands.Command;
- import com.dmdirc.commandparser.commands.IntelligentCommand;
- import com.dmdirc.commandparser.commands.context.CommandContext;
- import com.dmdirc.commandparser.commands.context.ServerCommandContext;
- import com.dmdirc.interfaces.CommandController;
- import com.dmdirc.interfaces.Connection;
- import com.dmdirc.messages.MessageSinkManager;
- import com.dmdirc.parser.interfaces.Parser;
- import com.dmdirc.ui.WindowManager;
- import com.dmdirc.ui.input.AdditionalTabTargets;
- import com.dmdirc.ui.input.TabCompleterFactory;
- import com.dmdirc.ui.input.TabCompletionType;
- import com.dmdirc.util.URLBuilder;
-
- import java.io.File;
- import java.util.concurrent.Callable;
-
- import javax.inject.Inject;
- import javax.swing.JFileChooser;
- import javax.swing.JOptionPane;
-
- /**
- * This command allows starting dcc chats/file transfers.
- */
- public class DCCCommand extends Command implements IntelligentCommand {
-
- /** A command info object for this command. */
- public static final CommandInfo INFO = new BaseCommandInfo("dcc",
- "dcc <SEND|CHAT> <target> [params] - starts a DCC",
- CommandType.TYPE_SERVER);
- /** My Plugin. */
- private final DCCManager myPlugin;
- /** Main frame instance used as the parent for dialogs. */
- private final MainFrame mainFrame;
- /** Window management. */
- private final WindowManager windowManager;
- /** The sink manager to use to despatch messages. */
- private final MessageSinkManager messageSinkManager;
- /** The factory to use for tab completers. */
- private final TabCompleterFactory tabCompleterFactory;
- /** The URL builder to use when finding icons. */
- private final URLBuilder urlBuilder;
-
- /**
- * Creates a new instance of DCCCommand.
- *
- * @param controller The controller to use for command information.
- * @param mainFrame mainFrame instance to use
- * @param plugin The DCC Plugin that this command belongs to
- * @param messageSinkManager The sink manager to use to despatch messages.
- * @param windowManager Window management
- * @param tabCompleterFactory The factory to use for tab completers.
- * @param urlBuilder The URL builder to use when finding icons.
- */
- @Inject
- public DCCCommand(
- final CommandController controller,
- final MainFrame mainFrame,
- final DCCManager plugin,
- final MessageSinkManager messageSinkManager,
- final WindowManager windowManager,
- final TabCompleterFactory tabCompleterFactory,
- final URLBuilder urlBuilder) {
- super(controller);
- this.mainFrame = mainFrame;
- myPlugin = plugin;
- this.messageSinkManager = messageSinkManager;
- this.windowManager = windowManager;
- this.tabCompleterFactory = tabCompleterFactory;
- this.urlBuilder = urlBuilder;
- }
-
- /** {@inheritDoc} */
- @Override
- public void execute(final FrameContainer origin,
- final CommandArguments args, final CommandContext context) {
- if (args.getArguments().length > 1) {
- final String target = args.getArguments()[1];
- final Connection connection = ((ServerCommandContext) context).getServer();
- final Parser parser = connection.getParser();
- final String myNickname = parser.getLocalClient().getNickname();
-
- if (parser.isValidChannelName(target)
- || parser.getStringConverter().equalsIgnoreCase(target,
- myNickname)) {
- new Thread(new Runnable() {
- /** {@inheritDoc} */
- @Override
- public void run() {
- if (parser.getStringConverter().equalsIgnoreCase(target,
- myNickname)) {
- JOptionPane.showMessageDialog(null,
- "You can't DCC yourself.", "DCC Error",
- JOptionPane.ERROR_MESSAGE);
- } else {
- JOptionPane.showMessageDialog(null,
- "You can't DCC a channel.", "DCC Error",
- JOptionPane.ERROR_MESSAGE);
- }
- }
- }, "DCC-Error-Message").start();
- return;
- }
- final String type = args.getArguments()[0];
- if (type.equalsIgnoreCase("chat")) {
- startChat(parser, connection, origin, myNickname, target, true);
- } else if (type.equalsIgnoreCase("send")) {
- sendFile(target, origin, connection, true,
- args.getArgumentsAsString(2));
- } else {
- sendLine(origin, args.isSilent(), FORMAT_ERROR,
- "Unknown DCC Type: '" + type + "'");
- }
- } else {
- showUsage(origin, true, INFO.getName(), INFO.getHelp());
- }
- }
-
- /**
- * Starts a DCC Chat.
- *
- * @param parser Parser from which command originated
- * @param connection Server from which command originated
- * @param origin Frame container from which command originated
- * @param myNickname My current nickname
- * @param target Target of the command
- * @param isSilent Is this a silent command
- */
- private void startChat(final Parser parser, final Connection connection,
- final FrameContainer origin, final String myNickname,
- final String target, final boolean isSilent) {
- final DCCChat chat = new DCCChat();
- if (myPlugin.listen(chat)) {
- final ChatContainer window = new ChatContainer(chat, origin.getConfigManager(),
- getController(), "*Chat: " + target, myNickname, target, tabCompleterFactory,
- messageSinkManager, urlBuilder);
- windowManager.addWindow(myPlugin.getContainer(), window);
- parser.sendCTCP(target, "DCC", "CHAT chat " + DCC.ipToLong(
- myPlugin.getListenIP(parser)) + " " + chat.getPort());
- ActionManager.getActionManager().triggerEvent(
- DCCActions.DCC_CHAT_REQUEST_SENT, null, connection, target);
- sendLine(origin, isSilent, "DCCChatStarting", target,
- chat.getHost(), chat.getPort());
- window.addLine("DCCChatStarting", target, chat.getHost(),
- chat.getPort());
- } else {
- sendLine(origin, isSilent, "DCCChatError",
- "Unable to start chat with " + target
- + " - unable to create listen socket");
- }
- }
-
- /**
- * Ask for the file to send, then start the send.
- *
- * @param target Person this dcc is to.
- * @param origin The InputWindow this command was issued on
- * @param connection The server instance that this command is being executed on
- * @param isSilent Whether this command is silenced or not
- * @param filename The file to send
- *
- * @since 0.6.3m1
- */
- public void sendFile(final String target, final FrameContainer origin,
- final Connection connection, final boolean isSilent, final String filename) {
- // New thread to ask the user what file to send
- final File givenFile = new File(filename);
- final File selectedFile = UIUtilities.invokeAndWait(new Callable<File>() {
- @Override
- public File call() {
- final JFileChooser jc = givenFile.exists()
- ? KFileChooser.getFileChooser(origin.getConfigManager(),
- myPlugin, givenFile)
- : KFileChooser.getFileChooser(origin.getConfigManager(),
- myPlugin);
- final int result = showFileChooser(givenFile, target, jc);
-
- if (result != JFileChooser.APPROVE_OPTION
- || !handleInvalidItems(jc)) {
- return null;
- }
- return jc.getSelectedFile();
- }
- });
- if (selectedFile == null) {
- return;
- }
- new Thread(new Runnable() {
- /** {@inheritDoc} */
- @Override
- public void run() {
- final DCCTransfer send = new DCCTransfer(origin
- .getConfigManager().getOptionInt(myPlugin.getDomain(),
- "send.blocksize"));
- send.setTurbo(origin.getConfigManager().getOptionBool(
- myPlugin.getDomain(), "send.forceturbo"));
- send.setType(DCCTransfer.TransferType.SEND);
-
- ActionManager.getActionManager().triggerEvent(
- DCCActions.DCC_SEND_REQUEST_SENT,
- null, connection, target, selectedFile);
-
- sendLine(origin, isSilent, FORMAT_OUTPUT,
- "Starting DCC Send with: " + target);
-
- send.setFileName(selectedFile.getAbsolutePath());
- send.setFileSize(selectedFile.length());
-
- if (origin.getConfigManager().getOptionBool(
- myPlugin.getDomain(), "send.reverse")) {
- final Parser parser = connection.getParser();
- final TransferContainer container = new TransferContainer(myPlugin, send,
- origin.getConfigManager(), "Send: " + target,
- target, connection, urlBuilder);
- windowManager.addWindow(myPlugin.getContainer(), container);
- parser.sendCTCP(target, "DCC", "SEND \""
- + selectedFile.getName() + "\" "
- + DCC.ipToLong(myPlugin.getListenIP(parser))
- + " 0 " + send.getFileSize() + " "
- + send.makeToken()
- + (send.isTurbo() ? " T" : ""));
- } else {
- final Parser parser = connection.getParser();
- if (myPlugin.listen(send)) {
- final TransferContainer container = new TransferContainer(myPlugin, send,
- origin.getConfigManager(), "*Send: "
- + target, target, connection, urlBuilder);
- windowManager.addWindow(myPlugin.getContainer(), container);
- parser.sendCTCP(target, "DCC", "SEND \""
- + selectedFile.getName() + "\" "
- + DCC.ipToLong(myPlugin.getListenIP(parser))
- + " " + send.getPort() + " " + send.getFileSize()
- + (send.isTurbo() ? " T" : ""));
- } else {
- sendLine(origin, isSilent, "DCCSendError",
- "Unable to start dcc send with " + target
- + " - unable to create listen socket");
- }
- }
- }
- }, "openFileThread").start();
- }
-
- /**
- * Checks for invalid items.
- *
- * @param jc File chooser to check
- *
- * @return true iif the selection was valid
- */
- private boolean handleInvalidItems(final JFileChooser jc) {
- if (jc.getSelectedFile().length() == 0) {
- JOptionPane.showMessageDialog(null,
- "You can't send empty files over DCC.", "DCC Error",
- JOptionPane.ERROR_MESSAGE);
- return false;
- } else if (!jc.getSelectedFile().exists()) {
- JOptionPane.showMessageDialog(null, "Invalid file specified",
- "DCC Error", JOptionPane.ERROR_MESSAGE);
- return false;
- }
- return true;
- }
-
- /**
- * Sets up and display a file chooser.
- *
- * @param givenFile File to display
- * @param target DCC target
- * @param jc File chooser
- *
- * @return the return state of the file chooser on popdown:
- * <ul>
- * <li>JFileChooser.CANCEL_OPTION
- * <li>JFileChooser.APPROVE_OPTION
- * <li>JFileChooser.ERROR_OPTION if an error occurs or the dialog is dismissed
- * </ul>
- */
- private int showFileChooser(final File givenFile, final String target,
- final JFileChooser jc) {
- if (givenFile.exists() && givenFile.isFile()) {
- jc.setSelectedFile(givenFile);
- return JFileChooser.APPROVE_OPTION;
- } else {
- jc.setDialogTitle("Send file to " + target + " - DMDirc ");
- jc.setFileSelectionMode(JFileChooser.FILES_ONLY);
- jc.setMultiSelectionEnabled(false);
- return jc.showOpenDialog(mainFrame);
- }
- }
-
- /** {@inheritDoc} */
- @Override
- public AdditionalTabTargets getSuggestions(final int arg,
- final IntelligentCommandContext context) {
- final AdditionalTabTargets res = new AdditionalTabTargets();
-
- if (arg == 0) {
- res.add("SEND");
- res.add("CHAT");
- res.excludeAll();
- } else if (arg == 1) {
- res.exclude(TabCompletionType.COMMAND);
- res.exclude(TabCompletionType.CHANNEL);
- } else {
- res.excludeAll();
- }
-
- return res;
- }
-
- }
|