Esempio n. 1
0
static void
process_numeric (session * sess, int n,
					  char *word[], char *word_eol[], char *text,
					  const message_tags_data *tags_data)
{
	server *serv = sess->server;
	/* show whois is the server tab */
	session *whois_sess = serv->server_session;
	
	/* unless this setting is on */
	if (prefs.hex_irc_whois_front)
		whois_sess = serv->front_session;

	switch (n)
	{
	case 1:
		inbound_login_start (sess, word[3], word[1], tags_data);
		/* if network is PTnet then you must get your IP address
			from "001" server message */
		if ((strncmp(word[7], "PTnet", 5) == 0) &&
			(strncmp(word[8], "IRC", 3) == 0) &&
			(strncmp(word[9], "Network", 7) == 0) &&
			(strrchr(word[10], '@') != NULL))
		{
			serv->use_who = FALSE;
			if (prefs.hex_dcc_ip_from_server)
				inbound_foundip (sess, strrchr(word[10], '@')+1, tags_data);
		}

		goto def;

	case 4:	/* check the ircd type */
		serv->use_listargs = FALSE;
		serv->modes_per_line = 3;		/* default to IRC RFC */
		if (strncmp (word[5], "bahamut", 7) == 0)				/* DALNet */
		{
			serv->use_listargs = TRUE;		/* use the /list args */
		} else if (strncmp (word[5], "u2.10.", 6) == 0)		/* Undernet */
		{
			serv->use_listargs = TRUE;		/* use the /list args */
			serv->modes_per_line = 6;		/* allow 6 modes per line */
		} else if (strncmp (word[5], "glx2", 4) == 0)
		{
			serv->use_listargs = TRUE;		/* use the /list args */
		}
		goto def;

	case 5:
		inbound_005 (serv, word, tags_data);
		goto def;

	case 263:	/*Server load is temporarily too heavy */
		if (fe_is_chanwindow (sess->server))
		{
			fe_chan_list_end (sess->server);
			fe_message (word_eol[4], FE_MSG_ERROR);
		}
		goto def;

	case 301:
		inbound_away (serv, word[4],
						  (word_eol[5][0] == ':') ? word_eol[5] + 1 : word_eol[5],
						  tags_data);
		break;

	case 302:
		if (serv->skip_next_userhost)
		{
			char *eq = strchr (word[4], '=');
			if (eq)
			{
				*eq = 0;
				if (!serv->p_cmp (word[4] + 1, serv->nick))
				{
					char *at = strrchr (eq + 1, '@');
					if (at)
						inbound_foundip (sess, at + 1, tags_data);
				}
			}

			serv->skip_next_userhost = FALSE;
			break;
		}
		else goto def;

	case 303:
		word[4]++;
		notify_markonline (serv, word, tags_data);
		break;

	case 305:
		inbound_uback (serv, tags_data);
		goto def;

	case 306:
		inbound_uaway (serv, tags_data);
		goto def;

	case 312:
		if (!serv->skip_next_whois)
			EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS3, whois_sess, word[4], word_eol[5],
										  NULL, NULL, 0, tags_data->timestamp);
		else
			inbound_user_info (sess, NULL, NULL, NULL, word[5], word[4], NULL, NULL,
									 0xff, tags_data);
		break;

	case 311:	/* WHOIS 1st line */
		serv->inside_whois = 1;
		inbound_user_info_start (sess, word[4], tags_data);
		if (!serv->skip_next_whois)
			EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS1, whois_sess, word[4], word[5],
										  word[6], (word_eol[8][0] == ':') ? word_eol[8] + 1 : word_eol[8],
										  0, tags_data->timestamp);
		else
			inbound_user_info (sess, NULL, word[5], word[6], NULL, word[4],
									 word_eol[8][0] == ':' ? word_eol[8] + 1 : word_eol[8],
									 NULL, 0xff, tags_data);
		break;

	case 314:	/* WHOWAS */
		inbound_user_info_start (sess, word[4], tags_data);
		EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS1, whois_sess, word[4], word[5],
									  word[6], word_eol[8] + 1, 0, tags_data->timestamp);
		break;

	case 317:
		if (!serv->skip_next_whois)
		{
			time_t timestamp = (time_t) atol (word[6]);
			long idle = atol (word[5]);
			char *tim;
			char outbuf[64];

			g_snprintf (outbuf, sizeof (outbuf),
						"%02ld:%02ld:%02ld", idle / 3600, (idle / 60) % 60,
						idle % 60);
			if (timestamp == 0)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS4, whois_sess, word[4],
											  outbuf, NULL, NULL, 0, tags_data->timestamp);
			else
			{
				tim = ctime (&timestamp);
				tim[19] = 0; 	/* get rid of the \n */
				EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS4T, whois_sess, word[4],
											  outbuf, tim, NULL, 0, tags_data->timestamp);
			}
		}
		break;

	case 318:	/* END OF WHOIS */
		if (!serv->skip_next_whois)
			EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS6, whois_sess, word[4], NULL,
										  NULL, NULL, 0, tags_data->timestamp);
		serv->skip_next_whois = 0;
		serv->inside_whois = 0;
		break;

	case 313:
	case 319:
		if (!serv->skip_next_whois)
			EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS2, whois_sess, word[4],
										  word_eol[5] + 1, NULL, NULL, 0,
										  tags_data->timestamp);
		break;

	case 307:	/* dalnet version */
	case 320:	/* :is an identified user */
		if (!serv->skip_next_whois)
			EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS_ID, whois_sess, word[4],
										  word_eol[5] + 1, NULL, NULL, 0,
										  tags_data->timestamp);
		break;

	case 321:
		if (!fe_is_chanwindow (sess->server))
			EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANLISTHEAD, serv->server_session, NULL,
										  NULL, NULL, NULL, 0, tags_data->timestamp);
		break;

	case 322:
		if (fe_is_chanwindow (sess->server))
		{
			fe_add_chan_list (sess->server, word[4], word[5], word_eol[6] + 1);
		} else
		{
			PrintTextTimeStampf (serv->server_session, tags_data->timestamp,
										"%-16s %-7d %s\017\n", word[4], atoi (word[5]),
										word_eol[6] + 1);
		}
		break;

	case 323:
		if (!fe_is_chanwindow (sess->server))
			EMIT_SIGNAL_TIMESTAMP (XP_TE_SERVTEXT, serv->server_session, text, 
										  word[1], word[2], NULL, 0, tags_data->timestamp);
		else
			fe_chan_list_end (sess->server);
		break;

	case 324:
		sess = find_channel (serv, word[4]);
		if (!sess)
			sess = serv->server_session;
		if (sess->ignore_mode)
			sess->ignore_mode = FALSE;
		else
			EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANMODES, sess, word[4], (word_eol[5][0] == ':') ? word_eol[5] + 1 : word_eol[5],
										  NULL, NULL, 0, tags_data->timestamp);
		fe_update_mode_buttons (sess, 'c', '-');
		fe_update_mode_buttons (sess, 't', '-');
		fe_update_mode_buttons (sess, 'n', '-');
		fe_update_mode_buttons (sess, 'i', '-');
		fe_update_mode_buttons (sess, 'm', '-');
		fe_update_mode_buttons (sess, 'l', '-');
		fe_update_mode_buttons (sess, 'k', '-');
		handle_mode (serv, word, word_eol, "", TRUE, tags_data);
		break;

	case 328: /* channel url */
		sess = find_channel (serv, word[4]);
		if (sess)
		{
			EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANURL, sess, word[4], (word_eol[5][0] == ':') ? word_eol[5] + 1 : word_eol[5],
									NULL, NULL, 0, tags_data->timestamp); 
		}
		break;

	case 329:
		sess = find_channel (serv, word[4]);
		if (sess)
		{
			if (sess->ignore_date)
				sess->ignore_date = FALSE;
			else
				channel_date (sess, word[4], (word[5][0] == ':') ? word[5] + 1 : word[5], tags_data);
		}
		break;

	case 330:
		if (!serv->skip_next_whois)
			EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS_AUTH, whois_sess, word[4],
										  word_eol[6] + 1, word[5], NULL, 0,
										  tags_data->timestamp);
		inbound_user_info (sess, NULL, NULL, NULL, NULL, word[4], NULL, word[5],
								 0xff, tags_data);
		break;

	case 332:
		inbound_topic (serv, word[4],
							(word_eol[5][0] == ':') ? word_eol[5] + 1 : word_eol[5],
							tags_data);
		break;

	case 333:
		inbound_topictime (serv, word[4], word[5], atol (word[6]), tags_data);
		break;

