ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/channel.c
(Generate patch)

Comparing ircd-hybrid/trunk/src/channel.c (file contents):
Revision 3888 by michael, Fri Jun 6 18:22:02 2014 UTC vs.
Revision 3912 by michael, Sun Jun 8 13:10:20 2014 UTC

# Line 882 | Line 882 | set_channel_topic(struct Channel *chptr,
882    strlcpy(chptr->topic_info, topic_info, sizeof(chptr->topic_info));
883    chptr->topic_time = topicts;
884   }
885 +
886 + /* do_join_0()
887 + *
888 + * inputs       - pointer to client doing join 0
889 + * output       - NONE
890 + * side effects - Use has decided to join 0. This is legacy
891 + *                from the days when channels were numbers not names. *sigh*
892 + *                There is a bunch of evilness necessary here due to
893 + *                anti spambot code.
894 + */
895 + void
896 + channel_do_join_0(struct Client *source_p)
897 + {
898 +  dlink_node *ptr = NULL, *ptr_next = NULL;
899 +
900 +  if (source_p->channel.head)
901 +    if (MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER))
902 +      check_spambot_warning(source_p, NULL);
903 +
904 +  DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->channel.head)
905 +  {
906 +    struct Channel *chptr = ((struct Membership *)ptr->data)->chptr;
907 +
908 +    sendto_server(source_p, NOCAPS, NOCAPS, ":%s PART %s",
909 +                  source_p->id, chptr->chname);
910 +    sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s PART %s",
911 +                         source_p->name, source_p->username,
912 +                         source_p->host, chptr->chname);
913 +
914 +    remove_user_from_channel(ptr->data);
915 +  }
916 + }
917 +
918 + static char *
919 + channel_find_last0(struct Client *source_p, char *chanlist)
920 + {
921 +  int join0 = 0;
922 +
923 +  for (char *p = chanlist; *p; ++p)  /* Find last "JOIN 0" */
924 +  {
925 +    if (*p == '0' && (*(p + 1) == ',' || *(p + 1) == '\0'))
926 +    {
927 +      if ((*p + 1) == ',')
928 +        ++p;
929 +
930 +      chanlist = p + 1;
931 +      join0 = 1;
932 +    }
933 +    else
934 +    {
935 +      while (*p != ',' && *p != '\0')  /* Skip past channel name */
936 +        ++p;
937 +
938 +      if (*p == '\0')  /* Hit the end */
939 +        break;
940 +    }
941 +  }
942 +
943 +  if (join0)
944 +    channel_do_join_0(source_p);
945 +
946 +  return chanlist;
947 + }
948 +
949 + void
950 + channel_do_join(struct Client *source_p, char *parv[])
951 + {
952 +  char *p = NULL;
953 +  char *key_list = NULL;
954 +  char *chan_list = NULL;
955 +  char *chan = NULL;
956 +  struct Channel *chptr = NULL;
957 +  struct MaskItem *conf = NULL;
958 +  int i = 0;
959 +  unsigned int flags = 0;
960 +
961 +  key_list = parv[2];
962 +  chan_list = channel_find_last0(source_p, parv[1]);
963 +
964 +  for (chan = strtoken(&p, chan_list, ","); chan;
965 +       chan = strtoken(&p,      NULL, ","))
966 +  {
967 +    const char *key = NULL;
968 +
969 +    /* If we have any more keys, take the first for this channel. */
970 +    if (!EmptyString(key_list) && (key_list = strchr(key = key_list, ',')))
971 +      *key_list++ = '\0';
972 +
973 +    /* Empty keys are the same as no keys. */
974 +    if (key && *key == '\0')
975 +      key = NULL;
976 +
977 +    if (!check_channel_name(chan, 1))
978 +    {
979 +      sendto_one_numeric(source_p, &me, ERR_BADCHANNAME, chan);
980 +      continue;
981 +    }
982 +
983 +    if (!IsExemptResv(source_p) &&
984 +        !(HasUMode(source_p, UMODE_OPER) && ConfigFileEntry.oper_pass_resv) &&
985 +        ((conf = match_find_resv(chan)) && !resv_find_exempt(source_p, conf)))
986 +    {
987 +      ++conf->count;
988 +      sendto_one_numeric(source_p, &me, ERR_CHANBANREASON,
989 +                         chan, conf->reason ? conf->reason : "Reserved channel");
990 +      sendto_realops_flags(UMODE_SPY, L_ALL, SEND_NOTICE,
991 +                           "Forbidding reserved channel %s from user %s",
992 +                           chan, get_client_name(source_p, HIDE_IP));
993 +      continue;
994 +    }
995 +
996 +    if (dlink_list_length(&source_p->channel) >=
997 +        (HasUMode(source_p, UMODE_OPER) ?
998 +         ConfigChannel.max_chans_per_oper :
999 +         ConfigChannel.max_chans_per_user))
1000 +    {
1001 +      sendto_one_numeric(source_p, &me, ERR_TOOMANYCHANNELS, chan);
1002 +      break;
1003 +    }
1004 +
1005 +    if ((chptr = hash_find_channel(chan)))
1006 +    {
1007 +      if (IsMember(source_p, chptr))
1008 +        continue;
1009 +
1010 +      if (splitmode && !HasUMode(source_p, UMODE_OPER) &&
1011 +          ConfigChannel.no_join_on_split)
1012 +      {
1013 +        sendto_one_numeric(source_p, &me, ERR_UNAVAILRESOURCE, chan);
1014 +        continue;
1015 +      }
1016 +
1017 +      /*
1018 +       * can_join checks for +i key, bans.
1019 +       */
1020 +      if ((i = can_join(source_p, chptr, key)))
1021 +      {
1022 +        sendto_one_numeric(source_p, &me, i, chptr->chname);
1023 +        continue;
1024 +      }
1025 +
1026 +      /*
1027 +       * This should never be the case unless there is some sort of
1028 +       * persistant channels.
1029 +       */
1030 +      if (dlink_list_length(&chptr->members) == 0)
1031 +        flags = CHFL_CHANOP;
1032 +      else
1033 +        flags = 0;
1034 +    }
1035 +    else
1036 +    {
1037 +      if (splitmode && !HasUMode(source_p, UMODE_OPER) &&
1038 +          (ConfigChannel.no_create_on_split || ConfigChannel.no_join_on_split))
1039 +      {
1040 +        sendto_one_numeric(source_p, &me, ERR_UNAVAILRESOURCE, chan);
1041 +        continue;
1042 +      }
1043 +
1044 +      flags = CHFL_CHANOP;
1045 +      chptr = make_channel(chan);
1046 +    }
1047 +
1048 +    if (!HasUMode(source_p, UMODE_OPER))
1049 +      check_spambot_warning(source_p, chptr->chname);
1050 +
1051 +    add_user_to_channel(chptr, source_p, flags, 1);
1052 +
1053 +    /*
1054 +     *  Set timestamp if appropriate, and propagate
1055 +     */
1056 +    if (flags == CHFL_CHANOP)
1057 +    {
1058 +      chptr->channelts = CurrentTime;
1059 +      chptr->mode.mode |= MODE_TOPICLIMIT;
1060 +      chptr->mode.mode |= MODE_NOPRIVMSGS;
1061 +
1062 +      sendto_server(source_p, NOCAPS, NOCAPS, ":%s SJOIN %lu %s +nt :@%s",
1063 +                    me.id, (unsigned long)chptr->channelts,
1064 +                    chptr->chname, source_p->id);
1065 +
1066 +      /*
1067 +       * Notify all other users on the new channel
1068 +       */
1069 +      sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s JOIN :%s",
1070 +                           source_p->name, source_p->username,
1071 +                           source_p->host, chptr->chname);
1072 +      sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s +nt",
1073 +                           me.name, chptr->chname);
1074 +
1075 +      if (source_p->away[0])
1076 +        sendto_channel_local_butone(source_p, 0, CAP_AWAY_NOTIFY, chptr,
1077 +                                    ":%s!%s@%s AWAY :%s",
1078 +                                    source_p->name, source_p->username,
1079 +                                    source_p->host, source_p->away);
1080 +    }
1081 +    else
1082 +    {
1083 +      sendto_server(source_p, NOCAPS, NOCAPS, ":%s JOIN %lu %s +",
1084 +                    source_p->id, (unsigned long)chptr->channelts,
1085 +                    chptr->chname);
1086 +      sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s JOIN :%s",
1087 +                           source_p->name, source_p->username,
1088 +                           source_p->host, chptr->chname);
1089 +
1090 +      if (source_p->away[0])
1091 +        sendto_channel_local_butone(source_p, 0, CAP_AWAY_NOTIFY, chptr,
1092 +                                    ":%s!%s@%s AWAY :%s",
1093 +                                    source_p->name, source_p->username,
1094 +                                    source_p->host, source_p->away);
1095 +    }
1096 +
1097 +    del_invite(chptr, source_p);
1098 +
1099 +    if (chptr->topic[0])
1100 +    {
1101 +      sendto_one_numeric(source_p, &me, RPL_TOPIC, chptr->chname, chptr->topic);
1102 +      sendto_one_numeric(source_p, &me, RPL_TOPICWHOTIME, chptr->chname,
1103 +                         chptr->topic_info, chptr->topic_time);
1104 +    }
1105 +
1106 +    channel_member_names(source_p, chptr, 1);
1107 +
1108 +    source_p->localClient->last_join_time = CurrentTime;
1109 +  }
1110 + }
1111 +
1112 + /*! \brief Removes a client from a specific channel
1113 + * \param source_p Pointer to source client to remove
1114 + * \param name     Name of channel to remove from
1115 + * \param reason   Part reason to show
1116 + */
1117 + static void
1118 + channel_part_one_client(struct Client *source_p, const char *name, const char *reason)
1119 + {
1120 +  struct Channel *chptr = NULL;
1121 +  struct Membership *ms = NULL;
1122 +
1123 +  if ((chptr = hash_find_channel(name)) == NULL)
1124 +  {
1125 +    sendto_one_numeric(source_p, &me, ERR_NOSUCHCHANNEL, name);
1126 +    return;
1127 +  }
1128 +
1129 +  if ((ms = find_channel_link(source_p, chptr)) == NULL)
1130 +  {
1131 +    sendto_one_numeric(source_p, &me, ERR_NOTONCHANNEL, chptr->chname);
1132 +    return;
1133 +  }
1134 +
1135 +  if (MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER))
1136 +    check_spambot_warning(source_p, NULL);
1137 +
1138 +  /*
1139 +   * Remove user from the old channel (if any)
1140 +   * only allow /part reasons in -m chans
1141 +   */
1142 +  if (*reason && (!MyConnect(source_p) ||
1143 +      ((can_send(chptr, source_p, ms, reason) &&
1144 +       (source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time)
1145 +        < CurrentTime))))
1146 +  {
1147 +    sendto_server(source_p, NOCAPS, NOCAPS, ":%s PART %s :%s",
1148 +                  source_p->id, chptr->chname, reason);
1149 +    sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s PART %s :%s",
1150 +                         source_p->name, source_p->username,
1151 +                         source_p->host, chptr->chname, reason);
1152 +  }
1153 +  else
1154 +  {
1155 +    sendto_server(source_p, NOCAPS, NOCAPS, ":%s PART %s",
1156 +                  source_p->id, chptr->chname);
1157 +    sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s PART %s",
1158 +                         source_p->name, source_p->username,
1159 +                         source_p->host, chptr->chname);
1160 +  }
1161 +
1162 +  remove_user_from_channel(ms);
1163 + }
1164 +
1165 + void
1166 + channel_do_part(struct Client *source_p, char *parv[])
1167 + {
1168 +  char *p = NULL, *name = NULL;
1169 +  char reason[KICKLEN + 1] = "";
1170 +
1171 +  if (!EmptyString(parv[2]))
1172 +    strlcpy(reason, parv[2], sizeof(reason));
1173 +
1174 +  for (name = strtoken(&p, parv[1], ","); name;
1175 +       name = strtoken(&p,    NULL, ","))
1176 +    channel_part_one_client(source_p, name, reason);
1177 + }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines