Exemple #1
0
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");
}
Exemple #2
0
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);
}
Exemple #3
0
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");
}
Exemple #4
0
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);
}
Exemple #5
0
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);
}
Exemple #6
0
/* 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);
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}
Exemple #10
0
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);
}
Exemple #11
0
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);
}
Exemple #12
0
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;
}