#if 0
	case 338:  /* Undernet Real user@host, Real IP */
		EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS_REALHOST, sess, word[4], word[5], word[6], 
									  (word_eol[7][0]==':') ? word_eol[7]+1 : word_eol[7],
									  0, tags_data->timestamp);
		break;
#endif

	case 341:						  /* INVITE ACK */
		EMIT_SIGNAL_TIMESTAMP (XP_TE_UINVITE, sess, word[4], word[5],
									  serv->servername, NULL, 0, tags_data->timestamp);
		break;

	case 352:						  /* WHO */
		{
			unsigned int away = 0;
			session *who_sess = find_channel (serv, word[4]);

			if (*word[9] == 'G')
				away = 1;

			inbound_user_info (sess, word[4], word[5], word[6], word[7],
									 word[8], word_eol[11], NULL, away,
									 tags_data);

			/* try to show only user initiated whos */
			if (!who_sess || !who_sess->doing_who)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_SERVTEXT, serv->server_session, text, word[1],
											  word[2], NULL, 0, tags_data->timestamp);
		}
		break;

	case 354:	/* undernet WHOX: used as a reply for irc_away_status */
		{
			unsigned int away = 0;
			session *who_sess;

			/* irc_away_status and irc_user_list sends out a "152" */
			if (!strcmp (word[4], "152"))
			{
				who_sess = find_channel (serv, word[5]);

				if (*word[10] == 'G')
					away = 1;

				/* :server 354 yournick 152 #channel ~ident host servname nick H account :realname */
				inbound_user_info (sess, word[5], word[6], word[7], word[8],
										 word[9], word_eol[12]+1, word[11], away,
										 tags_data);

				/* try to show only user initiated whos */
				if (!who_sess || !who_sess->doing_who)
					EMIT_SIGNAL_TIMESTAMP (XP_TE_SERVTEXT, serv->server_session, text,
												  word[1], word[2], NULL, 0,
												  tags_data->timestamp);
			} else
				goto def;
		}
		break;

	case 315:						  /* END OF WHO */
		{
			session *who_sess;
			who_sess = find_channel (serv, word[4]);
			if (who_sess)
			{
				if (!who_sess->doing_who)
					EMIT_SIGNAL_TIMESTAMP (XP_TE_SERVTEXT, serv->server_session, text,
												  word[1], word[2], NULL, 0,
												  tags_data->timestamp);
				who_sess->doing_who = FALSE;
			} else
			{
				if (!serv->doing_dns)
					EMIT_SIGNAL_TIMESTAMP (XP_TE_SERVTEXT, serv->server_session, text,
												  word[1], word[2], NULL, 0, tags_data->timestamp);
				serv->doing_dns = FALSE;
			}
		}
		break;

	case 346:	/* +I-list entry */
		if (!inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], 346,
									 tags_data))
			goto def;
		break;

	case 347:	/* end of invite list */
		if (!fe_ban_list_end (sess, 347))
			goto def;
		break;

	case 348:	/* +e-list entry */
		if (!inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], 348,
									 tags_data))
			goto def;
		break;

	case 349:	/* end of exemption list */
		sess = find_channel (serv, word[4]);
		if (!sess)
			goto def;
		if (!fe_ban_list_end (sess, 349))
			goto def;
		break;

	case 353:						  /* NAMES */
		inbound_nameslist (serv, word[5],
								 (word_eol[6][0] == ':') ? word_eol[6] + 1 : word_eol[6],
								 tags_data);
		break;

	case 366:
		if (!inbound_nameslist_end (serv, word[4], tags_data))
			goto def;
		break;

	case 367: /* banlist entry */
		if (!inbound_banlist (sess, atol (word[7]), word[4], word[5], word[6], 367,
									 tags_data))
			goto def;
		break;

	case 368:
		sess = find_channel (serv, word[4]);
		if (!sess)
			goto def;
		if (!fe_ban_list_end (sess, 368))
			goto def;
		break;

	case 369:	/* WHOWAS end */
	case 406:	/* WHOWAS error */
		EMIT_SIGNAL_TIMESTAMP (XP_TE_SERVTEXT, whois_sess, text, word[1], word[2],
									  NULL, 0, tags_data->timestamp);
		serv->inside_whois = 0;
		break;

	case 372:	/* motd text */
	case 375:	/* motd start */
		if (!prefs.hex_irc_skip_motd || serv->motd_skipped)
			EMIT_SIGNAL_TIMESTAMP (XP_TE_MOTD, serv->server_session, text, NULL,
										  NULL, NULL, 0, tags_data->timestamp);
		break;

	case 376:	/* end of motd */
	case 422:	/* motd file is missing */
		inbound_login_end (sess, text, tags_data);
		break;

	case 432:	/* erroneous nickname */
		if (serv->end_of_motd)
		{
			goto def;
		}
		inbound_next_nick (sess,  word[4], 1, tags_data);
		break;

	case 433:	/* nickname in use */
		if (serv->end_of_motd)
		{
			goto def;
		}
		inbound_next_nick (sess,  word[4], 0, tags_data);
		break;

	case 437:
		if (serv->end_of_motd || is_channel (serv, word[4]))
			goto def;
		inbound_next_nick (sess, word[4], 0, tags_data);
		break;

	case 471:
		EMIT_SIGNAL_TIMESTAMP (XP_TE_USERLIMIT, sess, word[4], NULL, NULL, NULL, 0,
									  tags_data->timestamp);
		break;

	case 473:
		EMIT_SIGNAL_TIMESTAMP (XP_TE_INVITE, sess, word[4], NULL, NULL, NULL, 0,
									  tags_data->timestamp);
		break;

	case 474:
		EMIT_SIGNAL_TIMESTAMP (XP_TE_BANNED, sess, word[4], NULL, NULL, NULL, 0,
									  tags_data->timestamp);
		break;

	case 475:
		EMIT_SIGNAL_TIMESTAMP (XP_TE_KEYWORD, sess, word[4], NULL, NULL, NULL, 0,
									  tags_data->timestamp);
		break;

	case 601:
		notify_set_offline (serv, word[4], FALSE, tags_data);
		break;

	case 605:
		notify_set_offline (serv, word[4], TRUE, tags_data);
		break;

	case 600:
	case 604:
		notify_set_online (serv, word[4], tags_data);
		break;

	case 728:	/* +q-list entry */
		/* NOTE:  FREENODE returns these results inconsistent with e.g. +b */
		/* Who else has imlemented MODE_QUIET, I wonder? */
		if (!inbound_banlist (sess, atol (word[8]), word[4], word[6], word[7], 728,
									 tags_data))
			goto def;
		break;

	case 729:	/* end of quiet list */
		if (!fe_ban_list_end (sess, 729))
			goto def;
		break;

	case 730: /* RPL_MONONLINE */
		notify_set_online_list (serv, word[4] + 1, tags_data);
		break;

	case 731: /* RPL_MONOFFLINE */
		notify_set_offline_list (serv, word[4] + 1, FALSE, tags_data);
		break;

	case 900:	/* successful SASL 'logged in as ' */
		EMIT_SIGNAL_TIMESTAMP (XP_TE_SERVTEXT, serv->server_session, 
									  word_eol[6]+1, word[1], word[2], NULL, 0,
									  tags_data->timestamp);
		break;
	case 904:	/* failed SASL auth */
		inbound_sasl_error (serv);
	case 903:	/* successful SASL auth */
	case 905:	/* failed SASL auth */
	case 906:	/* aborted */
	case 907:	/* attempting to re-auth after a successful auth */
		EMIT_SIGNAL_TIMESTAMP (XP_TE_SASLRESPONSE, serv->server_session, word[1],
									  word[2], word[3], ++word_eol[4], 0,
									  tags_data->timestamp);
		if (!serv->sent_capend)
		{
			serv->sent_capend = TRUE;
			tcp_send_len (serv, "CAP END\r\n", 9);
		}
		break;
	case 908:	/* Supported SASL Mechs */
		/* ignored for now, SASL 3.2 is a better solution and we only do PLAIN atm */
		break;

	default:

		if (serv->inside_whois && word[4][0])
		{
			/* some unknown WHOIS reply, ircd coders make them up weekly */
			if (!serv->skip_next_whois)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_WHOIS_SPECIAL, whois_sess, word[4],
											  (word_eol[5][0] == ':') ? word_eol[5] + 1 : word_eol[5],
											  word[2], NULL, 0, tags_data->timestamp);
			return;
		}

	def:
		{
			session *sess;
		
			if (is_channel (serv, word[4]))
			{
				sess = find_channel (serv, word[4]);
				if (!sess)
					sess = serv->server_session;
			}
			else if ((sess=find_dialog (serv,word[4]))) /* user with an open dialog */
				;
			else
				sess=serv->server_session;
			
			EMIT_SIGNAL_TIMESTAMP (XP_TE_SERVTEXT, sess, text, word[1], word[2],
										  NULL, 0, tags_data->timestamp);
		}
	}
}
Esempio n. 2
0
void
inbound_notice (server *serv, char *to, char *nick, char *msg, char *ip, int id,
					 const message_tags_data *tags_data)
{
	char *po,*ptr=to;
	session *sess = 0;
	int server_notice = FALSE;

	if (is_channel (serv, ptr))
		sess = find_channel (serv, ptr);

	if (!sess && ptr[0] == '@')
	{
		ptr++;
		sess = find_channel (serv, ptr);
	}

	if (!sess && ptr[0] == '%')
	{
		ptr++;
		sess = find_channel (serv, ptr);
	}

	if (!sess && ptr[0] == '+')
	{
		ptr++;
		sess = find_channel (serv, ptr);
	}

	if (strcmp (nick, ip) == 0)
		server_notice = TRUE;

	if (!sess)
	{
		ptr = 0;
		if (prefs.hex_irc_notice_pos == 0)
		{
											/* paranoia check */
			if (msg[0] == '[' && (!serv->have_idmsg || id))
			{
				/* guess where chanserv meant to post this -sigh- */
				if (!g_ascii_strcasecmp (nick, "ChanServ") && !find_dialog (serv, nick))
				{
					char *dest = strdup (msg + 1);
					char *end = strchr (dest, ']');
					if (end)
					{
						*end = 0;
						sess = find_channel (serv, dest);
					}
					free (dest);
				}
			}
			if (!sess)
				sess = find_session_from_nick (nick, serv);
		} else if (prefs.hex_irc_notice_pos == 1)
		{
			int stype = server_notice ? SESS_SNOTICES : SESS_NOTICES;
			sess = find_session_from_type (stype, serv);
			if (!sess)
			{
				if (stype == SESS_NOTICES)
					sess = new_ircwindow (serv, "(notices)", SESS_NOTICES, 0);
				else
					sess = new_ircwindow (serv, "(snotices)", SESS_SNOTICES, 0);
				fe_set_channel (sess);
				fe_set_title (sess);
				fe_set_nonchannel (sess, FALSE);
				userlist_clear (sess);
				log_open_or_close (sess);
			}
			/* Avoid redundancy with some Undernet notices */
			if (!strncmp (msg, "*** Notice -- ", 14))
				msg += 14;
		} else
		{
			sess = serv->front_session;
		}

		if (!sess)
		{
			if (server_notice)	
				sess = serv->server_session;
			else
				sess = serv->front_session;
		}
	}

	if (msg[0] == 1)
	{
		msg++;
		if (!strncmp (msg, "PING", 4))
		{
			inbound_ping_reply (sess, msg + 5, nick, tags_data);
			return;
		}
	}
	po = strchr (msg, '\001');
	if (po)
		po[0] = 0;

	if (server_notice)
		EMIT_SIGNAL_TIMESTAMP (XP_TE_SERVNOTICE, sess, msg, nick, NULL, NULL, 0,
									  tags_data->timestamp);
	else if (ptr)
		EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANNOTICE, sess, nick, to, msg, NULL, 0,
									  tags_data->timestamp);
	else
		EMIT_SIGNAL_TIMESTAMP (XP_TE_NOTICE, sess, nick, msg, NULL, NULL, 0,
									  tags_data->timestamp);
}
Esempio n. 3
0
static void
process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
						 const message_tags_data *tags_data)
{
	server *serv = sess->server;
	char ip[128], nick[NICKLEN];
	char *text, *ex;
	int len = strlen (type);

	/* fill in the "ip" and "nick" buffers */
	ex = strchr (word[1], '!');
	if (!ex)							  /* no '!', must be a server message */
	{
		safe_strcpy (ip, word[1], sizeof (ip));
		safe_strcpy (nick, word[1], sizeof (nick));
	} else
	{
		safe_strcpy (ip, ex + 1, sizeof (ip));
		ex[0] = 0;
		safe_strcpy (nick, word[1], sizeof (nick));
		ex[0] = '!';
	}

	if (len == 4)
	{
		guint32 t;

		t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); 	
		/* this should compile to a bunch of: CMP.L, JE ... nice & fast */
		switch (t)
		{
		case WORDL('J','O','I','N'):
			{
				char *chan = word[3];
				char *account = word[4];
				char *realname = word_eol[5];

				if (account && strcmp (account, "*") == 0)
					account = NULL;
				if (realname && *realname == ':')
					realname++;
				if (*chan == ':')
					chan++;
				if (!serv->p_cmp (nick, serv->nick))
					inbound_ujoin (serv, chan, nick, ip, tags_data);
				else
					inbound_join (serv, chan, nick, ip, account, realname,
									  tags_data);
			}
			return;

		case WORDL('K','I','C','K'):
			{
				char *kicked = word[4];
				char *reason = word_eol[5];
				if (*kicked)
				{
					if (*reason == ':')
						reason++;
					if (!strcmp (kicked, serv->nick))
	 					inbound_ukick (serv, word[3], nick, reason, tags_data);
					else
						inbound_kick (serv, word[3], kicked, nick, reason, tags_data);
				}
			}
			return;

		case WORDL('K','I','L','L'):
			{
				char *reason = word_eol[4];
				if (*reason == ':')
					reason++;

				EMIT_SIGNAL_TIMESTAMP (XP_TE_KILL, sess, nick, reason, NULL, NULL,
											  0, tags_data->timestamp);
			}
			return;

		case WORDL('M','O','D','E'):
			handle_mode (serv, word, word_eol, nick, FALSE, tags_data);	/* modes.c */
			return;

		case WORDL('N','I','C','K'):
			inbound_newnick (serv, nick, 
								  (word_eol[3][0] == ':') ? word_eol[3] + 1 : word_eol[3],
								  FALSE, tags_data);
			return;

		case WORDL('P','A','R','T'):
			{
				char *chan = word[3];
				char *reason = word_eol[4];

				if (*chan == ':')
					chan++;
				if (*reason == ':')
					reason++;
				if (!strcmp (nick, serv->nick))
					inbound_upart (serv, chan, ip, reason, tags_data);
				else
					inbound_part (serv, chan, nick, ip, reason, tags_data);
			}
			return;

		case WORDL('P', 'I', 'N', 'G'):
			tcp_sendf (sess->server, "PONG %s\r\n", word_eol[3]);
			return;

		case WORDL('P','O','N','G'):
			inbound_ping_reply (serv->server_session,
									  (word[4][0] == ':') ? word[4] + 1 : word[4],
									  word[3], tags_data);
			return;

		case WORDL('Q','U','I','T'):
			inbound_quit (serv, nick, ip,
							  (word_eol[3][0] == ':') ? word_eol[3] + 1 : word_eol[3],
							  tags_data);
			return;

		case WORDL('A','W','A','Y'):
			inbound_away_notify (serv, nick,
										(word_eol[3][0] == ':') ? word_eol[3] + 1 : NULL,
										tags_data);
			return;
		}

		goto garbage;
	}

	else if (len >= 5)
	{
		guint32 t;

		t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]); 	
		/* this should compile to a bunch of: CMP.L, JE ... nice & fast */
		switch (t)
		{

		case WORDL('A','C','C','O'):
			inbound_account (serv, nick, word[3], tags_data);
			return;

		case WORDL('A', 'U', 'T', 'H'):
			inbound_sasl_authenticate (sess->server, word_eol[3]);
			return;

		case WORDL('C', 'H', 'G', 'H'):
			inbound_user_info (sess, NULL, word[3], word[4], NULL, nick, NULL,
							   NULL, 0xff, tags_data);
			return;

		case WORDL('I','N','V','I'):
			if (ignore_check (word[1], IG_INVI))
				return;
			
			if (word[4][0] == ':')
				EMIT_SIGNAL_TIMESTAMP (XP_TE_INVITED, sess, word[4] + 1, nick,
											  serv->servername, NULL, 0,
											  tags_data->timestamp);
			else
				EMIT_SIGNAL_TIMESTAMP (XP_TE_INVITED, sess, word[4], nick,
											  serv->servername, NULL, 0,
											  tags_data->timestamp);
				
			return;

		case WORDL('N','O','T','I'):
			{
				int id = FALSE;								/* identified */

				text = word_eol[4];
				if (*text == ':')
				{
					text++;
				}

#ifdef USE_OPENSSL
				/* QuakeNet CHALLENGE upon our request */
				if (serv->loginmethod == LOGIN_CHALLENGEAUTH && !serv->p_cmp (word[1], CHALLENGEAUTH_FULLHOST)
				    && !strncmp (text, "CHALLENGE ", 10) && *serv->password)
				{
					char *response;
					ircnet *net = serv->network;
					char *user = net && net->user ? net->user : prefs.hex_irc_user_name;

					response = challengeauth_response (user, serv->password, word[5]);

					tcp_sendf (serv, "PRIVMSG %s :CHALLENGEAUTH %s %s %s\r\n",
						CHALLENGEAUTH_NICK,
						user,
						response,
						CHALLENGEAUTH_ALGO);

					g_free (response);
					return;									/* omit the CHALLENGE <hash> ALGOS message */
				}
#endif

				if (serv->have_idmsg)
				{
					if (*text == '+')
					{
						id = TRUE;
						text++;
					} else if (*text == '-')
						text++;
				}

				if (!ignore_check (word[1], IG_NOTI))
					inbound_notice (serv, word[3], nick, text, ip, id, tags_data);
			}
			return;

		case WORDL('P','R','I','V'):
			{
				char *to = word[3];
				int len;
				int id = FALSE;	/* identified */
				if (*to)
				{
					/* Handle limited channel messages, for now no special event */
					if (strchr (serv->chantypes, to[0]) == NULL
						&& strchr (serv->nick_prefixes, to[0]) != NULL)
						to++;
						
					text = word_eol[4];
					if (*text == ':')
						text++;
					if (serv->have_idmsg)
					{
						if (*text == '+')
						{
							id = TRUE;
							text++;
						} else if (*text == '-')
							text++;
					}
					len = strlen (text);
					if (text[0] == 1 && text[len - 1] == 1)	/* ctcp */
					{
						text[len - 1] = 0;
						text++;
						if (g_ascii_strncasecmp (text, "ACTION", 6) != 0)
							flood_check (nick, ip, serv, sess, 0);
						if (g_ascii_strncasecmp (text, "DCC ", 4) == 0)
							/* redo this with handle_quotes TRUE */
							process_data_init (word[1], word_eol[1], word, word_eol, TRUE, FALSE);
						ctcp_handle (sess, to, nick, ip, text, word, word_eol, id,
										 tags_data);
					} else
					{
						if (is_channel (serv, to))
						{
							if (ignore_check (word[1], IG_CHAN))
								return;
							inbound_chanmsg (serv, NULL, to, nick, text, FALSE, id,
												  tags_data);
						} else
						{
							if (ignore_check (word[1], IG_PRIV))
								return;
							inbound_privmsg (serv, nick, ip, text, id, tags_data);
						}
					}
				}
			}
			return;

		case WORDL('T','O','P','I'):
			inbound_topicnew (serv, nick, word[3],
									(word_eol[4][0] == ':') ? word_eol[4] + 1 : word_eol[4],
									tags_data);
			return;

		case WORDL('W','A','L','L'):
			text = word_eol[3];
			if (*text == ':')
				text++;
			EMIT_SIGNAL_TIMESTAMP (XP_TE_WALLOPS, sess, nick, text, NULL, NULL, 0,
										  tags_data->timestamp);
			return;
		}
	}

	else if (len == 3)
	{
		guint32 t;

		t = WORDL((guint8)type[0], (guint8)type[1], (guint8)type[2], (guint8)type[3]);
		switch (t)
		{
			case WORDL('C','A','P','\0'):
				if (strncasecmp (word[4], "ACK", 3) == 0)
				{
					inbound_cap_ack (serv, word[1], 
										  word[5][0] == ':' ? word_eol[5] + 1 : word_eol[5],
										  tags_data);
				}
				else if (strncasecmp (word[4], "LS", 2) == 0 || strncasecmp (word[4], "NEW", 3) == 0)
				{
					inbound_cap_ls (serv, word[1], 
										 word[5][0] == ':' ? word_eol[5] + 1 : word_eol[5],
										 tags_data);
				}
				else if (strncasecmp (word[4], "NAK", 3) == 0)
				{
					inbound_cap_nak (serv, tags_data);
				}
				else if (strncasecmp (word[4], "LIST", 4) == 0)	
				{
					inbound_cap_list (serv, word[1], 
											word[5][0] == ':' ? word_eol[5] + 1 : word_eol[5],
											tags_data);
				}
				else if (strncasecmp (word[4], "DEL", 3) == 0)
				{
					inbound_cap_del (serv, word[1],
											word[5][0] == ':' ? word_eol[5] + 1 : word_eol[5],
											tags_data);
				}

				return;
		}
	}

