aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--irc.h8
-rw-r--r--irc_cap.c180
-rw-r--r--irc_commands.c149
-rw-r--r--tests/Makefile2
5 files changed, 190 insertions, 151 deletions
diff --git a/Makefile b/Makefile
index cc187c89..102af35f 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@
-include Makefile.settings
# Program variables
-objects = bitlbee.o dcc.o help.o ipc.o irc.o irc_im.o irc_channel.o irc_commands.o irc_send.o irc_user.o irc_util.o nick.o $(OTR_BI) query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o conf.o log.o
+objects = bitlbee.o dcc.o help.o ipc.o irc.o irc_im.o irc_cap.o irc_channel.o irc_commands.o irc_send.o irc_user.o irc_util.o nick.o $(OTR_BI) query.o root_commands.o set.o storage.o $(STORAGE_OBJS) unix.o conf.o log.o
headers = $(wildcard $(_SRCDIR_)*.h $(_SRCDIR_)lib/*.h $(_SRCDIR_)protocols/*.h)
subdirs = lib protocols
diff --git a/irc.h b/irc.h
index fc449524..c7d1aa85 100644
--- a/irc.h
+++ b/irc.h
@@ -65,6 +65,11 @@ typedef enum {
IRC_UTF8_NICKS = 0x10000, /* Disable ASCII restrictions on buddy nicks. */
} irc_status_t;
+typedef enum {
+ CAP_FOO = (1 << 0),
+ CAP_BAR = (1 << 1),
+} irc_cap_flag_t;
+
struct irc_user;
typedef struct irc {
@@ -351,4 +356,7 @@ char *irc_format_timestamp(irc_t *irc, time_t msg_ts);
void bee_irc_channel_update(irc_t *irc, irc_channel_t *ic, irc_user_t *iu);
void bee_irc_user_nick_reset(irc_user_t *iu);
+/* irc_cap.c */
+void irc_cmd_cap(irc_t *irc, char **cmd);
+
#endif
diff --git a/irc_cap.c b/irc_cap.c
new file mode 100644
index 00000000..3b139c94
--- /dev/null
+++ b/irc_cap.c
@@ -0,0 +1,180 @@
+/********************************************************************\
+ * BitlBee -- An IRC to other IM-networks gateway *
+ * *
+ * Copyright 2002-2013 Wilmer van der Gaast and others *
+ \********************************************************************/
+
+/* IRCv3 CAP command
+ *
+ * Specs:
+ * - v3.1: http://ircv3.net/specs/core/capability-negotiation-3.1.html
+ * - v3.2: http://ircv3.net/specs/core/capability-negotiation-3.2.html
+ *
+ * */
+
+/*
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License with
+ the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+ if not, write to the Free Software Foundation, Inc., 51 Franklin St.,
+ Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "bitlbee.h"
+
+typedef struct {
+ char *name;
+ irc_cap_flag_t flag;
+} cap_info_t;
+
+static const cap_info_t supported_caps[] = {
+ {"foo", CAP_FOO},
+ {"bar", CAP_BAR},
+ {NULL},
+};
+
+static irc_cap_flag_t cap_flag_from_string(char *cap_name)
+{
+ int i;
+
+ if (!cap_name || !cap_name[0]) {
+ return 0;
+ }
+
+ if (cap_name[0] == '-') {
+ cap_name++;
+ }
+
+ for (i = 0; supported_caps[i].name; i++) {
+ if (strcmp(supported_caps[i].name, cap_name) == 0) {
+ return supported_caps[i].flag;
+ }
+ }
+ return 0;
+}
+
+static gboolean irc_cmd_cap_req(irc_t *irc, char *caps)
+{
+ int i;
+ char *lower = NULL;
+ char **split = NULL;
+ irc_cap_flag_t new_caps = irc->caps;
+
+ if (!caps || !caps[0]) {
+ return FALSE;
+ }
+
+ lower = g_ascii_strdown(caps, -1);
+ split = g_strsplit(lower, " ", -1);
+ g_free(lower);
+
+ for (i = 0; split[i]; i++) {
+ gboolean remove;
+ irc_cap_flag_t flag;
+
+ if (!split[i][0]) {
+ continue; /* skip empty items (consecutive spaces) */
+ }
+
+ remove = (split[i][0] == '-');
+ flag = cap_flag_from_string(split[i]);
+
+ if (!flag || (remove && !(irc->caps & flag))) {
+ /* unsupported cap, or removing something that isn't there */
+ g_strfreev(split);
+ return FALSE;
+ }
+
+ if (remove) {
+ new_caps &= ~flag;
+ } else {
+ new_caps |= flag;
+ }
+ }
+
+ /* if we got here, set the new caps and ack */
+ irc->caps = new_caps;
+
+ g_strfreev(split);
+ return TRUE;
+}
+
+/* version can be "302" or NULL, but we don't need cap-3.2 for anything yet */
+static void irc_cmd_cap_ls(irc_t *irc, char *version)
+{
+ int i;
+ GString *str = g_string_sized_new(256);
+
+ for (i = 0; supported_caps[i].name; i++) {
+ if (i != 0) {
+ g_string_append_c(str, ' ');
+ }
+ g_string_append(str, supported_caps[i].name);
+ }
+
+ irc_send_cap(irc, "LS", str->str);
+
+ g_string_free(str, TRUE);
+}
+
+/* this one looks suspiciously similar to cap ls,
+ * but cap-3.2 will make them very different */
+static void irc_cmd_cap_list(irc_t *irc)
+{
+ int i;
+ gboolean first = TRUE;
+ GString *str = g_string_sized_new(256);
+
+ for (i = 0; supported_caps[i].name; i++) {
+ if (irc->caps & supported_caps[i].flag) {
+ if (!first) {
+ g_string_append_c(str, ' ');
+ }
+ first = FALSE;
+
+ g_string_append(str, supported_caps[i].name);
+ }
+ }
+
+ irc_send_cap(irc, "LIST", str->str);
+
+ g_string_free(str, TRUE);
+}
+
+void irc_cmd_cap(irc_t *irc, char **cmd)
+{
+ if (!(irc->status & USTATUS_LOGGED_IN)) {
+ /* Put registration on hold until CAP END */
+ irc->status |= USTATUS_CAP_PENDING;
+ }
+
+ if (g_strcasecmp(cmd[1], "LS") == 0) {
+ irc_cmd_cap_ls(irc, cmd[2]);
+
+ } else if (g_strcasecmp(cmd[1], "LIST") == 0) {
+ irc_cmd_cap_list(irc);
+
+ } else if (g_strcasecmp(cmd[1], "REQ") == 0) {
+ gboolean ack = irc_cmd_cap_req(irc, cmd[2]);
+
+ irc_send_cap(irc, ack ? "ACK" : "NAK", cmd[2] ? : "");
+
+ } else if (g_strcasecmp(cmd[1], "END") == 0) {
+ irc->status &= ~USTATUS_CAP_PENDING;
+ irc_check_login(irc);
+
+ } else {
+ irc_send_num(irc, 410, "%s :Invalid CAP command", cmd[1]);
+ }
+
+}
+
diff --git a/irc_commands.c b/irc_commands.c
index ebcc300b..14a3fd9d 100644
--- a/irc_commands.c
+++ b/irc_commands.c
@@ -28,155 +28,6 @@
#include "help.h"
#include "ipc.h"
-typedef guint32 cap_flag; /* 32 bits ought to be enough for anybody */
-
-typedef struct _cap_info {
- char *name;
- cap_flag flag;
-} cap_info_t;
-
-#define CAP_FOO (1 << 0)
-#define CAP_BAR (1 << 1)
-
-static const cap_info_t supported_caps[] = {
- {"foo", CAP_FOO},
- {"bar", CAP_BAR},
- {NULL},
-};
-
-static cap_flag cap_flag_from_string(char *cap_name) {
- int i;
-
- if (!cap_name && !cap_name[0]) {
- return 0;
- }
-
- if (cap_name[0] == '-') {
- cap_name++;
- }
-
- for (i = 0; supported_caps[i].name; i++) {
- if (strcmp(supported_caps[i].name, cap_name) == 0) {
- return supported_caps[i].flag;
- }
- }
- return 0;
-}
-
-static gboolean irc_cmd_cap_req(irc_t *irc, char *caps)
-{
- int i;
- char *lower = NULL;
- char **split = NULL;
- cap_flag new_caps = irc->caps;
-
- if (!caps || !caps[0]) {
- return FALSE;
- }
-
- lower = g_ascii_strdown(caps, -1);
- split = g_strsplit(lower, " ", -1);
- g_free(lower);
-
- for (i = 0; split[i]; i++) {
- gboolean remove;
- cap_flag flag;
-
- if (!split[i][0]) {
- continue; /* skip empty items (consecutive spaces) */
- }
-
- remove = (split[i][0] == '-');
- flag = cap_flag_from_string(split[i]);
-
- if (!flag || (remove && !(irc->caps & flag))) {
- /* unsupported cap, or removing something that isn't there */
- g_strfreev(split);
- return FALSE;
- }
-
- if (remove) {
- new_caps &= ~flag;
- } else {
- new_caps |= flag;
- }
- }
-
- /* if we got here, set the new caps and ack */
- irc->caps = new_caps;
-
- g_strfreev(split);
- return TRUE;
-}
-
-/* version can be "302" or NULL, but we don't need cap-3.2 for anything yet */
-static void irc_cmd_cap_ls(irc_t *irc, char *version) {
- int i;
- GString *str = g_string_sized_new(256);
-
- for (i = 0; supported_caps[i].name; i++) {
- if (i != 0) {
- g_string_append_c(str, ' ');
- }
- g_string_append(str, supported_caps[i].name);
- }
-
- irc_send_cap(irc, "LS", str->str);
-
- g_string_free(str, TRUE);
-}
-
-/* this one looks suspiciously similar to cap ls,
- * but cap-3.2 will make them very different */
-static void irc_cmd_cap_list(irc_t *irc) {
- int i;
- gboolean first = TRUE;
- GString *str = g_string_sized_new(256);
-
- for (i = 0; supported_caps[i].name; i++) {
- if (irc->caps & supported_caps[i].flag) {
- if (!first) {
- g_string_append_c(str, ' ');
- }
- first = FALSE;
-
- g_string_append(str, supported_caps[i].name);
- }
- }
-
- irc_send_cap(irc, "LIST", str->str);
-
- g_string_free(str, TRUE);
-}
-
-static void irc_cmd_cap(irc_t *irc, char **cmd)
-{
- if (!(irc->status & USTATUS_LOGGED_IN)) {
- /* Put registration on hold until CAP END */
- irc->status |= USTATUS_CAP_PENDING;
- }
-
- if (g_strcasecmp(cmd[1], "LS") == 0) {
- irc_cmd_cap_ls(irc, cmd[2]);
-
- } else if (g_strcasecmp(cmd[1], "LIST") == 0) {
- irc_cmd_cap_list(irc);
-
- } else if (g_strcasecmp(cmd[1], "REQ") == 0) {
- gboolean ack = irc_cmd_cap_req(irc, cmd[2]);
-
- irc_send_cap(irc, ack ? "ACK" : "NAK", cmd[2] ? : "");
-
- } else if (g_strcasecmp(cmd[1], "END") == 0) {
- irc->status &= ~USTATUS_CAP_PENDING;
- irc_check_login(irc);
-
- } else {
- irc_send_num(irc, 410, "%s :Invalid CAP command", cmd[1]);
- }
-
-}
-
static void irc_cmd_pass(irc_t *irc, char **cmd)
{
if (irc->status & USTATUS_LOGGED_IN) {
diff --git a/tests/Makefile b/tests/Makefile
index d77fb1d1..efca9bff 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -14,7 +14,7 @@ clean:
distclean: clean
-main_objs = bitlbee.o conf.o dcc.o help.o ipc.o irc.o irc_channel.o irc_commands.o irc_im.o irc_send.o irc_user.o irc_util.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o
+main_objs = bitlbee.o conf.o dcc.o help.o ipc.o irc.o irc_cap.o irc_channel.o irc_commands.o irc_im.o irc_send.o irc_user.o irc_util.o irc_commands.o log.o nick.o query.o root_commands.o set.o storage.o storage_xml.o
test_objs = check.o check_util.o check_nick.o check_md5.o check_arc.o check_irc.o check_help.o check_user.o check_set.o check_jabber_sasl.o check_jabber_util.o