static void event_invalid_cap (IRC_SERVER_REC *server, const char *data, const char *from) { /* The server didn't understand one (or more) requested caps, terminate the negotiation. * This could be handled in a graceful way but since it shouldn't really ever happen this seems a * good way to deal with 410 errors. */ server->cap_complete = FALSE; irc_send_cmd_now(server, "CAP END"); }
static void sasl_start(IRC_SERVER_REC *server, const char *data, const char *from) { IRC_SERVER_CONNECT_REC *conn; conn = server->connrec; switch (conn->sasl_mechanism) { case SASL_MECHANISM_PLAIN: irc_send_cmd_now(server, "AUTHENTICATE PLAIN"); break; case SASL_MECHANISM_EXTERNAL: irc_send_cmd_now(server, "AUTHENTICATE EXTERNAL"); break; } server->sasl_timeout = g_timeout_add(SASL_TIMEOUT, (GSourceFunc) sasl_timeout, server); }
static void sasl_step_fail(IRC_SERVER_REC *server) { irc_send_cmd_now(server, "AUTHENTICATE *"); cap_finish_negotiation(server); server->sasl_timeout = 0; signal_emit("server sasl failure", 2, server, "The server sent an invalid payload"); }
void cap_finish_negotiation (IRC_SERVER_REC *server) { if (server->cap_complete) return; server->cap_complete = TRUE; irc_send_cmd_now(server, "CAP END"); signal_emit("server cap end", 1, server); }
static void event_ping(IRC_SERVER_REC *server, const char *data) { char *params, *origin, *target, *str; params = event_get_params(data, 2, &origin, &target); str = *target == '\0' ? g_strconcat("PONG :", origin, NULL) : g_strdup_printf("PONG %s :%s", target, origin); irc_send_cmd_now(server, str); g_free(str); g_free(params); }
/* SYNTAX: QUOTE <data> */ static void cmd_quote(const char *data, IRC_SERVER_REC *server) { if (server != NULL && !IS_IRC_SERVER(server)) return; if (server == NULL || server->connect_time == 0) cmd_return_error(CMDERR_NOT_CONNECTED); if (!server->connected) irc_send_cmd_now(server, data); else irc_send_cmd(server, data); }
static gboolean sasl_timeout(IRC_SERVER_REC *server) { /* The authentication timed out, we can't do much beside terminating it */ irc_send_cmd_now(server, "AUTHENTICATE *"); cap_finish_negotiation(server); server->sasl_timeout = 0; signal_emit("server sasl failure", 2, server, "The authentication timed out"); return FALSE; }
static void sig_server_quit(IRC_SERVER_REC *server, const char *msg) { char *str; char *recoded; if (!IS_IRC_SERVER(server) || !server->connected) return; recoded = recode_out(SERVER(server), msg, NULL); str = g_strdup_printf("QUIT :%s", recoded); irc_send_cmd_now(server, str); g_free(str); g_free(recoded); }
static PyObject *PyIrcServer_send_raw_now(PyIrcServer *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"cmd", NULL}; char *cmd; RET_NULL_IF_INVALID(self->data); if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &cmd)) return NULL; irc_send_cmd_now(self->data, cmd); Py_RETURN_NONE; }
static void event_nick_in_use(IRC_SERVER_REC *server, const char *data) { char *str, *cmd; int n; g_return_if_fail(data != NULL); if (server->connected) { /* Already connected, no need to handle this anymore. */ return; } /* nick already in use - need to change it .. */ if (g_ascii_strcasecmp(server->nick, server->connrec->nick) == 0 && server->connrec->alternate_nick != NULL && g_ascii_strcasecmp(server->connrec->alternate_nick, server->nick) != 0) { /* first try, so try the alternative nick.. */ g_free(server->nick); server->nick = g_strdup(server->connrec->alternate_nick); } else if (strlen(server->nick) < 9) { /* keep adding '_' to end of nick.. */ str = g_strdup_printf("%s_", server->nick); g_free(server->nick); server->nick = str; } else { /* nick full, keep adding number at the end */ for (n = 8; n > 0; n--) { if (server->nick[n] < '0' || server->nick[n] > '9') { server->nick[n] = '1'; break; } if (server->nick[n] < '9') { server->nick[n]++; break; } server->nick[n] = '0'; } } cmd = g_strdup_printf("NICK %s", server->nick); irc_send_cmd_now(server, cmd); g_free(cmd); }
static void event_cap (IRC_SERVER_REC *server, char *args, char *nick, char *address) { GSList *tmp; GString *cmd; char *params, *evt, *list, **caps; int i, caps_length, disable, avail_caps; params = event_get_params(args, 3, NULL, &evt, &list); if (params == NULL) return; /* Strip the trailing whitespaces before splitting the string, some servers send responses with * superfluous whitespaces that g_strsplit the interprets as tokens */ caps = g_strsplit(g_strchomp(list), " ", -1); caps_length = g_strv_length(caps); if (!g_strcmp0(evt, "LS")) { /* Create a list of the supported caps */ for (i = 0; i < caps_length; i++) server->cap_supported = g_slist_prepend(server->cap_supported, g_strdup(caps[i])); /* Request the required caps, if any */ if (server->cap_queue == NULL) { cap_finish_negotiation(server); } else { cmd = g_string_new("CAP REQ :"); avail_caps = 0; /* Check whether the cap is supported by the server */ for (tmp = server->cap_queue; tmp != NULL; tmp = tmp->next) { if (gslist_find_string(server->cap_supported, tmp->data)) { g_string_append_c(cmd, ' '); g_string_append(cmd, tmp->data); avail_caps++; } } /* Clear the queue here */ gslist_free_full(server->cap_queue, (GDestroyNotify) g_free); server->cap_queue = NULL; /* If the server doesn't support any cap we requested close the negotiation here */ if (avail_caps > 0) irc_send_cmd_now(server, cmd->str); else cap_finish_negotiation(server); g_string_free(cmd, TRUE); } } else if (!g_strcmp0(evt, "ACK")) { int got_sasl = FALSE; /* Emit a signal for every ack'd cap */ for (i = 0; i < caps_length; i++) { disable = (*caps[i] == '-'); if (disable) server->cap_active = gslist_remove_string(server->cap_active, caps[i] + 1); else server->cap_active = g_slist_prepend(server->cap_active, g_strdup(caps[i])); if (!g_strcmp0(caps[i], "sasl")) got_sasl = TRUE; cap_emit_signal(server, "ack", caps[i]); } /* Hopefully the server has ack'd all the caps requested and we're ready to terminate the * negotiation, unless sasl was requested. In this case we must not terminate the negotiation * until the sasl handshake is over. */ if (got_sasl == FALSE) cap_finish_negotiation(server); } else if (!g_strcmp0(evt, "NAK")) { g_warning("The server answered with a NAK to our CAP request, this should not happen"); /* A NAK'd request means that a required cap can't be enabled or disabled, don't update the * list of active caps and notify the listeners. */ for (i = 0; i < caps_length; i++) cap_emit_signal(server, "nak", caps[i]); } g_strfreev(caps); g_free(params); }
static void server_init(IRC_SERVER_REC *server) { IRC_SERVER_CONNECT_REC *conn; char *address, *ptr, *username, *cmd; GTimeVal now; g_return_if_fail(server != NULL); conn = server->connrec; if (conn->proxy != NULL && conn->proxy_password != NULL && *conn->proxy_password != '\0') { cmd = g_strdup_printf("PASS %s", conn->proxy_password); irc_send_cmd_now(server, cmd); g_free(cmd); } if (conn->proxy != NULL && conn->proxy_string != NULL) { cmd = g_strdup_printf(conn->proxy_string, conn->address, conn->port); irc_send_cmd_now(server, cmd); g_free(cmd); } if (conn->password != NULL && *conn->password != '\0') { /* send password */ cmd = g_strdup_printf("PASS %s", conn->password); irc_send_cmd_now(server, cmd); g_free(cmd); } /* send nick */ cmd = g_strdup_printf("NICK %s", conn->nick); irc_send_cmd_now(server, cmd); g_free(cmd); /* send user/realname */ address = server->connrec->address; ptr = strrchr(address, ':'); if (ptr != NULL) { /* IPv6 address .. doesn't work here, use the string after the last : char */ address = ptr+1; if (*address == '\0') address = "x"; } username = g_strdup(conn->username); ptr = strchr(username, ' '); if (ptr != NULL) *ptr = '\0'; cmd = g_strdup_printf("USER %s %s %s :%s", username, username, address, conn->realname); irc_send_cmd_now(server, cmd); g_free(cmd); g_free(username); if (conn->proxy != NULL && conn->proxy_string_after != NULL) { cmd = g_strdup_printf(conn->proxy_string_after, conn->address, conn->port); irc_send_cmd_now(server, cmd); g_free(cmd); } server->isupport = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal); /* set the standards */ g_hash_table_insert(server->isupport, g_strdup("CHANMODES"), g_strdup("beIqd,k,lfJ,imnpst")); g_hash_table_insert(server->isupport, g_strdup("PREFIX"), g_strdup("(ohv)@%+")); server->cmdcount = 0; /* prevent the queue from sending too early, we have a max cut off of 120 secs */ /* this will reset to 1 sec after we get the 001 event */ g_get_current_time(&now); memcpy(&((IRC_SERVER_REC *)server)->wait_cmd, &now, sizeof(GTimeVal)); ((IRC_SERVER_REC *)server)->wait_cmd.tv_sec += 120; }