unrealircd- supernets unrealircd source & configuration |
git clone git://git.acid.vegas/unrealircd.git |
Log | Files | Refs | Archive | README | LICENSE |
part.c (5644B)
1 /* 2 * IRC - Internet Relay Chat, src/modules/part.c 3 * (C) 2005 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_part); 26 27 #define MSG_PART "PART" 28 29 ModuleHeader MOD_HEADER 30 = { 31 "part", 32 "5.0", 33 "command /part", 34 "UnrealIRCd Team", 35 "unrealircd-6", 36 }; 37 38 MOD_INIT() 39 { 40 CommandAdd(modinfo->handle, MSG_PART, cmd_part, 2, CMD_USER); 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 /* 56 ** cmd_part 57 ** parv[1] = channel 58 ** parv[2] = comment (added by Lefler) 59 */ 60 CMD_FUNC(cmd_part) 61 { 62 char request[BUFSIZE]; 63 Channel *channel; 64 Membership *lp; 65 char *p = NULL, *name; 66 const char *commentx = (parc > 2 && parv[2]) ? parv[2] : NULL; 67 const char *comment; 68 int n; 69 int ntargets = 0; 70 int maxtargets = max_targets_for_command("PART"); 71 72 if (parc < 2 || parv[1][0] == '\0') 73 { 74 sendnumeric(client, ERR_NEEDMOREPARAMS, "PART"); 75 return; 76 } 77 78 if (MyUser(client)) 79 { 80 if (IsShunned(client)) 81 commentx = NULL; 82 if (STATIC_PART) 83 { 84 if (!strcasecmp(STATIC_PART, "yes") || !strcmp(STATIC_PART, "1")) 85 commentx = NULL; 86 else if (!strcasecmp(STATIC_PART, "no") || !strcmp(STATIC_PART, "0")) 87 ; /* keep original reason */ 88 else 89 commentx = STATIC_PART; 90 } 91 if (commentx) 92 { 93 if (match_spamfilter(client, commentx, SPAMF_PART, "PART", parv[1], 0, NULL)) 94 commentx = NULL; 95 if (IsDead(client)) 96 return; 97 } 98 } 99 100 strlcpy(request, parv[1], sizeof(request)); 101 for (name = strtoken(&p, request, ","); name; name = strtoken(&p, NULL, ",")) 102 { 103 MessageTag *mtags = NULL; 104 105 if (MyUser(client) && (++ntargets > maxtargets)) 106 { 107 sendnumeric(client, ERR_TOOMANYTARGETS, name, maxtargets, "PART"); 108 break; 109 } 110 111 channel = find_channel(name); 112 if (!channel) 113 { 114 sendnumeric(client, ERR_NOSUCHCHANNEL, name); 115 continue; 116 } 117 118 /* 'commentx' is the general part msg, but it can be changed 119 * per-channel (eg some chans block badwords, strip colors, etc) 120 * so we copy it to 'comment' and use that in this for loop :) 121 */ 122 comment = commentx; 123 124 if (!(lp = find_membership_link(client->user->channel, channel))) 125 { 126 /* Normal to get get when our client did a kick 127 ** for a remote client (who sends back a PART), 128 ** so check for remote client or not --Run 129 */ 130 if (MyUser(client)) 131 sendnumeric(client, ERR_NOTONCHANNEL, name); 132 continue; 133 } 134 135 if (!ValidatePermissionsForPath("channel:override:banpartmsg",client,NULL,channel,NULL) && !check_channel_access(client, channel, "oaq")) { 136 /* Banned? No comment allowed ;) */ 137 if (comment && is_banned(client, channel, BANCHK_MSG, &comment, NULL)) 138 comment = NULL; 139 if (comment && is_banned(client, channel, BANCHK_LEAVE_MSG, &comment, NULL)) 140 comment = NULL; 141 } 142 143 if (MyConnect(client)) 144 { 145 Hook *tmphook; 146 for (tmphook = Hooks[HOOKTYPE_PRE_LOCAL_PART]; tmphook; tmphook = tmphook->next) { 147 comment = (*(tmphook->func.stringfunc))(client, channel, comment); 148 if (!comment) 149 break; 150 } 151 } 152 153 /* Create a new message, this one is actually used by 8 calls (though at most 4 max) */ 154 new_message_special(client, recv_mtags, &mtags, ":%s PART %s", client->name, channel->name); 155 156 /* Send to other servers... */ 157 sendto_server(client, 0, 0, mtags, ":%s PART %s :%s", 158 client->id, channel->name, comment ? comment : ""); 159 160 if (invisible_user_in_channel(client, channel)) 161 { 162 /* Show PART only to chanops and self */ 163 if (!comment) 164 { 165 sendto_channel(channel, client, client, 166 "ho", 0, 167 SEND_LOCAL, mtags, 168 ":%s PART %s", 169 client->name, channel->name); 170 if (MyUser(client)) 171 { 172 sendto_one(client, mtags, ":%s!%s@%s PART %s", 173 client->name, client->user->username, GetHost(client), channel->name); 174 } 175 } 176 else 177 { 178 sendto_channel(channel, client, client, 179 "ho", 0, 180 SEND_LOCAL, mtags, 181 ":%s PART %s %s", 182 client->name, channel->name, comment); 183 if (MyUser(client)) 184 { 185 sendto_one(client, mtags, 186 ":%s!%s@%s PART %s %s", 187 client->name, client->user->username, GetHost(client), 188 channel->name, comment); 189 } 190 } 191 } 192 else 193 { 194 /* Show PART to all users in channel */ 195 if (!comment) 196 { 197 sendto_channel(channel, client, NULL, 0, 0, SEND_LOCAL, mtags, 198 ":%s PART %s", 199 client->name, channel->name); 200 } else { 201 sendto_channel(channel, client, NULL, 0, 0, SEND_LOCAL, mtags, 202 ":%s PART %s :%s", 203 client->name, channel->name, comment); 204 } 205 } 206 207 if (MyUser(client)) 208 RunHook(HOOKTYPE_LOCAL_PART, client, channel, mtags, comment); 209 else 210 RunHook(HOOKTYPE_REMOTE_PART, client, channel, mtags, comment); 211 212 free_message_tags(mtags); 213 214 remove_user_from_channel(client, channel, 0); 215 } 216 }