]> jfr.im git - irc/rizon/acid.git/blob - acid/src/main/java/net/rizon/acid/core/User.java
c3accd5a320ca01eb2ff375c20a313cda456ae33
[irc/rizon/acid.git] / acid / src / main / java / net / rizon / acid / core / User.java
1 package net.rizon.acid.core;
2
3 import java.net.InetAddress;
4 import java.sql.PreparedStatement;
5 import java.sql.ResultSet;
6 import java.sql.SQLException;
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.HashMap;
10 import java.util.HashSet;
11 import java.util.Hashtable;
12 import java.util.Iterator;
13 import java.util.Set;
14 import net.rizon.acid.conf.AccessPreset;
15 import net.rizon.acid.events.EventUserMode;
16 import org.slf4j.Logger;
17 import org.slf4j.LoggerFactory;
18
19 public class User implements Comparable<User>
20 {
21 private static final Logger log = LoggerFactory.getLogger(User.class);
22
23 private String nick, user, host, vhost, name, identnick, modes, UID, ip,
24 certfp, authflags, su, snomask;
25 private String cloakedIp, cloakedHost;
26 private int nickTS, conTS;
27 private Server server;
28 private String flags; // Access flags
29 private ArrayList<String> oldNicks;
30 private Hashtable<String, ArrayList<Integer>> chans;
31 private HashSet<Channel> chanList;
32 private InetAddress cgisockhost;
33 private String cgihost;
34
35 public User(String nick, String user, String host, String vhost, String name,
36 Server server, int nickTS, int conTS, String modes, String UID, String ip)
37 {
38 this.nick = nick;
39 this.user = user;
40 this.host = host;
41 this.vhost = vhost;
42 this.host = host;
43 this.name = name;
44 this.server = server;
45 this.identnick = "";
46 this.nickTS = nickTS;
47 this.conTS = conTS;
48 this.modes = modes;
49 this.UID = UID;
50 this.ip = ip;
51 // Check if this IP isn't spoofed.
52 if (!isSpoofed())
53 {
54 // Cloak IP if IP is visible host, else cloak hostname.
55 this.cloakedIp = Acidictive.cloakGenerator.cloak(this.ip);
56 if (this.ip.equals(this.host))
57 {
58 this.cloakedHost = this.cloakedIp;
59 }
60 else
61 {
62 this.cloakedHost = Acidictive.cloakGenerator.cloak(this.host);
63 }
64 }
65 else
66 {
67 this.cloakedIp = this.ip;
68 this.cloakedHost = this.host;
69 }
70 this.flags = "";
71 this.certfp = "";
72 this.authflags = "";
73 this.su = "";
74
75 /*
76 * i'm not sure if this is just how plexus handles it
77 * or if it's irc protocol for empty snomasks.
78 *
79 * -!- Mode change [-s] for user kristina
80 * -!- + Server notice mask
81 */
82 this.snomask = "+";
83
84 oldNicks = new ArrayList<String>();
85 chans = new Hashtable<String, ArrayList<Integer>>();
86 chanList = new HashSet<Channel>();
87
88 uidMap.put(UID, this);
89 nickMap.put(nick.toLowerCase(), this);
90
91 this.getServer().incUsers();
92 }
93
94 public final boolean isSpoofed()
95 {
96 return this.ip.equals("255.255.255.255") || this.ip.equals("0");
97 }
98
99 public void setSnomask(String s)
100 {
101 /* see comment in ctor */
102 if (s == null || s.isEmpty())
103 snomask = "+";
104 else
105 snomask = s;
106 }
107
108 public String getSnomask()
109 {
110 return snomask;
111 }
112
113 public void onQuit()
114 {
115 for (Iterator<Channel> it = chanList.iterator(); it.hasNext();)
116 {
117 Channel chan = it.next();
118 chan.removeUser(this);
119 it.remove();
120 }
121
122 this.getServer().decUsers();
123 if (!(this instanceof AcidUser))
124 UserList.decreaseHost(this.ip);
125
126 uidMap.remove(UID);
127 nickMap.remove(nick.toLowerCase());
128 }
129
130 public void flush()
131 {
132 oldNicks.clear();
133 chans.clear();
134 }
135
136 public void clearFlood()
137 {
138 if (chans != null)
139 chans.clear();
140 }
141
142 public ArrayList<Integer> addChanJoinPart(String chan, int TS)
143 {
144 ArrayList<Integer> x = chans.get(chan.toLowerCase());
145 if (x == null)
146 {
147 ArrayList<Integer> tmp = new ArrayList<Integer>();
148 tmp.add(new Integer(TS));
149 chans.put(chan.toLowerCase(), tmp);
150 return tmp;
151 }
152 else
153 {
154 x.add(new Integer(TS));
155 if (x.size() > 4)
156 x.remove(0);
157 return x;
158 }
159
160 }
161
162 public boolean isOnChan(Channel chan)
163 {
164 return chanList.contains(chan);
165 }
166
167 public void addChan(Channel chan)
168 {
169 chanList.add(chan);
170 }
171
172 public void remChan(Channel chan)
173 {
174 chanList.remove(chan);
175 }
176
177 public Set<Channel> getChannels()
178 {
179 return this.chanList;
180 }
181
182 public String getChanStr()
183 {
184 StringBuilder sb = new StringBuilder();
185
186 for (Channel c : chanList)
187 {
188 if (sb.length() > 0)
189 sb.append(' ');
190
191 if (c.hasMode('s'))
192 sb.append('!');
193
194 sb.append(c.getName());
195 }
196
197 if (sb.length() == 0)
198 return "none";
199
200 return sb.toString();
201 }
202
203 public void setRealhost(String ip, String host)
204 {
205 this.ip = ip;
206 this.host = host;
207 }
208
209 public void setFlags(String flags)
210 {
211 this.flags = flags;
212 }
213
214 public void setUID(String uid)
215 {
216 this.UID = uid;
217 }
218
219 public void changeNick(String newNick)
220 {
221 String oldnick = this.getNick();
222
223 nickMap.remove(this.getNick().toLowerCase());
224 oldNicks.add(this.getNick());
225 if (oldNicks.size() > 20)
226 oldNicks.remove(0);
227 this.nick = newNick;
228 nickMap.put(this.getNick().toLowerCase(), this);
229
230 this.setMode("-r");
231
232 for (Channel chan : chanList)
233 {
234 chan.onNick(oldnick, this.getNick());
235 }
236 }
237
238 // accessor methods
239 public String getIdentNick()
240 {
241 return identnick;
242 }
243
244 public String getIP()
245 {
246 return ip;
247 }
248
249 public String getNick()
250 {
251 return nick;
252 }
253
254 public boolean hasMode(String mode)
255 {
256 return modes.contains(mode);
257 }
258
259 public void setMode(String mode)
260 {
261 if (mode.equals("") || mode == null)
262 return;
263
264 String old = modes;
265
266 boolean plus = true;
267 String chr;
268 for (int x = 0; x < mode.length(); x++)
269 {
270 chr = mode.substring(x, x + 1);
271 if (chr.equals("+"))
272 {
273 plus = true;
274 }
275 else if (chr.equals("-"))
276 {
277 plus = false;
278 }
279 else if (plus && modes.indexOf(chr) == -1)
280 {
281 modes += chr;
282 }
283 else if (!plus && modes.indexOf(chr) >= 0)
284 {
285 if (chr.equals("x"))
286 this.vhost = this.host;
287 modes = modes.replaceAll(chr, "");
288 }
289 }
290
291 EventUserMode event = new EventUserMode();
292 event.setNewmodes(modes);
293 event.setOldmodes(old);
294 event.setUser(this);
295 Acidictive.eventBus.post(event);
296 }
297
298 public String getUser()
299 {
300 return user;
301 }
302
303 public void setUser(String user)
304 {
305 this.user = user;
306 }
307
308 public String getUID()
309 {
310 return UID;
311 }
312
313 public String getHost()
314 {
315 return host;
316 }
317
318 public String getVhost()
319 {
320 return vhost;
321 }
322
323 public void setVhost(String vhost)
324 {
325 this.vhost = vhost;
326 }
327
328 public String getRealName()
329 {
330 return name;
331 }
332
333 public int getNickTS()
334 {
335 return nickTS;
336 }
337
338 public int getConTS()
339 {
340 return conTS;
341 }
342
343 public void changeNickTS(int nickTS)
344 {
345 this.nickTS = nickTS;
346 }
347
348 public Server getServer()
349 {
350 return server;
351 }
352
353 /* Does this user have all of these flags? Can also take a type (SRA/SA/SO/whatever) */
354 public boolean hasFlags(String flags)
355 {
356 if (flags.isEmpty())
357 return false;
358
359 String my_flags = this.flags;
360
361 for (AccessPreset p : Acidictive.conf.access_preset)
362 {
363 for (String s : p.name)
364 {
365 my_flags = my_flags.replace(s, p.privileges);
366 flags = flags.replace(s, p.privileges);
367 }
368 }
369
370 for (int i = 0; i < flags.length(); ++i)
371 if (my_flags.indexOf(flags.charAt(i)) == -1)
372 return false;
373
374 return true;
375 }
376
377 public String getCloakedIp()
378 {
379 return this.cloakedIp;
380 }
381
382 public String getCloakedHost()
383 {
384 return this.cloakedHost;
385 }
386
387 public String getFlags()
388 {
389 return this.flags;
390 }
391
392 public String getModes()
393 {
394 return modes;
395 }
396
397 public String getCertFP()
398 {
399 return certfp;
400 }
401
402 public void setCertFP(String certfp)
403 {
404 this.certfp = certfp;
405 }
406
407 public String getAuthFlags()
408 {
409 return authflags;
410 }
411
412 public void setAuthFlags(String authflags)
413 {
414 this.authflags = authflags;
415 }
416
417 public void setCgisockhost(InetAddress cgisockhost)
418 {
419 this.cgisockhost = cgisockhost;
420 }
421
422 public void setCgihost(String cgihost)
423 {
424 this.cgihost = cgihost;
425 }
426
427 public InetAddress getCgisockhost()
428 {
429 return this.cgisockhost;
430 }
431
432 public String getCgihost()
433 {
434 return cgihost;
435 }
436
437 public String getSU()
438 {
439 return su;
440 }
441
442 public void setSU(String su)
443 {
444 this.su = su;
445 }
446
447 @Override
448 public int compareTo(User user)
449 {
450 return nick.compareTo(user.getNick());
451 }
452
453 @Override
454 public String toString()
455 {
456 return nick + "!" + user + "@" + host + "/" + ip + "/" + this.cloakedIp + "/" + this.cloakedHost + "/" + "(" + name + ")[" + server + "] / " + oldNicksList();
457 }
458
459 public String getNickString()
460 {
461 return nick + "!" + user + "@" + host + "/" + ip + "/" + this.cloakedIp + "/" + this.cloakedHost + "/" + vhost + "(" + name + ")";
462 }
463
464 public String getSNString()
465 {
466 return nick + "!" + user + "@" + host;
467 }
468
469 public String getNString()
470 {
471 return nick + "!" + user + "@" + host + "/" + ip + "/" + this.cloakedIp + "/" + this.cloakedHost + "/" + vhost + "(" + name + ")(" + modes + ")[" + server + "]";
472 }
473
474 public String getNStringON()
475 {
476 return nick + "!" + user + "@" + host + "/" + ip + "/" + this.cloakedIp + "/" + this.cloakedHost + "/" + vhost + "(" + name + ")(" + modes + ")[" + server + "] / " + oldNicksList();
477 }
478
479 public String getNickLine()
480 {
481 return getNick() + "!" + getUser() + "@" + getHost() + "/" + getRealName();
482 }
483
484 public ArrayList<String> oldNicks()
485 {
486 return oldNicks == null ? new ArrayList<String>() : oldNicks;
487 }
488
489 public String oldNicksList()
490 {
491 if (oldNicks == null)
492 return "No nick changes.";
493 if (oldNicks.size() > 0)
494 {
495 StringBuffer sb = new StringBuffer();
496 for (int i = 0; i < oldNicks.size(); i++)
497 {
498 sb.append(oldNicks.get(i) + " -> ");
499 }
500 sb.append(nick);
501 return sb.toString();
502 }
503 return "No nick changes.";
504 }
505
506 public boolean isIdentified()
507 {
508 if (this.hasMode("r"))
509 return true;
510 return this.su != null && !this.su.isEmpty() && !this.su.equals("*") && !Character.isDigit(this.su.charAt(0));
511 }
512
513 // TODO: Fixme to make this either properly static or a "real" method
514 // XXX ??????????????????????????????????? wtf is this
515 public void loadAccess(final User user)
516 {
517 try
518 {
519 PreparedStatement ps = Acidictive.acidcore_sql.prepare("SELECT `user`, `flags` FROM `access` WHERE `user` = ?");
520 ps.setString(1, user.getSU());
521 ResultSet rs = Acidictive.acidcore_sql.executeQuery(ps);
522 if (rs.next())
523 {
524 String oldflags = this.flags;
525
526 this.flags = rs.getString("flags");
527 this.identnick = user.getSU();
528
529 if (oldflags.equals(this.flags) == false)
530 Acidictive.notice(this, "You have been logged in with flags " + this.flags);
531 }
532 }
533 catch (SQLException ex)
534 {
535 log.warn("Unable to load access for user", ex);
536 }
537 }
538
539 private static HashMap<String, User> uidMap = new HashMap<String, User>();
540 private static HashMap<String, User> nickMap = new HashMap<String, User>();
541
542 public static User findUser(final String nick)
543 {
544 if (nick != null && nick.isEmpty() == false && Character.isDigit(nick.charAt(0)))
545 return uidMap.get(nick);
546 return nickMap.get(nick.toLowerCase());
547 }
548
549 public static final Set<String> getUsers()
550 {
551 return nickMap.keySet();
552 }
553
554 public static Collection<User> getUsersC() { return nickMap.values(); }
555
556 public static final String toName(final String uid)
557 {
558 User u = findUser(uid);
559 if (u != null)
560 return u.getNick();
561 return uid;
562 }
563
564 public static int userCount()
565 {
566 return nickMap.size();
567 }
568
569 private static char[] currentUid = new char[] { 'A', 'A', 'A', 'A', 'A', '@' };
570
571 public static String generateUID()
572 {
573 for (int i = 5; i >= 0; --i)
574 {
575 if (currentUid[i] == 'Z')
576 {
577 currentUid[i] = '0';
578 break;
579 }
580 else if (currentUid[i] != '9')
581 {
582 currentUid[i]++;
583 break;
584 }
585 else
586 currentUid[i] = 'A';
587 }
588
589 return AcidCore.me.getSID() + new String(currentUid);
590 }
591 }