]>
Commit | Line | Data |
---|---|---|
1 | /* whois.c */ | |
2 | ||
3 | #include "miscreply.h" | |
4 | #include "../irc/irc.h" | |
5 | #include "../core/error.h" | |
6 | #include "../core/hooks.h" | |
7 | #include "../server/server.h" | |
8 | ||
9 | #include <string.h> | |
10 | ||
11 | ||
12 | ||
13 | /* do whois | |
14 | * | |
15 | */ | |
16 | static void do_whois(char *sourcenum, nick *snick, nick *tnick) { | |
17 | ||
18 | void *nicks[3]; /* nick array for whois channels hook */ | |
19 | ||
20 | ||
21 | /* user | |
22 | * | |
23 | * 311 RPL_WHOISUSER "source 311 target nick user host * :realname" | |
24 | * "irc.netsplit.net 311 foobar bar foo host.com * :foobar" | |
25 | */ | |
26 | /* sethost (usermode +h) */ | |
27 | if (IsSetHost(tnick)) { | |
28 | irc_send("%s 311 %s %s %s %s * :%s", getmynumeric(), sourcenum, tnick->nick, | |
29 | tnick->shident->content, tnick->sethost->content, tnick->realname->name->content); | |
30 | /* account and hiddenhost (usermode +rx) */ | |
31 | } else if (IsAccount(tnick) && IsHideHost(tnick)) { | |
32 | irc_send("%s 311 %s %s %s %s.%s * :%s", getmynumeric(), sourcenum, tnick->nick, | |
33 | tnick->ident, tnick->authname, HIS_HIDDENHOST, tnick->realname->name->content); | |
34 | /* not hidden */ | |
35 | } else { | |
36 | irc_send("%s 311 %s %s %s %s * :%s", getmynumeric(), sourcenum, tnick->nick, | |
37 | tnick->ident, tnick->host->name->content, tnick->realname->name->content); | |
38 | } | |
39 | ||
40 | ||
41 | /* channels | |
42 | * show channels only when | |
43 | * target user is not a service (usermode +k) AND | |
44 | * target user is not hidechan (usermode +n) | |
45 | * OR user WHOIS'ing himself | |
46 | */ | |
47 | if ((!IsService(tnick) && !IsHideChan(tnick) && canseeuser(snick, tnick)) || snick == tnick) { | |
48 | nicks[0] = (char *)snick; | |
49 | nicks[1] = (char *)tnick; | |
50 | nicks[2] = sourcenum; | |
51 | triggerhook(HOOK_NICK_WHOISCHANNELS, nicks); | |
52 | } | |
53 | ||
54 | ||
55 | /* server | |
56 | * | |
57 | * 312 RPL_WHOISSERVER "source 312 target nick server :description" | |
58 | * "irc.netsplit.net 312 foobar barfoo *.netsplit.net :Netsplit Server" | |
59 | */ | |
60 | /* show server and description when | |
61 | * user WHOIS'ing himself, OR to an IRC Operator, OR when HIS_SERVER is 0 | |
62 | */ | |
63 | if (snick == tnick || IsOper(snick) || !HIS_SERVER) { | |
64 | irc_send("%s 312 %s %s %s :%s", getmynumeric(), sourcenum, tnick->nick, | |
65 | serverlist[homeserver(tnick->numeric)].name->content, | |
66 | serverlist[homeserver(tnick->numeric)].description->content); | |
67 | /* show HIS server and description */ | |
68 | } else { | |
69 | irc_send("%s 312 %s %s %s :%s", getmynumeric(), sourcenum, tnick->nick, | |
70 | HIS_SERVERNAME, | |
71 | HIS_SERVERDESC); | |
72 | } | |
73 | ||
74 | ||
75 | /* target user is away */ | |
76 | if ((tnick)->away) { | |
77 | /* | |
78 | * 301 RPL_AWAY "source 301 target nick :awaymsg" | |
79 | * "irc.netsplit.net 301 foobar barfoo :afk." | |
80 | */ | |
81 | irc_send("%s 301 %s %s :%s", getmynumeric(), sourcenum, tnick->nick, tnick->away->content); | |
82 | } | |
83 | ||
84 | ||
85 | /* target user is an IRC Operator */ | |
86 | if (IsOper(tnick)) { | |
87 | /* | |
88 | * 313 RPL_WHOISOPERATOR "source 313 target nick :is an IRC Operator" | |
89 | * "irc.netsplit.net 313 foobar barfoo :is an IRC Operator" | |
90 | */ | |
91 | irc_send("%s 313 %s %s :is an IRC Operator", getmynumeric(), sourcenum, tnick->nick); | |
92 | ||
93 | /* source user is an IRC Operator, show opername if we have it */ | |
94 | if (IsOper(snick) && (tnick->opername && strcmp(tnick->opername->content, "-"))) | |
95 | /* | |
96 | * 343 RPL_WHOISOPERNAME "source 343 target nick opername :is opered as" | |
97 | * "irc.netsplit.net 343 foobar barfoo fish :is opered as" | |
98 | * | |
99 | * note: snircd extension | |
100 | */ | |
101 | irc_send("%s 343 %s %s %s :is opered as", getmynumeric(), sourcenum, tnick->nick, tnick->opername->content); | |
102 | } | |
103 | ||
104 | ||
105 | ||
106 | /* target user got an account (usermode +r) */ | |
107 | if (IsAccount(tnick)) { | |
108 | /* | |
109 | * 330 RPL_WHOISACCOUNT "source 330 target nick account :is authed as" | |
110 | * "irc.netsplit.net 330 foobar barfoo fish :is authed as" | |
111 | * | |
112 | * note: ircu shows "is logged in as" as text | |
113 | */ | |
114 | irc_send("%s 330 %s %s %s :is authed as", getmynumeric(), sourcenum, tnick->nick, tnick->authname); | |
115 | } | |
116 | ||
117 | ||
118 | ||
119 | /* target user got a sethost (usermode +h) or has a hiddenhost (usermode +rx) | |
120 | * show real host to user WHOIS'ing himself and to an IRC Operator | |
121 | */ | |
122 | if ((snick == tnick || IsOper(snick)) && (IsSetHost(tnick) || (IsAccount(tnick) && IsHideHost(tnick)) )) { | |
123 | /* | |
124 | * 338 RPL_WHOISACTUALLY "source 338 target nick user@host IP :Actual user@host, Actual IP" | |
125 | * "irc.netsplit.net 338 foobar barfoo foobar@localhost 127.0.0.1 :Actual user@host, Actual IP" | |
126 | */ | |
127 | irc_send("%s 338 %s %s %s@%s %s :Actual user@host, Actual IP", getmynumeric(), sourcenum, tnick->nick, | |
128 | tnick->ident, tnick->host->name->content, IPtostr(tnick->ipaddress)); | |
129 | } | |
130 | ||
131 | ||
132 | ||
133 | /* my user, | |
134 | * AND not a service (usermode +k), AND not hiding idle time (usermode +I) | |
135 | * show idle and signon time | |
136 | */ | |
137 | if (mylongnum == homeserver(tnick->numeric) && !IsService(tnick) && !IsHideIdle(tnick)) { | |
138 | /* | |
139 | * 317 RPL_WHOISIDLE "source 317 target nick idle signon :seconds idle, signon time" | |
140 | * "irc.netsplit.net 317 foobar barfoo 5 1084458353" | |
141 | */ | |
142 | irc_send("%s 317 %s %s %ld %ld :seconds idle, signon time", getmynumeric(), sourcenum, tnick->nick, | |
143 | (getnettime() - tnick->timestamp) % (((tnick->numeric + tnick->timestamp) % 983) + 7), tnick->timestamp); | |
144 | } | |
145 | } | |
146 | ||
147 | ||
148 | ||
149 | /* handle remote whois request | |
150 | * | |
151 | * <source numeric> WHOIS/W <target server numeric> <nick> | |
152 | * | |
153 | * cargv[0] = target server numeric | |
154 | * cargv[1] = nick as given by source | |
155 | * comma separated list of one or more nicks, may contain wildcards | |
156 | * ircu does not do wildcard matches for remote whois, we dont either | |
157 | * | |
158 | */ | |
159 | int handlewhoismsg(void *source, int cargc, char **cargv) { | |
160 | ||
161 | nick *snick; /* struct nick for source nick */ | |
162 | nick *tnick; /* struct nick for target nick */ | |
163 | char *sourcenum = (char *)source; /* source user numeric */ | |
164 | char nicks[BUFSIZE]; /* nick parameter */ | |
165 | char *nick; /* loop nick */ | |
166 | ||
167 | /* check parameters */ | |
168 | if (cargc < 2) { | |
169 | miscreply_needmoreparams(sourcenum, "WHOIS"); | |
170 | return CMD_OK; | |
171 | } | |
172 | ||
173 | /* get the parameters */ | |
174 | strcpy(nicks, cargv[1]); | |
175 | ||
176 | /* find source user */ | |
177 | if (!(snick = miscreply_finduser(sourcenum, "WHOIS"))) | |
178 | return CMD_OK; | |
179 | ||
180 | /* go through the list of nicks */ | |
181 | for (nick = strtok(nicks, ","); nick != NULL; nick = strtok(NULL, ",")) { | |
182 | ||
183 | /* find the target */ | |
184 | if (!(tnick = getnickbynick(nick))) { | |
185 | /* | |
186 | * 401 ERR_NOSUCHNICK "source 401 target nick :No such nick" | |
187 | * "irc.netsplit.net 391 foobar barfoo :No such nick" | |
188 | */ | |
189 | irc_send("%s 401 %s %s :No such nick", getmynumeric(), sourcenum, nick); | |
190 | } | |
191 | ||
192 | else | |
193 | do_whois(sourcenum, snick, tnick); | |
194 | } | |
195 | ||
196 | ||
197 | /* end of | |
198 | * | |
199 | * 318 RPL_ENDOFWHOIS "source 318 target nick :End of /WHOIS list." | |
200 | * "irc.netsplit.net 318 foobar barfoo :End of /WHOIS list." | |
201 | */ | |
202 | irc_send("%s 318 %s %s :End of /WHOIS list.", getmynumeric(), sourcenum, cargv[1]); | |
203 | ||
204 | return CMD_OK; | |
205 | } |