garbage:
	/* unknown message */
	PrintTextTimeStampf (sess, tags_data->timestamp, "GARBAGE: %s\n", word_eol[1]);
}
Esempio n. 4
0
void
inbound_action (session *sess, char *chan, char *from, char *ip, char *text,
					 int fromme, int id, const message_tags_data *tags_data)
{
	session *def = sess;
	server *serv = sess->server;
	struct User *user;
	char nickchar[2] = "\000";
	char idtext[64];
	int privaction = FALSE;

	if (!fromme)
	{
		if (is_channel (serv, chan))
		{
			sess = find_channel (serv, chan);
		} else
		{
			/* it's a private action! */
			privaction = TRUE;
			/* find a dialog tab for it */
			sess = find_dialog (serv, from);
			/* if non found, open a new one */
			if (!sess && prefs.hex_gui_autoopen_dialog)
			{
				/* but only if it wouldn't flood */
				if (flood_check (from, ip, serv, current_sess, 1))
					sess = inbound_open_dialog (serv, from, tags_data);
				else
					sess = serv->server_session;
			}
			if (!sess)
			{
				sess = find_session_from_nick (from, serv);
				/* still not good? */
				if (!sess)
					sess = serv->front_session;
			}
		}
	}

	if (!sess)
		sess = def;

	if (sess != current_tab)
	{
		if (fromme)
		{
			sess->msg_said = FALSE;
			sess->new_data = TRUE;
		} else
		{
			sess->msg_said = TRUE;
			sess->new_data = FALSE;
		}
		lastact_update (sess);
	}

	user = userlist_find (sess, from);
	if (user)
	{
		nickchar[0] = user->prefix[0];
		user->lasttalk = time (0);
		if (user->account)
			id = TRUE;
	}

	inbound_make_idtext (serv, idtext, sizeof (idtext), id);

	if (!fromme && !privaction)
	{
		if (is_hilight (from, text, sess, serv))
		{
			EMIT_SIGNAL_TIMESTAMP (XP_TE_HCHANACTION, sess, from, text, nickchar,
										  idtext, 0, tags_data->timestamp);
			return;
		}
	}

	if (fromme)
		EMIT_SIGNAL_TIMESTAMP (XP_TE_UACTION, sess, from, text, nickchar, idtext,
									  0, tags_data->timestamp);
	else if (!privaction)
		EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANACTION, sess, from, text, nickchar,
									  idtext, 0, tags_data->timestamp);
	else if (sess->type == SESS_DIALOG)
		EMIT_SIGNAL_TIMESTAMP (XP_TE_DPRIVACTION, sess, from, text, idtext, NULL,
									  0, tags_data->timestamp);
	else
		EMIT_SIGNAL_TIMESTAMP (XP_TE_PRIVACTION, sess, from, text, idtext, NULL, 0,
									  tags_data->timestamp);
}
Esempio n. 5
0
void
inbound_chanmsg (server *serv, session *sess, char *chan, char *from, 
					  char *text, char fromme, int id, 
					  const message_tags_data *tags_data)
{
	struct User *user;
	int hilight = FALSE;
	char nickchar[2] = "\000";
	char idtext[64];

	if (!sess)
	{
		if (chan)
		{
			sess = find_channel (serv, chan);
			if (!sess && !is_channel (serv, chan))
				sess = find_dialog (serv, chan);
		} else
		{
			sess = find_dialog (serv, from);
		}
		if (!sess)
			return;
	}

	if (sess != current_tab)
	{
		sess->msg_said = TRUE;
		sess->new_data = FALSE;
		lastact_update (sess);
	}

	user = userlist_find (sess, from);
	if (user)
	{
		if (user->account)
			id = TRUE;
		nickchar[0] = user->prefix[0];
		user->lasttalk = time (0);
	}

	if (fromme)
	{
  		if (prefs.hex_away_auto_unmark && serv->is_away)
			sess->server->p_set_back (sess->server);
		EMIT_SIGNAL_TIMESTAMP (XP_TE_UCHANMSG, sess, from, text, nickchar, NULL,
									  0, tags_data->timestamp);
		return;
	}

	inbound_make_idtext (serv, idtext, sizeof (idtext), id);

	if (is_hilight (from, text, sess, serv))
		hilight = TRUE;

	if (sess->type == SESS_DIALOG)
		EMIT_SIGNAL_TIMESTAMP (XP_TE_DPRIVMSG, sess, from, text, idtext, NULL, 0,
									  tags_data->timestamp);
	else if (hilight)
		EMIT_SIGNAL_TIMESTAMP (XP_TE_HCHANMSG, sess, from, text, nickchar, idtext,
									  0, tags_data->timestamp);
	else
		EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANMSG, sess, from, text, nickchar, idtext,
									  0, tags_data->timestamp);
}
Esempio n. 6
0
void
inbound_privmsg (server *serv, char *from, char *ip, char *text, int id,
					  const message_tags_data *tags_data)
{
	session *sess;
	struct User *user;
	char idtext[64];
	gboolean nodiag = FALSE;

	sess = find_dialog (serv, from);

	if (sess || prefs.hex_gui_autoopen_dialog)
	{
		/*0=ctcp  1=priv will set hex_gui_autoopen_dialog=0 here is flud detected */
		if (!sess)
		{
			if (flood_check (from, ip, serv, current_sess, 1))
				/* Create a dialog session */
				sess = inbound_open_dialog (serv, from, tags_data);
			else
				sess = serv->server_session;
			if (!sess)
				return; /* ?? */
		}

		if (ip && ip[0])
		{
			if (prefs.hex_irc_logging && sess->logfd != -1 &&
				(!sess->topic || strcmp(sess->topic, ip)))
			{
				char tbuf[1024];
				snprintf (tbuf, sizeof (tbuf), "[%s has address %s]\n", from, ip);
				write (sess->logfd, tbuf, strlen (tbuf));
			}
			set_topic (sess, ip, ip);
		}
		inbound_chanmsg (serv, NULL, NULL, from, text, FALSE, id, tags_data);
		return;
	}

	sess = find_session_from_nick (from, serv);
	if (!sess)
	{
		sess = serv->front_session;
		nodiag = TRUE; /* We don't want it to look like a normal message in front sess */
	}

	user = userlist_find (sess, from);
	if (user)
	{
		user->lasttalk = time (0);
		if (user->account)
			id = TRUE;
	}
	
	inbound_make_idtext (serv, idtext, sizeof (idtext), id);

	if (sess->type == SESS_DIALOG && !nodiag)
		EMIT_SIGNAL_TIMESTAMP (XP_TE_DPRIVMSG, sess, from, text, idtext, NULL, 0,
									  tags_data->timestamp);
	else
		EMIT_SIGNAL_TIMESTAMP (XP_TE_PRIVMSG, sess, from, text, idtext, NULL, 0, 
									  tags_data->timestamp);
}
Esempio n. 7
0
void
inbound_cap_ls (server *serv, char *nick, char *extensions_str,
					 const message_tags_data *tags_data)
{
	char buffer[256];	/* buffer for requesting capabilities and emitting the signal */
	guint32 want_cap; /* format the CAP REQ string based on previous capabilities being requested or not */
	guint32 want_sasl; /* CAP END shouldn't be sent when SASL is requested, it needs further responses */
	char **extensions;
	int i;

	EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPLIST, serv->server_session, nick,
								  extensions_str, NULL, NULL, 0, tags_data->timestamp);
	want_cap = 0;
	want_sasl = 0;

	extensions = g_strsplit (extensions_str, " ", 0);

	strcpy (buffer, "CAP REQ :");

	for (i=0; extensions[i]; i++)
	{
		const char *extension = extensions[i];

		if (!strcmp (extension, "identify-msg"))
		{
			strcat (buffer, "identify-msg ");
			want_cap = 1;
		}
		if (!strcmp (extension, "multi-prefix"))
		{
			strcat (buffer, "multi-prefix ");
			want_cap = 1;
		}
		if (!strcmp (extension, "away-notify"))
		{
			strcat (buffer, "away-notify ");
			want_cap = 1;
		}
		if (!strcmp (extension, "account-notify"))
		{
			strcat (buffer, "account-notify ");
			want_cap = 1;
		}
		if (!strcmp (extension, "extended-join"))
		{
			strcat (buffer, "extended-join ");
			want_cap = 1;
		}

		/* bouncers can prefix a name space to the extension so we should use.
		 * znc <= 1.0 uses "znc.in/server-time" and newer use "znc.in/server-time-iso".
		 */
		if (!strcmp (extension, "znc.in/server-time-iso"))
		{
			strcat (buffer, "znc.in/server-time-iso ");
		}
		if (!strcmp (extension, "znc.in/server-time"))
		{
			strcat (buffer, "znc.in/server-time ");
		}
		if (prefs.hex_irc_cap_server_time
			 && !strcmp (extension, "server-time"))
		{
			strcat (buffer, "server-time ");
		}
		
		/* if the SASL password is set AND auth mode is set to SASL, request SASL auth */
		if (serv->loginmethod == LOGIN_SASL
			 && strcmp (extension, "sasl") != 0
			 && strlen (serv->password) != 0)
		{
			strcat (buffer, "sasl ");
			want_cap = 1;
			want_sasl = 1;
		}
	}

	g_strfreev (extensions);

	if (want_cap)
	{
		/* buffer + 9 = emit buffer without "CAP REQ :" */
		EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPREQ, serv->server_session,
									  buffer + 9, NULL, NULL, NULL, 0,
									  tags_data->timestamp);
		tcp_sendf (serv, "%s\r\n", buffer);
	}
	if (!want_sasl)
	{
		/* if we use SASL, CAP END is dealt via raw numerics */
		tcp_send_len (serv, "CAP END\r\n", 9);
	}
}
Esempio n. 8
0
void
inbound_login_end (session *sess, char *text, const message_tags_data *tags_data)
{
	GSList *cmdlist;
	commandentry *cmd;
	server *serv = sess->server;

	if (!serv->end_of_motd)
	{
		if (prefs.hex_dcc_ip_from_server && serv->use_who)
		{
			serv->skip_next_userhost = TRUE;
			serv->p_get_ip_uh (serv, serv->nick);	/* sends USERHOST mynick */
		}
		set_default_modes (serv);

		if (serv->network)
		{
			/* there may be more than 1, separated by \n */

			cmdlist = ((ircnet *)serv->network)->commandlist;
			while (cmdlist)
			{
				cmd = cmdlist->data;
				inbound_exec_eom_cmd (cmd->command, sess);
				cmdlist = cmdlist->next;
			}

			/* send nickserv password */
			if (((ircnet *)serv->network)->pass && inbound_nickserv_login (serv))
			{
				serv->p_ns_identify (serv, ((ircnet *)serv->network)->pass);
			}
		}

		/* wait for join if command or nickserv set */
		if (serv->network && prefs.hex_irc_join_delay
			&& ((((ircnet *)serv->network)->pass && inbound_nickserv_login (serv))
				|| ((ircnet *)serv->network)->commandlist))
		{
			serv->joindelay_tag = fe_timeout_add (prefs.hex_irc_join_delay * 1000, check_autojoin_channels, serv);
		}
		else
		{
			check_autojoin_channels (serv);
		}

		if (serv->supports_watch || serv->supports_monitor)
		{
			notify_send_watches (serv);
		}

		serv->end_of_motd = TRUE;
	}

	if (prefs.hex_irc_skip_motd && !serv->motd_skipped)
	{
		serv->motd_skipped = TRUE;
		EMIT_SIGNAL_TIMESTAMP (XP_TE_MOTDSKIP, serv->server_session, NULL, NULL,
									  NULL, NULL, 0, tags_data->timestamp);
		return;
	}

	EMIT_SIGNAL_TIMESTAMP (XP_TE_MOTD, serv->server_session, text, NULL, NULL,
								  NULL, 0, tags_data->timestamp);
}
Esempio n. 9
0
void
inbound_cap_ls (server *serv, char *nick, char *extensions_str,
					 const message_tags_data *tags_data)
{
	char buffer[500];	/* buffer for requesting capabilities and emitting the signal */
	gboolean want_cap = FALSE; /* format the CAP REQ string based on previous capabilities being requested or not */
	gboolean want_sasl = FALSE; /* CAP END shouldn't be sent when SASL is requested, it needs further responses */
	char **extensions;
	int i;

	if (g_str_has_prefix (extensions_str, "* "))
	{
		serv->waiting_on_cap = TRUE;
		extensions_str += 2;
		extensions_str += extensions_str[0] == ':' ? 1 : 0;
	}
	else
	{
		serv->waiting_on_cap = FALSE;
	}

	EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPLIST, serv->server_session, nick,
								  extensions_str, NULL, NULL, 0, tags_data->timestamp);

	extensions = g_strsplit (extensions_str, " ", 0);

	strcpy (buffer, "CAP REQ :");

	for (i=0; extensions[i]; i++)
	{
		char *extension = extensions[i];
		char *value;
		gsize x;

		/* CAP 3.2 can provide values */
		if ((value = strchr (extension, '=')))
		{
			*value = '\0';
			value++;
		}

		/* if the SASL password is set AND auth mode is set to SASL, request SASL auth */
		if (!g_strcmp0 (extension, "sasl") &&
			((serv->loginmethod == LOGIN_SASL && strlen (serv->password) != 0)
				|| (serv->loginmethod == LOGIN_SASLEXTERNAL && serv->have_cert)))
		{
			if (value)
			{
				int sasl_mech = get_supported_mech (serv, value);
				if (sasl_mech == -1) /* No supported mech */
					continue;
				serv->sasl_mech = sasl_mech;
			}
			want_cap = TRUE;
			want_sasl = TRUE;
			g_strlcat (buffer, "sasl ", sizeof(buffer));
			continue;
		}

		for (x = 0; x < G_N_ELEMENTS(supported_caps); ++x)
		{
			if (!g_strcmp0 (extension, supported_caps[x]))
			{
				g_strlcat (buffer, extension, sizeof(buffer));
				g_strlcat (buffer, " ", sizeof(buffer));
				want_cap = TRUE;
			}
		}
	}

	g_strfreev (extensions);

	if (want_cap)
	{
		/* buffer + 9 = emit buffer without "CAP REQ :" */
		EMIT_SIGNAL_TIMESTAMP (XP_TE_CAPREQ, serv->server_session,
									  buffer + 9, NULL, NULL, NULL, 0,
									  tags_data->timestamp);
		tcp_sendf (serv, "%s\r\n", g_strchomp (buffer));
	}
	if (!want_sasl && !serv->waiting_on_cap)
	{
		/* if we use SASL, CAP END is dealt via raw numerics */
		serv->sent_capend = TRUE;
		tcp_send_len (serv, "CAP END\r\n", 9);
	}
}
Esempio n. 10
0
void
ctcp_handle (session *sess, char *to, char *nick, char *ip,
				 char *msg, char *word[], char *word_eol[], int id,
				 const message_tags_data *tags_data)
{
	char *po;
	session *chansess;
	server *serv = sess->server;
	char outbuf[1024];
	int ctcp_offset = 2;

	if (serv->have_idmsg && (word[4][1] == '+' || word[4][1] == '-') )
			ctcp_offset = 3;

	/* consider DCC to be different from other CTCPs */
	if (!g_ascii_strncasecmp (msg, "DCC", 3))
	{
		/* but still let CTCP replies override it */
		if (!ctcp_check (sess, nick, word, word_eol, word[4] + ctcp_offset))
		{
			if (!ignore_check (word[1], IG_DCC))
				handle_dcc (sess, nick, word, word_eol, tags_data);
		}
		return;
	}

	/* consider ACTION to be different from other CTCPs. Check
      ignore as if it was a PRIV/CHAN. */
	if (!g_ascii_strncasecmp (msg, "ACTION ", 7))
	{
		if (is_channel (serv, to))
		{
			/* treat a channel action as a CHAN */
			if (ignore_check (word[1], IG_CHAN))
				return;
		} else
		{
			/* treat a private action as a PRIV */
			if (ignore_check (word[1], IG_PRIV))
				return;
		}

		/* but still let CTCP replies override it */
		if (ctcp_check (sess, nick, word, word_eol, word[4] + ctcp_offset))
			goto generic;

		inbound_action (sess, to, nick, ip, msg + 7, FALSE, id, tags_data);
		return;
	}

	if (ignore_check (word[1], IG_CTCP))
		return;

	if (!g_ascii_strcasecmp (msg, "VERSION") && !prefs.hex_irc_hide_version)
	{
#ifdef WIN32
		g_snprintf (outbuf, sizeof (outbuf), "VERSION HexChat "PACKAGE_VERSION" [x%d] / %s",
					 get_cpu_arch (), get_sys_str (1));
#else
		g_snprintf (outbuf, sizeof (outbuf), "VERSION HexChat "PACKAGE_VERSION" / %s",
					 get_sys_str (1));
#endif
		serv->p_nctcp (serv, nick, outbuf);
	}

	if (word[4][1] == '\0')
		return;

	if (!ctcp_check (sess, nick, word, word_eol, word[4] + ctcp_offset))
	{
		if (!g_ascii_strncasecmp (msg, "SOUND", 5))
		{
			po = strchr (word[5], '\001');
			if (po)
				po[0] = 0;

			if (is_channel (sess->server, to))
			{
				chansess = find_channel (sess->server, to);
				if (!chansess)
					chansess = sess;

				EMIT_SIGNAL_TIMESTAMP (XP_TE_CTCPSNDC, chansess, word[5],
											  nick, to, NULL, 0, tags_data->timestamp);
			} else
			{
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CTCPSND, sess->server->front_session,
											  word[5], nick, NULL, NULL, 0,
											  tags_data->timestamp);
			}

			/* don't let IRCers specify path */
#ifdef WIN32
			if (strchr (word[5], '/') == NULL && strchr (word[5], '\\') == NULL)
#else
			if (strchr (word[5], '/') == NULL)
#endif
				sound_play (word[5], TRUE);
			return;
		}
	}

