]> jfr.im git - irc/quakenet/newserv.git/blob - nterface/nterfacer_country.c
f91893abdebc57288b7eee43e33e4c62c841ae7f
[irc/quakenet/newserv.git] / nterface / nterfacer_country.c
1 /*
2 nterfacer newserv geoip country module
3 Copyright (C) 2004 Chris Porter.
4 */
5
6 #include "../nick/nick.h"
7 #include "../core/error.h"
8 #include "../core/config.h"
9 #include "../core/hooks.h"
10
11 #include "library.h"
12 #include "nterfacer_control.h"
13
14 #include "libGeoIP/GeoIP.h"
15
16 struct handler *hl = NULL, *hl2 = NULL;
17
18 #define COUNTRY_MIN 0
19 #define COUNTRY_MAX 246
20
21 unsigned int totals[COUNTRY_MAX + 1];
22 int country_nickext = -1;
23 GeoIP *gi = NULL;
24
25 void country_setupuser(nick *np);
26 int handle_countrytotals(struct rline *li, int argc, char **argv);
27 int handle_countrywhois(struct rline *li, int argc, char **argv);
28
29 void country_new_nick(int hook, void *args);
30 void country_quit(int hook, void *args);
31
32 void _init(void) {
33 int i;
34 nick *np;
35 sstring *filename;
36
37 if(!n_node) {
38 Error("nterfacer_country", ERR_ERROR, "Unable to register country as nterfacer_control isn't loaded!");
39 return;
40 }
41
42 filename = getcopyconfigitem("nterfacer", "geoipdb", "GeoIP.dat", 256);
43 gi = GeoIP_new(GEOIP_MEMORY_CACHE, filename->content);
44 freesstring(filename);
45
46 if(!gi)
47 return;
48
49 country_nickext = registernickext("nterfacer_country");
50 if(country_nickext == -1)
51 return; /* PPA: registerchanext produces an error, however the module should stop loading */
52
53 hl = register_handler(n_node, "countrytotals", 0, handle_countrytotals);
54 hl2 = register_handler(n_node, "countrywhois", 1, handle_countrywhois);
55 memset(totals, 0, sizeof(totals));
56
57 for(i=0;i<NICKHASHSIZE;i++) {
58 for(np=nicktable[i];np;np=np->next) {
59 country_setupuser(np);
60 }
61 }
62
63 registerhook(HOOK_NICK_LOSTNICK, &country_quit);
64 registerhook(HOOK_NICK_NEWNICK, &country_new_nick);
65 }
66
67 void _fini(void) {
68 if(gi)
69 GeoIP_delete(gi);
70
71 if(country_nickext == -1)
72 return;
73
74 releasenickext(country_nickext);
75
76 deregisterhook(HOOK_NICK_NEWNICK, &country_new_nick);
77 deregisterhook(HOOK_NICK_LOSTNICK, &country_quit);
78
79 if(hl2)
80 deregister_handler(hl2);
81 if(hl)
82 deregister_handler(hl);
83 }
84
85 int handle_countrytotals(struct rline *li, int argc, char **argv) {
86 int i;
87 for(i=COUNTRY_MIN;i<=COUNTRY_MAX;i++)
88 if(ri_append(li, "%d", totals[i]) == BF_OVER)
89 return ri_error(li, BF_OVER, "Buffer overflow.");
90
91 return ri_final(li);
92 }
93
94 void country_setupuser(nick *np) {
95 int country = GeoIP_id_by_ipnum(gi, np->ipaddress);
96 if((country < COUNTRY_MIN) || (country > COUNTRY_MAX))
97 return;
98
99 totals[country]++;
100 np->exts[country_nickext] = (void *)&totals[country];
101 }
102
103 void country_new_nick(int hook, void *args) {
104 country_setupuser((nick *)args);
105 }
106
107 void country_quit(int hook, void *args) {
108 nick *np = (nick *)args;
109
110 unsigned int *item;
111 if((item = (unsigned int *)np->exts[country_nickext]))
112 (*item)--;
113 }
114
115 int handle_countrywhois(struct rline *li, int argc, char **argv) {
116 int result;
117 char *longcountry, *shortcountry, *shortcountry3;
118 nick *np = getnickbynick(argv[0]);
119
120 if(!np)
121 return ri_error(li, ERR_TARGET_NOT_FOUND, "User not online");
122
123 result = GeoIP_id_by_ipnum(gi, np->ipaddress);
124 if((result < COUNTRY_MIN) || (result > COUNTRY_MAX))
125 result = -1;
126
127 if(!GeoIP_country_info_by_id(result, &shortcountry, &shortcountry3, &longcountry))
128 result = -1;
129
130 ri_append(li, "%d", result);
131
132 if(result == -1) {
133 ri_append(li, "%s", "!!");
134 ri_append(li, "%s", "!!");
135 ri_append(li, "%s", "Error");
136 } else {
137 ri_append(li, "%s", shortcountry);
138 ri_append(li, "%s", shortcountry3);
139 ri_append(li, "%s", longcountry);
140 }
141
142 return ri_final(li);
143 }
144