Relation Relation::join(Relation r2) { // Combine the schemes and make a new empty relation that uses the combined schemes Relation join_result = Relation("temp_join"); join_result.scheme = join_scheme(r2); // Find which attributes they have in common to prep for the join std::vector<std::pair<int, int>> common_attributes = get_common_attributes(r2); for (Tuple t1 : this->tuples) { for (Tuple t2 : r2.tuples) { if (common_attributes.size() > 0) { // Check if the tuples can join bool join = can_join(t1, t2, common_attributes); if (join) { // Build the joined tuple and add it to the new relation Tuple t = join_tuples(t1, t2, common_attributes); join_result.tuples.insert(t); } } else { Tuple t = do_product(t1, t2); join_result.tuples.insert(t); } } } return join_result; }
static int cb_join(aClient *sptr, aChannel *chptr, char *parv[]) { aModeB *p = NULL; if (!can_join(sptr, sptr, chptr, NULL, NULL, parv)) /* test for operoverride or invite */ { return HOOK_CONTINUE; } if (chptr->mode.extmode & EXTCMODE_BANLINK) /* mode +B set? */ { if (is_banned(sptr, chptr, BANCHK_JOIN)) /* user is banned? */ { p = (aModeB *) extcmode_get_struct(chptr->mode.extmodeparam, 'B'); if (p && p->val) { sendto_one(sptr, ":%s 470 %s %s (you are banned) transferring you to %s", me.name, sptr->name, chptr->chname, p->val); parv[0] = sptr->name; parv[1] = p->val; do_join(sptr, sptr, 2, parv); return HOOK_DENY; } } } return HOOK_CONTINUE; }
/* * m_lljoin * parv[0] = sender prefix * parv[1] = channel * parv[2] = nick ("!nick" == cjoin) * parv[3] = vchan/key (optional) * parv[4] = key (optional) * * If a lljoin is received, from our uplink, join * the requested client to the given channel, or ignore it * if there is an error. * * Ok, the way this works. Leaf client tries to join a channel, * it doesn't exist so the join does a cburst request on behalf of the * client, and aborts that join. The cburst sjoin's the channel if it * exists on the hub, and sends back an LLJOIN to the leaf. Thats where * this is now.. * */ static void ms_lljoin(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *chname = NULL; char *nick = NULL; char *key = NULL; char *vkey = NULL; int flags; int i; struct Client *target_p; struct Channel *chptr, *vchan_chptr, *root_vchan; #ifdef VCHANS int cjoin = 0; int vc_ts; char *pvc = NULL; #endif if(uplink && !IsCapable(uplink,CAP_LL)) { sendto_realops_flags(FLAGS_ALL, L_ALL, "*** LLJOIN requested from non LL server %s", client_p->name); return; } chname = parv[1]; if(chname == NULL) return; nick = parv[2]; if(nick == NULL) return; #ifdef VCHANS if (nick[0] == '!') { cjoin = 1; nick++; } if(parc > 4) { key = parv[4]; vkey = parv[3]; } #endif else if(parc >3) { key = vkey = parv[3]; } flags = 0; target_p = find_client(nick); if( !target_p || !target_p->user ) return; if( !MyClient(target_p) ) return; chptr = hash_find_channel(chname); #ifdef VCHANS if (cjoin) { if(!chptr) /* Uhm, bad! */ { sendto_realops_flags(FLAGS_ALL, L_ALL, "LLJOIN %s %s called by %s, but root chan doesn't exist!", chname, nick, client_p->name); return; } flags = CHFL_CHANOP; if(! (vchan_chptr = cjoin_channel(chptr, target_p, chname))) return; root_vchan = chptr; chptr = vchan_chptr; } else #endif { #ifdef VCHANS if (chptr) { vchan_chptr = select_vchan(chptr, target_p, vkey, chname); } else #endif { chptr = vchan_chptr = get_or_create_channel(target_p, chname, NULL); flags = CHFL_CHANOP; } #ifdef VCHANS if (vchan_chptr != chptr) { root_vchan = chptr; chptr = vchan_chptr; } else #endif root_vchan = chptr; if(!chptr || !root_vchan) return; if (chptr->users == 0) flags = CHFL_CHANOP; else flags = 0; /* XXX in m_join.c :( */ /* check_spambot_warning(target_p, chname); */ /* They _could_ join a channel twice due to lag */ if(chptr) { if (IsMember(target_p, chptr)) /* already a member, ignore this */ return; } else { sendto_one(target_p, form_str(ERR_UNAVAILRESOURCE), me.name, nick, root_vchan->chname); return; } if( (i = can_join(target_p, chptr, key)) ) { sendto_one(target_p, form_str(i), me.name, nick, root_vchan->chname); return; } } if ((target_p->user->joined >= ConfigChannel.max_chans_per_user) && (!IsOper(target_p) || (target_p->user->joined >= ConfigChannel.max_chans_per_user*3))) { sendto_one(target_p, form_str(ERR_TOOMANYCHANNELS), me.name, nick, root_vchan->chname ); return; } if(flags == CHFL_CHANOP) { chptr->channelts = CurrentTime; /* * XXX - this is a rather ugly hack. * * Unfortunately, there's no way to pass * the fact that it is a vchan through SJOIN... */ /* Prevent users creating a fake vchan */ #ifdef VCHANS if (chname[0] == '#' && chname[1] == '#') { if ((pvc = strrchr(chname+3, '_'))) { /* * OK, name matches possible vchan: * ##channel_blah */ pvc++; /* point pvc after last _ */ vc_ts = atol(pvc); /* * if blah is the same as the TS, up the TS * by one, to prevent this channel being * seen as a vchan */ if (vc_ts == CurrentTime) chptr->channelts++; } } #endif sendto_one(uplink, ":%s SJOIN %lu %s + :@%s", me.name, (unsigned long) chptr->channelts, chptr->chname, nick); } /* a user can create a channel with halfops..? */ #if 0 else if ((flags == CHFL_HALFOP) && (IsCapable(uplink, CAP_HOPS))) { sendto_one(uplink, ":%s SJOIN %lu %s + :%%%s", me.name, (unsigned long) chptr->channelts, chptr->chname, nick); } #endif else { sendto_one(uplink, ":%s SJOIN %lu %s + :%s", me.name, (unsigned long) chptr->channelts, chptr->chname, nick); } add_user_to_channel(chptr, target_p, flags); #ifdef VCHANS if ( chptr != root_vchan ) add_vchan_to_client_cache(target_p,root_vchan,chptr); #endif sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s", target_p->name, target_p->username, target_p->host, root_vchan->chname); if( flags & CHFL_CHANOP ) { chptr->mode.mode |= MODE_TOPICLIMIT; chptr->mode.mode |= MODE_NOPRIVMSGS; sendto_channel_local(ALL_MEMBERS,chptr, ":%s MODE %s +nt", me.name, root_vchan->chname); sendto_one(uplink, ":%s MODE %s +nt", me.name, chptr->chname); } channel_member_names(target_p, chptr, chname, 1); }
/* * m_lljoin * parv[0] = sender prefix * parv[1] = channel * parv[2] = nick ("!nick" == cjoin) * parv[3] = key (optional) * * If a lljoin is received, from our uplink, join * the requested client to the given channel, or ignore it * if there is an error. * * Ok, the way this works. Leaf client tries to join a channel, * it doesn't exist so the join does a cburst request on behalf of the * client, and aborts that join. The cburst sjoin's the channel if it * exists on the hub, and sends back an LLJOIN to the leaf. Thats where * this is now.. * */ static void ms_lljoin(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *chname = NULL; char *nick = NULL; char *key = NULL; int flags; int i; struct Client *target_p; struct Channel *chptr; if (uplink && !IsCapable(uplink,CAP_LL)) { sendto_realops_flags(UMODE_ALL, L_ALL, "*** LLJOIN requested from non LL server %s", client_p->name); return; } chname = parv[1]; if(chname == NULL) return; nick = parv[2]; if(nick == NULL) return; if (parc >3) key = parv[3]; flags = 0; target_p = find_person(client_p, nick); if (!target_p) return; if (!MyClient(target_p)) return; if (!check_channel_name(chname, 0)) { sendto_gnotice_flags(UMODE_DEBUG, L_ALL, me.name, &me, NULL, "*** Too long or invalid channel name from %s: %s", target_p->name, chname); return; } chptr = make_channel(chname); flags = CHFL_CHANOP; if(!chptr) return; if (dlink_list_length(&chptr->members) == 0) flags = CHFL_CHANOP; else flags = 0; /* XXX in m_join.c :( */ /* check_spambot_warning(target_p, chname); */ /* They _could_ join a channel twice due to lag */ if(chptr) { if (IsMember(target_p, chptr)) /* already a member, ignore this */ return; } else { sendto_one(target_p, form_str(ERR_UNAVAILRESOURCE), me.name, nick, chptr->chname); return; } if ((i = can_join(target_p, chptr, key))) { sendto_one(target_p, form_str(i), me.name, nick, chptr->chname); return; } if ((dlink_list_length(&target_p->channel) >= ConfigChannel.max_chans_per_user) && (!IsOper(target_p) || (dlink_list_length(&target_p->channel) >= ConfigChannel.max_chans_per_user*3))) { sendto_one(target_p, form_str(ERR_TOOMANYCHANNELS), me.name, nick, chptr->chname ); return; } if (flags == CHFL_CHANOP) { chptr->channelts = CurrentTime; sendto_one(uplink, ":%s SJOIN %lu %s + :@%s", me.name, (unsigned long) chptr->channelts, chptr->chname, nick); } sendto_one(uplink, ":%s SJOIN %lu %s + :%s", me.name, (unsigned long) chptr->channelts, chptr->chname, nick); add_user_to_channel(chptr, target_p, flags, YES); sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s JOIN :%s", target_p->name, target_p->username, target_p->host, chptr->chname); if (flags & CHFL_CHANOP) { chptr->mode.mode |= MODE_TOPICLIMIT; chptr->mode.mode |= MODE_NOPRIVMSGS; sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s MODE %s +nt", me.name, chptr->chname); sendto_one(uplink, ":%s MODE %s +nt", me.name, chptr->chname); } channel_member_names(target_p, chptr, 1); }
/* * m_join * parv[0] = sender prefix * parv[1] = channel * parv[2] = channel password (key) */ static void m_join(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Channel *chptr = NULL; char *name, *key = NULL; int i, flags = 0; char *p = NULL, *p2 = NULL; int successful_join_count = 0; /* Number of channels successfully joined */ if (*parv[1] == '\0') { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "JOIN"); return; } if (parc > 2) { key = strtoken(&p2, parv[2], ","); } for (name = strtoken(&p, parv[1], ","); name; key = (key) ? strtoken(&p2, NULL, ",") : NULL, name = strtoken(&p, NULL, ",")) { if(!check_channel_name(name)) { sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name, source_p->name, (unsigned char*)name); continue; } /* ** JOIN 0 sends out a part for all channels a user ** has joined. ** ** this should be either disabled or selectable in ** config file .. it's abused a lot more than it's ** used these days :/ --is */ if (*name == '0' && !atoi(name)) { if (source_p->user->channel.head == NULL) continue; do_join_0(&me,source_p); continue; } /* check it begins with # or & */ else if(!IsChannelName(name)) { sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), me.name, source_p->name, name); continue; } if(ConfigServerHide.disable_local_channels && (*name == '&')) { sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), me.name, source_p->name, name); continue; } /* check the length */ if (strlen(name) > CHANNELLEN) { sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name, source_p->name, name); continue; } /* see if its resv'd */ if(find_channel_resv(name) && (!IsOper(source_p) || !ConfigChannel.no_oper_resvs)) { sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE), me.name, source_p->name, name); sendto_realops_flags(UMODE_SPY, L_ALL, "User %s (%s@%s) is attempting to join locally juped channel %s", source_p->name, source_p->username, source_p->host, name); continue; } /* look for the channel */ if((chptr = hash_find_channel(name)) != NULL) { if(IsMember(source_p, chptr)) return; if(splitmode && !IsOper(source_p) && (*name != '&') && ConfigChannel.no_join_on_split) { sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE), me.name, source_p->name, name); continue; } if (chptr->users == 0) flags = CHFL_CHANOP; else flags = 0; } else { if(splitmode && !IsOper(source_p) && (*name != '&') && (ConfigChannel.no_create_on_split || ConfigChannel.no_join_on_split)) { sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE), me.name, source_p->name, name); continue; } flags = CHFL_CHANOP; } if ((source_p->user->joined >= ConfigChannel.max_chans_per_user) && (!IsOper(source_p) || (source_p->user->joined >= ConfigChannel.max_chans_per_user*3))) { sendto_one(source_p, form_str(ERR_TOOMANYCHANNELS), me.name, parv[0], name); if(successful_join_count) source_p->localClient->last_join_time = CurrentTime; return; } if(flags == 0) /* if channel doesn't exist, don't penalize */ successful_join_count++; if(chptr == NULL) /* If I already have a chptr, no point doing this */ { chptr = get_or_create_channel(source_p, name, NULL); } if(chptr == NULL) { sendto_one(source_p, form_str(ERR_UNAVAILRESOURCE), me.name, parv[0], name); if(successful_join_count > 0) successful_join_count--; continue; } if (!IsOper(source_p)) check_spambot_warning(source_p, name); /* can_join checks for +i key, bans etc */ if ( (i = can_join(source_p, chptr, key)) ) { sendto_one(source_p, form_str(i), me.name, parv[0], name); if(successful_join_count > 0) successful_join_count--; continue; } /* add the user to the channel */ add_user_to_channel(chptr, source_p, flags); /* we send the user their join here, because we could have to * send a mode out next. */ sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s", source_p->name, source_p->username, source_p->host, chptr->chname); /* if theyre joining opped (ie, new chan or joining one thats * persisting) then set timestamp to current, set +nt and * broadcast the sjoin with its old modes, or +nt. */ if (flags & CHFL_CHANOP) { char mbuf[MODEBUFLEN]; char pbuf[MODEBUFLEN]; chptr->channelts = CurrentTime; chptr->mode.mode |= MODE_TOPICLIMIT; chptr->mode.mode |= MODE_NOPRIVMSGS; sendto_channel_local(ONLY_CHANOPS, chptr, ":%s MODE %s +nt", me.name, chptr->chname); if(*chptr->chname == '#') { channel_modes(chptr, source_p, mbuf, pbuf); strlcat(mbuf, " ", sizeof(mbuf)); if(pbuf[0] != '\0') strlcat(mbuf, pbuf, sizeof(mbuf)); /* note: mbuf here will have a trailing space. we add one above, * and channel_modes() will leave a trailing space on pbuf if * its used --fl */ sendto_server(client_p, chptr, NOCAPS, NOCAPS, ":%s SJOIN %lu %s %s:@%s", me.name, (unsigned long) chptr->channelts, chptr->chname, mbuf, parv[0]); } /* drop our +beI modes */ free_channel_list(&chptr->banlist); free_channel_list(&chptr->exceptlist); free_channel_list(&chptr->invexlist); } else { sendto_server(client_p, chptr, NOCAPS, NOCAPS, ":%s SJOIN %lu %s + :%s", me.name, (unsigned long) chptr->channelts, chptr->chname, parv[0]); } del_invite(chptr, source_p); if (chptr->topic != NULL) { sendto_one(source_p, form_str(RPL_TOPIC), me.name, parv[0], chptr->chname, chptr->topic); sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name, parv[0], chptr->chname, chptr->topic_info, chptr->topic_time); } channel_member_names(source_p, chptr, chptr->chname, 1); if(successful_join_count) source_p->localClient->last_join_time = CurrentTime; } }