summaryrefslogtreecommitdiffstats
path: root/comm/chat/protocols/irc/ircDCC.sys.mjs
blob: afd88f52be588b0b4a39c2441f8af82c3e47e134 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * This contains an implementation of the Direct Client-to-Client (DCC)
 * protocol.
 *   A description of the DCC protocol
 *     http://www.irchelp.org/irchelp/rfc/dccspec.html
 */

import { ircHandlerPriorities } from "resource:///modules/ircHandlerPriorities.sys.mjs";

// Parse a CTCP message into a DCC message. A DCC message is a CTCP message of
// the form:
//   DCC <type> <argument> <address> <port> [<size>]
function DCCMessage(aMessage, aAccount) {
  let message = aMessage;
  let params = message.ctcp.param.split(" ");
  if (params.length < 4) {
    aAccount.ERROR("Not enough DCC parameters:\n" + JSON.stringify(aMessage));
    return null;
  }

  try {
    // Address, port and size should be treated as unsigned long, unsigned short
    // and unsigned long, respectively. The protocol is designed to handle
    // further arguments, if necessary.
    message.ctcp.dcc = {
      type: params[0],
      argument: params[1],
      address: Number(params[2]),
      port: Number(params[3]),
      size: params.length == 5 ? Number(params[4]) : null,
      furtherArguments: params.length > 5 ? params.slice(5) : [],
    };
  } catch (e) {
    aAccount.ERROR(
      "Error parsing DCC parameters:\n" + JSON.stringify(aMessage)
    );
    return null;
  }

  return message;
}

// This is the DCC handler for CTCP, it will call each DCC handler.
export var ctcpDCC = {
  name: "DCC",
  // Slightly above default CTCP priority.
  priority: ircHandlerPriorities.HIGH_PRIORITY + 10,
  isEnabled: () => true,

  commands: {
    // Handle a DCC message by parsing the message and executing any handlers.
    DCC(message, ircHandlers) {
      // If there are no DCC handlers, then don't parse the DCC message.
      if (!ircHandlers.hasDCCHandlers) {
        return false;
      }

      // Parse the message and attempt to handle it.
      return ircHandlers.handleDCCMessage(this, DCCMessage(message, this));
    },
  },
};