+ /* Lost the TS, other side wins, so remove modes on this side */
+ if(!keep_our_modes)
+ {
+ remove_our_modes(chptr, fakesource_p);
+ RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->invites.head)
+ {
+ del_invite(chptr, ptr->data);
+ }
+
+ if(rb_dlink_list_length(&chptr->banlist) > 0)
+ remove_ban_list(chptr, fakesource_p, &chptr->banlist, 'b', ALL_MEMBERS);
+ if(rb_dlink_list_length(&chptr->exceptlist) > 0)
+ remove_ban_list(chptr, fakesource_p, &chptr->exceptlist,
+ 'e', ONLY_CHANOPS);
+ if(rb_dlink_list_length(&chptr->invexlist) > 0)
+ remove_ban_list(chptr, fakesource_p, &chptr->invexlist,
+ 'I', ONLY_CHANOPS);
+ if(rb_dlink_list_length(&chptr->quietlist) > 0)
+ remove_ban_list(chptr, fakesource_p, &chptr->quietlist,
+ 'q', ALL_MEMBERS);
+ chptr->bants++;
+
+ sendto_channel_local(ALL_MEMBERS, chptr,
+ ":%s NOTICE %s :*** Notice -- TS for %s changed from %ld to %ld",
+ me.name, chptr->chname, chptr->chname,
+ (long) oldts, (long) newts);
+ /* Update capitalization in channel name, this makes the
+ * capitalization timestamped like modes are -- jilles */
+ strcpy(chptr->chname, parv[2]);
+ }
+
+ if(*modebuf != '\0')
+ sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s %s %s",
+ fakesource_p->name, chptr->chname, modebuf, parabuf);
+
+ if(*omodebuf != '\0')
+ sendto_channel_local(ONLY_OPERS, chptr, ":%s MODE %s %s %s",
+ fakesource_p->name, chptr->chname, omodebuf, parabuf);
+
+ *omodebuf = *modebuf = *parabuf = '\0';
+
+ if(parv[3][0] != '0' && keep_new_modes)
+ modes = channel_modes(chptr, source_p);
+ else
+ modes = empty_modes;
+
+ mlen_uid = rb_sprintf(buf_uid, ":%s SJOIN %ld %s %s :",
+ use_id(source_p), (long) chptr->channelts, parv[2], modes);
+ ptr_uid = buf_uid + mlen_uid;
+
+ mbuf = modebuf;
+ ombuf = omodebuf;
+ para[0] = para[1] = para[2] = para[3] = empty;
+ pargs = 0;
+ len_nick = len_uid = 0;
+
+ /* if theres a space, theres going to be more than one nick, change the
+ * first space to \0, so s is just the first nick, and point p to the
+ * second nick
+ */
+ if((p = strchr(s, ' ')) != NULL)
+ {
+ *p++ = '\0';
+ }
+
+ *mbuf++ = '+';
+
+ while (s)
+ {
+ fl = 0;
+
+ for (i = 0; i < 2; i++)
+ {
+ if(*s == '!')
+ {
+ fl |= CHFL_ADMIN;
+ s++;
+ }
+ else if(*s == '@')
+ {
+ fl |= CHFL_CHANOP;
+ s++;
+ }
+ else if(*s == '%')
+ {
+ fl |= CHFL_HALFOP;
+ s++;
+ }
+ else if(*s == '+')
+ {
+ fl |= CHFL_VOICE;
+ s++;
+ }
+ }
+
+ /* if the client doesnt exist or is fake direction, skip. */
+ if(!(target_p = find_client(s)) ||
+ (target_p->from != client_p) || !IsPerson(target_p))
+ goto nextnick;
+
+ /* we assume for these we can fit at least one nick/uid in.. */
+
+ /* check we can fit another status+nick+space into a buffer */
+ if((mlen_uid + len_uid + IDLEN + 3) > (BUFSIZE - 3))
+ {
+ *(ptr_uid - 1) = '\0';
+ sendto_server(client_p->from, NULL, CAP_TS6, NOCAPS, "%s", buf_uid);
+ ptr_uid = buf_uid + mlen_uid;
+ len_uid = 0;
+ }
+
+ if(keep_new_modes)
+ {
+ if(fl & CHFL_ADMIN)
+ {
+ *ptr_uid++ = '!';
+ len_nick++;
+ len_uid++;
+ }
+ if(fl & CHFL_CHANOP)
+ {
+ *ptr_uid++ = '@';
+ len_nick++;
+ len_uid++;
+ }
+ if(fl & CHFL_HALFOP)
+ {
+ *ptr_uid++ = '%';
+ len_nick++;
+ len_uid++;
+ }
+ if(fl & CHFL_VOICE)
+ {
+ *ptr_uid++ = '+';
+ len_nick++;
+ len_uid++;
+ }
+ }
+
+ /* copy the nick to the two buffers */
+ len = rb_sprintf(ptr_uid, "%s ", use_id(target_p));
+ ptr_uid += len;
+ len_uid += len;
+
+ if(!keep_new_modes)
+ fl = 0;
+
+ if(!IsMember(target_p, chptr))
+ {
+ add_user_to_channel(chptr, target_p, fl);
+ sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
+ target_p->name,
+ target_p->username, target_p->host, parv[2]);
+ joins++;
+ }
+
+ /* If anyone can think of a way to do this that doesn't make babies cry
+ * I would love to hear it - Taros */
+
+ if(fl & CHFL_ADMIN)
+ {
+ *mbuf++ = 'a';
+ para[pargs++] = target_p->name;
+
+ if(fl & CHFL_CHANOP)
+ {
+ /* its possible the +a has filled up MAXMODEPARAMS, if so, start
+ * a new buffer
+ */
+ if(pargs >= MAXMODEPARAMS)
+ {
+ *mbuf = '\0';
+ sendto_channel_local(ALL_MEMBERS, chptr,
+ ":%s MODE %s %s %s %s %s %s",
+ fakesource_p->name, chptr->chname,
+ modebuf,
+ para[0], para[1], para[2], para[3]);
+ mbuf = modebuf;
+ *mbuf++ = '+';
+ para[0] = para[1] = para[2] = para[3] = NULL;
+ pargs = 0;
+ }
+
+ *mbuf++ = 'o';
+ para[pargs++] = target_p->name;
+ }
+ if(fl & CHFL_HALFOP)
+ {
+ /* its possible the +a has filled up MAXMODEPARAMS, if so, start
+ * a new buffer
+ */
+ if(pargs >= MAXMODEPARAMS)
+ {
+ *mbuf = '\0';
+ sendto_channel_local(ALL_MEMBERS, chptr,
+ ":%s MODE %s %s %s %s %s %s",
+ fakesource_p->name, chptr->chname,
+ modebuf,
+ para[0], para[1], para[2], para[3]);
+ mbuf = modebuf;
+ *mbuf++ = '+';
+ para[0] = para[1] = para[2] = para[3] = NULL;
+ pargs = 0;
+ }
+
+ *mbuf++ = 'h';
+ para[pargs++] = target_p->name;
+ }
+ if(fl & CHFL_VOICE)
+ {
+ /* its possible the +a has filled up MAXMODEPARAMS, if so, start
+ * a new buffer
+ */
+ if(pargs >= MAXMODEPARAMS)
+ {
+ *mbuf = '\0';
+ sendto_channel_local(ALL_MEMBERS, chptr,
+ ":%s MODE %s %s %s %s %s %s",
+ fakesource_p->name, chptr->chname,
+ modebuf,
+ para[0], para[1], para[2], para[3]);
+ mbuf = modebuf;
+ *mbuf++ = '+';
+ para[0] = para[1] = para[2] = para[3] = NULL;
+ pargs = 0;
+ }
+
+ *mbuf++ = 'v';
+ para[pargs++] = target_p->name;
+ }