generic:
	po = strchr (msg, '\001');
	if (po)
		po[0] = 0;

	if (!is_channel (sess->server, to))
	{
		EMIT_SIGNAL_TIMESTAMP (XP_TE_CTCPGEN, sess->server->front_session, msg,
									  nick, NULL, NULL, 0, tags_data->timestamp);
	} else
	{
		chansess = find_channel (sess->server, to);
		if (!chansess)
			chansess = sess;
		EMIT_SIGNAL_TIMESTAMP (XP_TE_CTCPGENC, chansess, msg, nick, to, NULL, 0,
									  tags_data->timestamp);
	}
}
Esempio n. 11
0
void
handle_mode (server * serv, char *word[], char *word_eol[],
				 char *nick, int numeric_324, const message_tags_data *tags_data)
{
	session *sess;
	char *chan;
	char *modes;
	char *argstr;
	char sign;
	int len;
	size_t arg;
	size_t i, num_args;
	int num_modes;
	size_t offset = 3;
	int all_modes_have_args = FALSE;
	int using_front_tab = FALSE;
	mode_run mr;

	mr.serv = serv;
	mr.op = mr.deop = mr.voice = mr.devoice = NULL;

	/* numeric 324 has everything 1 word later (as opposed to MODE) */
	if (numeric_324)
		offset++;

	chan = word[offset];
	modes = word[offset + 1];
	if (*modes == ':')
		modes++;

	if (*modes == 0)
		return;	/* beyondirc's blank modes */

	sess = find_channel (serv, chan);
	if (!sess)
	{
		sess = serv->front_session;
		using_front_tab = TRUE;
	}
	/* remove trailing space */
	len = strlen (word_eol[offset]) - 1;
	if (word_eol[offset][len] == ' ')
		word_eol[offset][len] = 0;

	if (prefs.hex_irc_raw_modes && !numeric_324)
		EMIT_SIGNAL_TIMESTAMP (XP_TE_RAWMODES, sess, nick, word_eol[offset], 0, 0, 0,
									  tags_data->timestamp);

	if (numeric_324 && !using_front_tab)
	{
		if (sess->current_modes)
			free (sess->current_modes);
		sess->current_modes = strdup (word_eol[offset+1]);
	}

	sign = *modes;
	modes++;
	arg = 1;

	/* count the number of arguments (e.g. after the -o+v) */
	num_args = 0;
	i = 1;
	while ((i + offset + 1) < PDIWORDS)
	{
		i++;
		if (!(*word[i + offset]))
			break;
		num_args++;
	}

	/* count the number of modes (without the -/+ chars */
	num_modes = 0;
	i = 0;
	while (i < strlen (modes))
	{
		if (modes[i] != '+' && modes[i] != '-')
			num_modes++;
		i++;
	}

	if (num_args == num_modes)
		all_modes_have_args = TRUE;

	while (*modes)
	{
		switch (*modes)
		{
		case '-':
		case '+':
			/* print all the grouped Op/Deops */
			mode_print_grouped (sess, nick, &mr, tags_data);
			sign = *modes;
			break;
		default:
			argstr = "";
			if ((all_modes_have_args || mode_has_arg (serv, sign, *modes)) && arg < (num_args + 1))
			{
				arg++;
				argstr = word[arg + offset];
			}
			handle_single_mode (&mr, sign, *modes, nick, chan,
									  argstr, numeric_324 || prefs.hex_irc_raw_modes,
									  numeric_324, tags_data);
		}

		modes++;
	}

	/* update the title at the end, now that the mode update is internal now */
	if (!using_front_tab)
		fe_set_title (sess);

	/* print all the grouped Op/Deops */
	mode_print_grouped (sess, nick, &mr, tags_data);
}
Esempio n. 12
0
static void
handle_single_mode (mode_run *mr, char sign, char mode, char *nick,
						  char *chan, char *arg, int quiet, int is_324,
						  const message_tags_data *tags_data)
{
	session *sess;
	server *serv = mr->serv;
	char outbuf[4];
	char *cm = serv->chanmodes;
	gboolean supportsq = FALSE;

	outbuf[0] = sign;
	outbuf[1] = 0;
	outbuf[2] = mode;
	outbuf[3] = 0;

	sess = find_channel (serv, chan);
	if (!sess || !is_channel (serv, chan))
	{
		/* got modes for a chan we're not in! probably nickmode +isw etc */
		sess = serv->front_session;
		goto genmode;
	}

	/* is this a nick mode? */
	if (strchr (serv->nick_modes, mode))
	{
		/* update the user in the userlist */
		userlist_update_mode (sess, /*nickname */ arg, mode, sign);
	} else
	{
		if (!is_324 && !sess->ignore_mode && mode_chanmode_type(serv, mode) >= 1)
			record_chan_mode (sess, sign, mode, arg);
	}

	/* Is q a chanmode on this server? */
	if (cm)
		while (*cm)
		{
			if (*cm == ',')
				break;
			if (*cm == 'q')
				supportsq = TRUE;
			cm++;
		}

	switch (sign)
	{
	case '+':
		switch (mode)
		{
		case 'k':
			safe_strcpy (sess->channelkey, arg, sizeof (sess->channelkey));
			fe_update_channel_key (sess);
			fe_update_mode_buttons (sess, mode, sign);
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANSETKEY, sess, nick, arg, NULL,
											  NULL, 0, tags_data->timestamp);
			return;
		case 'l':
			sess->limit = atoi (arg);
			fe_update_channel_limit (sess);
			fe_update_mode_buttons (sess, mode, sign);
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANSETLIMIT, sess, nick, arg, NULL,
											  NULL, 0, tags_data->timestamp);
			return;
		case 'o':
			if (!quiet)
				mr->op = mode_cat (mr->op, arg);
			return;
		case 'h':
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANHOP, sess, nick, arg, NULL, NULL,
											  0, tags_data->timestamp);
			return;
		case 'v':
			if (!quiet)
				mr->voice = mode_cat (mr->voice, arg);
			return;
		case 'b':
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANBAN, sess, nick, arg, NULL, NULL,
											  0, tags_data->timestamp);
			return;
		case 'e':
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANEXEMPT, sess, nick, arg, NULL,
											  NULL, 0, tags_data->timestamp);
			return;
		case 'I':
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANINVITE, sess, nick, arg, NULL, NULL,
											  0, tags_data->timestamp);
			return;
		case 'q':
			if (!supportsq)
				break; /* +q is owner on this server */
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANQUIET, sess, nick, arg, NULL, NULL, 0,
								 tags_data->timestamp);
			return;
		}
		break;
	case '-':
		switch (mode)
		{
		case 'k':
			sess->channelkey[0] = 0;
			fe_update_channel_key (sess);
			fe_update_mode_buttons (sess, mode, sign);
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANRMKEY, sess, nick, NULL, NULL,
											  NULL, 0, tags_data->timestamp);
			return;
		case 'l':
			sess->limit = 0;
			fe_update_channel_limit (sess);
			fe_update_mode_buttons (sess, mode, sign);
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANRMLIMIT, sess, nick, NULL, NULL,
											  NULL, 0, tags_data->timestamp);
			return;
		case 'o':
			if (!quiet)
				mr->deop = mode_cat (mr->deop, arg);
			return;
		case 'h':
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANDEHOP, sess, nick, arg, NULL,
											  NULL, 0, tags_data->timestamp);
			return;
		case 'v':
			if (!quiet)
				mr->devoice = mode_cat (mr->devoice, arg);
			return;
		case 'b':
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANUNBAN, sess, nick, arg, NULL, NULL,
											  0, tags_data->timestamp);
			return;
		case 'e':
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANRMEXEMPT, sess, nick, arg, NULL,
											  NULL, 0, tags_data->timestamp);
			return;
		case 'I':
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANRMINVITE, sess, nick, arg, NULL,
											  NULL, 0, tags_data->timestamp);
			return;
		case 'q':
			if (!supportsq)
				break; /* -q is owner on this server */
			if (!quiet)
				EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANUNQUIET, sess, nick, arg, NULL,
											  NULL, 0, tags_data->timestamp);
			return;
		}
	}

	fe_update_mode_buttons (sess, mode, sign);

 genmode:
	/* Received umode +e. If we're waiting to send JOIN then send now! */
	if (mode == 'e' && sign == '+' && !serv->p_cmp (chan, serv->nick))
		inbound_identified (serv);

	if (!quiet)
	{
		if (*arg)
		{
			char *buf = malloc (strlen (chan) + strlen (arg) + 2);
			sprintf (buf, "%s %s", chan, arg);
			EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANMODEGEN, sess, nick, outbuf,
										  outbuf + 2, buf, 0, tags_data->timestamp);
			free (buf);
		} else
			EMIT_SIGNAL_TIMESTAMP (XP_TE_CHANMODEGEN, sess, nick, outbuf,
										  outbuf + 2, chan, 0, tags_data->timestamp);
	}
}