unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

sajoin.c (7620B)

      1 /*
      2  *   IRC - Internet Relay Chat, src/modules/sajoin.c
      3  *   (C) 2004 The UnrealIRCd Team
      4  *
      5  *   See file AUTHORS in IRC package for additional names of
      6  *   the programmers.
      7  *
      8  *   This program is free software; you can redistribute it and/or modify
      9  *   it under the terms of the GNU General Public License as published by
     10  *   the Free Software Foundation; either version 1, or (at your option)
     11  *   any later version.
     12  *
     13  *   This program is distributed in the hope that it will be useful,
     14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  *   GNU General Public License for more details.
     17  *
     18  *   You should have received a copy of the GNU General Public License
     19  *   along with this program; if not, write to the Free Software
     20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     21  */
     22 
     23 #include "unrealircd.h"
     24 
     25 CMD_FUNC(cmd_sajoin);
     26 
     27 #define MSG_SAJOIN 	"SAJOIN"	
     28 
     29 ModuleHeader MOD_HEADER
     30   = {
     31 	"sajoin",
     32 	"5.0",
     33 	"command /sajoin", 
     34 	"UnrealIRCd Team",
     35 	"unrealircd-6",
     36     };
     37 
     38 MOD_INIT()
     39 {
     40 	CommandAdd(modinfo->handle, MSG_SAJOIN, cmd_sajoin, MAXPARA, CMD_USER|CMD_SERVER);
     41 	MARK_AS_OFFICIAL_MODULE(modinfo);
     42 	return MOD_SUCCESS;
     43 }
     44 
     45 MOD_LOAD()
     46 {
     47 	return MOD_SUCCESS;
     48 }
     49 
     50 MOD_UNLOAD()
     51 {
     52 	return MOD_SUCCESS;
     53 }
     54 
     55 static void log_sajoin(Client *client, MessageTag *mtags, Client *target, const char *channels)
     56 {
     57 	const char *issuer = command_issued_by_rpc(mtags);
     58 	if (issuer)
     59 	{
     60 		unreal_log(ULOG_INFO, "sacmds", "SAJOIN_COMMAND", client, "SAJOIN: $issuer used SAJOIN to make $target join $channels",
     61 			   log_data_string("issuer", issuer),
     62 			   log_data_client("target", target),
     63 			   log_data_string("channels", channels));
     64 	} else {
     65 		unreal_log(ULOG_INFO, "sacmds", "SAJOIN_COMMAND", client, "SAJOIN: $client used SAJOIN to make $target join $channels",
     66 			   log_data_client("target", target),
     67 			   log_data_string("channels", channels));
     68 	}
     69 }
     70 
     71 /* cmd_sajoin() - Lamego - Wed Jul 21 20:04:48 1999
     72    Copied off PTlink IRCd (C) PTlink coders team.
     73    Coded for Sadmin by Stskeeps
     74    also Modified by NiQuiL (niquil@programmer.net)
     75 	parv[1] - nick to make join
     76 	parv[2] - channel(s) to join
     77 */
     78 CMD_FUNC(cmd_sajoin)
     79 {
     80 	Client *target;
     81 	char request[BUFSIZE];
     82 	char jbuf[BUFSIZE];
     83 	int did_anything = 0;
     84 	int ntargets = 0;
     85 	int maxtargets = max_targets_for_command("SAJOIN");
     86 
     87 	if (parc < 3)
     88 	{
     89 		sendnumeric(client, ERR_NEEDMOREPARAMS, "SAJOIN");
     90 		return;
     91 	}
     92 
     93 	if (!(target = find_user(parv[1], NULL)))
     94 	{
     95 		sendnumeric(client, ERR_NOSUCHNICK, parv[1]);
     96 		return;
     97 	}
     98 
     99 	/* Is this user disallowed from operating on this victim at all? */
    100 	if (!IsULine(client) && !ValidatePermissionsForPath("sacmd:sajoin",client,target,NULL,NULL))
    101 	{
    102 		sendnumeric(client, ERR_NOPRIVILEGES);
    103 		return;
    104 	}
    105 
    106 	/* Broadcast so other servers can log it appropriately as an SAJOIN */
    107 	sendto_server(client, 0, 0, recv_mtags, ":%s SAJOIN %s %s", client->id, target->id, parv[2]);
    108 
    109 	/* If it's not for our client, then only log... */
    110 	if (!MyUser(target))
    111 	{
    112 		log_sajoin(client, recv_mtags, target, parv[2]);
    113 		return;
    114 	}
    115 
    116 	/* 'target' is our client... */
    117 
    118 	/* Can't this just use do_join() or something with a parameter to bypass some checks?
    119 	 * This duplicate code is damn ugly. Ah well..
    120 	 */
    121 	{
    122 		char *name, *p = NULL;
    123 		int parted = 0;
    124 	
    125 		*jbuf = 0;
    126 
    127 		/* Now works like cmd_join */
    128 		strlcpy(request, parv[2], sizeof(request));
    129 		for (name = strtoken(&p, request, ","); name; name = strtoken(&p, NULL, ","))
    130 		{
    131 			Channel *channel;
    132 			Membership *lp;
    133 			char mode = '\0';
    134 			char prefix = '\0';
    135 
    136 			if (++ntargets > maxtargets)
    137 			{
    138 				sendnumeric(client, ERR_TOOMANYTARGETS, name, maxtargets, "SAJOIN");
    139 				break;
    140 			}
    141 
    142 			mode = prefix_to_mode(*name);
    143 			if (mode)
    144 			{
    145 				prefix = *name;
    146 				name++; /* skip the prefix */
    147 			}
    148 
    149 			if (strlen(name) > CHANNELLEN)
    150 			{
    151 				sendnotice(client, "Channel name too long: %s", name);
    152 				continue;
    153 			}
    154 
    155 			if (*name == '0' && !atoi(name) && !mode)
    156 			{
    157 				strlcpy(jbuf, "0", sizeof(jbuf));
    158 				parted = 1;
    159 				continue;
    160 			}
    161 
    162 			if (!valid_channelname(name))
    163 			{
    164 				send_invalid_channelname(client, name);
    165 				continue;
    166 			}
    167 
    168 			channel = make_channel(name);
    169 
    170 			/* If this _specific_ channel is not permitted, skip it */
    171 			if (!IsULine(client) && !ValidatePermissionsForPath("sacmd:sajoin",client,target,channel,NULL))
    172 			{
    173 				sendnumeric(client, ERR_NOPRIVILEGES);
    174 				continue;
    175 			}
    176 
    177 			if (!parted && channel && (lp = find_membership_link(target->user->channel, channel)))
    178 			{
    179 				sendnumeric(client, ERR_USERONCHANNEL, target->name, name);
    180 				continue;
    181 			}
    182 			if (*jbuf)
    183 				strlcat(jbuf, ",", sizeof(jbuf));
    184 			if (prefix)
    185 				strlcat_letter(jbuf, prefix, sizeof(jbuf));
    186 			strlcat(jbuf, name, sizeof(jbuf));
    187 		}
    188 		if (!*jbuf)
    189 			return;
    190 
    191 		strlcpy(request, jbuf, sizeof(request));
    192 		*jbuf = 0;
    193 		for (name = strtoken(&p, request, ","); name; name = strtoken(&p, NULL, ","))
    194 		{
    195 			MessageTag *mtags = NULL;
    196 			const char *member_modes;
    197 			Channel *channel;
    198 			Membership *lp;
    199 			Hook *h;
    200 			int i = 0;
    201 			char mode = '\0';
    202 			char prefix = '\0';
    203 
    204 			mode = prefix_to_mode(*name);
    205 			if (mode != '\0')
    206 			{
    207 				/* Yup, it was a real prefix. */
    208 				prefix = *name;
    209 				name++;
    210 			}
    211 
    212 			if (*name == '0' && !atoi(name) && !mode)
    213 			{
    214 				/* Rewritten so to generate a PART for each channel to servers,
    215 				 * so the same msgid is used for each part on all servers. -- Syzop
    216 				 */
    217 				did_anything = 1;
    218 				while ((lp = target->user->channel))
    219 				{
    220 					MessageTag *mtags = NULL;
    221 					channel = lp->channel;
    222 
    223 					new_message(target, NULL, &mtags);
    224 					mtag_add_issued_by(&mtags, client, recv_mtags);
    225 					sendto_channel(channel, target, NULL, 0, 0, SEND_LOCAL, mtags,
    226 					               ":%s PART %s :%s",
    227 					               target->name, channel->name, "Left all channels");
    228 					sendto_server(NULL, 0, 0, mtags, ":%s PART %s :Left all channels", target->name, channel->name);
    229 					if (MyConnect(target))
    230 						RunHook(HOOKTYPE_LOCAL_PART, target, channel, mtags, "Left all channels");
    231 					free_message_tags(mtags);
    232 					remove_user_from_channel(target, channel, 0);
    233 				}
    234 				strlcpy(jbuf, "0", sizeof(jbuf));
    235 				continue;
    236 			}
    237 			member_modes = (ChannelExists(name)) ? "" : LEVEL_ON_JOIN;
    238 			channel = make_channel(name);
    239 			if (channel && (lp = find_membership_link(target->user->channel, channel)))
    240 				continue;
    241 
    242 			i = HOOK_CONTINUE;
    243 			for (h = Hooks[HOOKTYPE_CAN_SAJOIN]; h; h = h->next)
    244 			{
    245 				i = (*(h->func.intfunc))(target,channel,client);
    246 				if (i != HOOK_CONTINUE)
    247 					break;
    248 			}
    249 
    250 			if (i == HOOK_DENY)
    251 				continue; /* process next channel */
    252 
    253 			/* Generate a new message without inheritance.
    254 			 * We can do this because we are the server that
    255 			 * will send a JOIN for each channel due to this loop.
    256 			 * Each with their own unique msgid.
    257 			 */
    258 			new_message(target, NULL, &mtags);
    259 			mtag_add_issued_by(&mtags, client, recv_mtags);
    260 			join_channel(channel, target, mtags, member_modes);
    261 			if (prefix)
    262 			{
    263 				char *modes;
    264 				const char *mode_args[3];
    265 
    266 				opermode = 0;
    267 				sajoinmode = 1;
    268 
    269 				modes = safe_alloc(2);
    270 				modes[0] = mode;
    271 
    272 				mode_args[0] = modes;
    273 				mode_args[1] = target->name;
    274 				mode_args[2] = 0;
    275 
    276 				do_mode(channel, target, NULL, 3, mode_args, 0, 1);
    277 
    278 				sajoinmode = 0;
    279 				safe_free(modes);
    280 			}
    281 			free_message_tags(mtags);
    282 			did_anything = 1;
    283 			if (*jbuf)
    284 				strlcat(jbuf, ",", sizeof jbuf);
    285 			strlcat(jbuf, name, sizeof jbuf);
    286 		}
    287 
    288 		//if (did_anything)
    289 		//{
    290 		//	sendnotice(target, "*** You were forced to join %s", jbuf);
    291 		//	log_sajoin(client, recv_mtags, target, jbuf);
    292 		//}
    293 	}
    294 }