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 }