00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "stdinc.h"
00026 #include "tools.h"
00027 #include "handlers.h"
00028 #include "channel.h"
00029 #include "channel_mode.h"
00030 #include "client.h"
00031 #include "hash.h"
00032 #include "irc_string.h"
00033 #include "ircd.h"
00034 #include "numeric.h"
00035 #include "s_conf.h"
00036 #include "s_serv.h"
00037 #include "send.h"
00038 #include "list.h"
00039 #include "msg.h"
00040 #include "parse.h"
00041 #include "modules.h"
00042 #include "s_user.h"
00043
00044 static void m_list(struct Client *, struct Client *, int, char **);
00045 static void ms_list(struct Client *, struct Client *, int, char **);
00046 static void mo_list(struct Client *, struct Client *, int, char **);
00047
00048 struct Message list_msgtab = {
00049 "LIST", 0, 0, 0, 0, MFLG_SLOW, 0,
00050 {m_unregistered, m_list, ms_list, m_ignore, mo_list, m_ignore}
00051 };
00052
00053 #ifndef STATIC_MODULES
00054 void
00055 _modinit(void)
00056 {
00057 mod_add_cmd(&list_msgtab);
00058 add_isupport("ELIST", "CMNTU", -1);
00059 add_isupport("SAFELIST", NULL, -1);
00060 }
00061
00062 void
00063 _moddeinit(void)
00064 {
00065 mod_del_cmd(&list_msgtab);
00066 delete_isupport("ELIST");
00067 delete_isupport("SAFELIST");
00068 }
00069
00070 const char *_version = "$Revision: 33 $";
00071 #endif
00072
00073 static int
00074 has_wildcards(const char *s)
00075 {
00076 char c;
00077
00078 while ((c = *s++))
00079 if (IsMWildChar(c))
00080 return 1;
00081
00082 return 0;
00083 }
00084
00085 static void
00086 do_list(struct Client *source_p, int parc, char *parv[])
00087 {
00088 struct ListTask *lt;
00089 int no_masked_channels;
00090
00091 if (MyConnect(source_p))
00092 {
00093 if (source_p->localClient->list_task != NULL)
00094 {
00095 free_list_task(source_p->localClient->list_task, source_p);
00096 sendto_one(source_p, form_str(RPL_LISTEND), me.name, source_p->name);
00097 return;
00098 }
00099 }
00100
00101 lt = (struct ListTask *) MyMalloc(sizeof(struct ListTask));
00102 lt->users_max = UINT_MAX;
00103 lt->created_max = UINT_MAX;
00104 lt->topicts_max = UINT_MAX;
00105 if (MyConnect(source_p))
00106 source_p->localClient->list_task = lt;
00107 no_masked_channels = 1;
00108
00109 if (parc > 1)
00110 {
00111 char *opt, *save;
00112 dlink_list *list;
00113 int i, errors = 0;
00114
00115 for (opt = strtoken(&save, parv[1], ","); opt != NULL;
00116 opt = strtoken(&save, NULL, ","))
00117 switch (*opt)
00118 {
00119 case '<': if ((i = atoi(opt + 1)) > 0)
00120 lt->users_max = (unsigned int) i - 1;
00121 else
00122 errors = 1;
00123 break;
00124 case '>': if ((i = atoi(opt + 1)) >= 0)
00125 lt->users_min = (unsigned int) i + 1;
00126 else
00127 errors = 1;
00128 break;
00129 case '-': break;
00130 case 'C':
00131 case 'c': switch (*++opt)
00132 {
00133 case '<': if ((i = atoi(opt + 1)) >= 0)
00134 lt->created_max = (unsigned int) (CurrentTime
00135 - 60 * i);
00136 else
00137 errors = 1;
00138 break;
00139 case '>': if ((i = atoi(opt + 1)) >= 0)
00140 lt->created_min = (unsigned int) (CurrentTime
00141 - 60 * i);
00142 else
00143 errors = 1;
00144 break;
00145 default: errors = 1;
00146 }
00147 break;
00148 case 'T':
00149 case 't': switch (*++opt)
00150 {
00151 case '<': if ((i = atoi(opt + 1)) >= 0)
00152 lt->topicts_min = (unsigned int) (CurrentTime
00153 - 60 * i);
00154 else
00155 errors = 1;
00156 break;
00157 case '>': if ((i = atoi(opt + 1)) >= 0)
00158 lt->topicts_max = (unsigned int) (CurrentTime
00159 - 60 * i);
00160 else
00161 errors = 1;
00162 break;
00163 default: errors = 1;
00164 }
00165 break;
00166 default: if (*opt == '!')
00167 {
00168 list = <->hide_mask;
00169 opt++;
00170 }
00171 else list = <->show_mask;
00172
00173 if (has_wildcards(opt + !!IsChanPrefix(*opt)))
00174 {
00175 if (list == <->show_mask)
00176 no_masked_channels = 0;
00177 }
00178 else if (!IsChanPrefix(*opt))
00179 errors = 1;
00180 if (!errors)
00181 {
00182 char *s;
00183 DupString(s, opt);
00184 dlinkAdd(s, make_dlink_node(), list);
00185 }
00186 }
00187 if (errors)
00188 {
00189 free_list_task(lt, source_p);
00190 sendto_one(source_p, form_str(ERR_LISTSYNTAX),
00191 MyConnect(source_p) ? me.name : ID(&me),
00192 MyConnect(source_p) ? source_p->name : ID(source_p));
00193 return;
00194 }
00195 }
00196
00197
00198 if (MyConnect(source_p))
00199 dlinkAdd(source_p, make_dlink_node(), &listing_client_list);
00200 sendto_one(source_p, form_str(RPL_LISTSTART),
00201 MyConnect(source_p) ? me.name : ID(&me),
00202 MyConnect(source_p) ? source_p->name : ID(source_p));
00203 safe_list_channels(source_p, lt, no_masked_channels &&
00204 lt->show_mask.head != NULL, !MyConnect(source_p));
00205 }
00206
00207
00208
00209
00210
00211
00212 static void
00213 m_list(struct Client *client_p, struct Client *source_p,
00214 int parc, char *parv[])
00215 {
00216 static time_t last_used = 0;
00217
00218
00219
00220
00221 if (((last_used + ConfigFileEntry.pace_wait) > CurrentTime))
00222 {
00223 sendto_one(source_p,form_str(RPL_LOAD2HI),me.name,parv[0]);
00224 return;
00225 }
00226 else
00227 last_used = CurrentTime;
00228
00229
00230 if (uplink && IsCapable(uplink, CAP_LL))
00231 {
00232 if (parc < 2)
00233 sendto_one(uplink, ":%s LIST", source_p->name);
00234 else
00235 sendto_one(uplink, ":%s LIST %s", source_p->name, parv[1]);
00236 return;
00237 }
00238
00239 do_list(source_p, parc, parv);
00240 }
00241
00242
00243
00244
00245
00246
00247 static void
00248 mo_list(struct Client *client_p, struct Client *source_p,
00249 int parc, char *parv[])
00250 {
00251
00252
00253
00254
00255 if (uplink && IsCapable(uplink, CAP_LL))
00256 {
00257 if (parc < 2)
00258 sendto_one(uplink, ":%s LIST", source_p->name);
00259 else
00260 sendto_one(uplink, ":%s LIST %s", source_p->name, parv[1]);
00261 return;
00262 }
00263
00264 do_list(source_p, parc, parv);
00265 }
00266
00267
00268
00269
00270
00271
00272 static void
00273 ms_list(struct Client *client_p, struct Client *source_p,
00274 int parc, char *parv[])
00275 {
00276
00277 if (ServerInfo.hub)
00278 {
00279 if (!IsCapable(client_p->from, CAP_LL) && !MyConnect(source_p))
00280 return;
00281
00282 do_list(source_p, parc, parv);
00283 }
00284 }