]> jfr.im git - irc/quakenet/newserv.git/blob - geoip/libGeoIP/GeoIPCity.c
CHANSERV: remove accidental sendemail from SETEMAIL command.
[irc/quakenet/newserv.git] / geoip / libGeoIP / GeoIPCity.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
2 /* GeoIPCity.c
3 *
4 * Copyright (C) 2006 MaxMind LLC
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <GeoIP.h>
22 #include <GeoIP_internal.h>
23 #include <GeoIPCity.h>
24 #if !defined(WIN32) && !defined(WIN64)
25 #include <netdb.h>
26 #include <netinet/in.h> /* For ntohl */
27 #else
28 #include <windows.h>
29 #include <winsock.h>
30 #endif
31 #include <sys/types.h> /* For uint32_t */
32 #ifdef HAVE_STDINT_H
33 #include <stdint.h> /* For uint32_t */
34 #endif
35
36 static
37 const int FULL_RECORD_LENGTH = 50;
38
39 static
40 GeoIPRecord * _extract_record(GeoIP* gi, unsigned int seek_record, int *next_record_ptr) {
41 int record_pointer;
42 unsigned char *record_buf = NULL;
43 unsigned char *begin_record_buf = NULL;
44 GeoIPRecord * record;
45 int str_length = 0;
46 int j;
47 double latitude = 0, longitude = 0;
48 int metroarea_combo = 0;
49 int bytes_read = 0;
50 if (seek_record == gi->databaseSegments[0])
51 return NULL;
52
53 record = malloc(sizeof(GeoIPRecord));
54 memset(record, 0, sizeof(GeoIPRecord));
55
56 record->charset = gi->charset;
57
58 record_pointer = seek_record + (2 * gi->record_length - 1) * gi->databaseSegments[0];
59
60 if (gi->cache == NULL) {
61 fseek(gi->GeoIPDatabase, record_pointer, SEEK_SET);
62 begin_record_buf = record_buf = malloc(sizeof(char) * FULL_RECORD_LENGTH);
63 bytes_read = fread(record_buf, sizeof(char), FULL_RECORD_LENGTH, gi->GeoIPDatabase);
64 if (bytes_read == 0) {
65 /* eof or other error */
66 free(begin_record_buf);
67 free(record);
68 return NULL;
69 }
70 } else {
71 record_buf = gi->cache + (long)record_pointer;
72 }
73
74 /* get country */
75 record->continent_code = (char *) GeoIP_country_continent[record_buf[0]];
76 record->country_code = (char *) GeoIP_country_code [record_buf[0]];
77 record->country_code3 = (char *) GeoIP_country_code3[record_buf[0]];
78 record->country_name = (char *) GeoIP_country_name [record_buf[0]];
79 record_buf++;
80
81 /* get region */
82 while (record_buf[str_length] != '\0')
83 str_length++;
84 if (str_length > 0) {
85 record->region = malloc(str_length+1);
86 strncpy(record->region, record_buf, str_length+1);
87 }
88 record_buf += str_length + 1;
89 str_length = 0;
90
91 /* get city */
92 while (record_buf[str_length] != '\0')
93 str_length++;
94 if (str_length > 0) {
95 if ( gi->charset == GEOIP_CHARSET_UTF8 ) {
96 record->city = _iso_8859_1__utf8( (const char * ) record_buf );
97 } else {
98 record->city = malloc(str_length+1);
99 strncpy(record->city, ( const char * ) record_buf, str_length+1);
100 }
101 }
102 record_buf += (str_length + 1);
103 str_length = 0;
104
105 /* get postal code */
106 while (record_buf[str_length] != '\0')
107 str_length++;
108 if (str_length > 0) {
109 record->postal_code = malloc(str_length+1);
110 strncpy(record->postal_code, record_buf, str_length+1);
111 }
112 record_buf += (str_length + 1);
113
114 /* get latitude */
115 for (j = 0; j < 3; ++j)
116 latitude += (record_buf[j] << (j * 8));
117 record->latitude = latitude/10000 - 180;
118 record_buf += 3;
119
120 /* get longitude */
121 for (j = 0; j < 3; ++j)
122 longitude += (record_buf[j] << (j * 8));
123 record->longitude = longitude/10000 - 180;
124
125 /* get area code and metro code for post April 2002 databases and for US locations */
126 if (GEOIP_CITY_EDITION_REV1 == gi->databaseType) {
127 if (!strcmp(record->country_code, "US")) {
128 record_buf += 3;
129 for (j = 0; j < 3; ++j)
130 metroarea_combo += (record_buf[j] << (j * 8));
131 record->metro_code = metroarea_combo/1000;
132 record->area_code = metroarea_combo % 1000;
133 }
134 }
135
136 if (gi->cache == NULL)
137 free(begin_record_buf);
138
139 /* Used for GeoIP_next_record */
140 if (next_record_ptr != NULL)
141 *next_record_ptr = seek_record + record_buf - begin_record_buf + 3;
142
143 return record;
144 }
145
146 static
147 GeoIPRecord * _get_record(GeoIP* gi, unsigned long ipnum) {
148 unsigned int seek_record;
149
150 if (gi->databaseType != GEOIP_CITY_EDITION_REV0 &&
151 gi->databaseType != GEOIP_CITY_EDITION_REV1) {
152 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_CITY_EDITION_REV1]);
153 return 0;
154 }
155
156 seek_record = _GeoIP_seek_record(gi, ipnum);
157 return _extract_record(gi, seek_record, NULL);
158 }
159
160 static
161 GeoIPRecord * _get_record_v6(GeoIP* gi, geoipv6_t ipnum) {
162 unsigned int seek_record;
163
164 if (gi->databaseType != GEOIP_CITY_EDITION_REV0 &&
165 gi->databaseType != GEOIP_CITY_EDITION_REV1) {
166 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_CITY_EDITION_REV1]);
167 return 0;
168 }
169
170 seek_record = _GeoIP_seek_record_v6(gi, ipnum);
171 return _extract_record(gi, seek_record, NULL);
172 }
173
174
175
176 GeoIPRecord * GeoIP_record_by_ipnum (GeoIP* gi, unsigned long ipnum) {
177 return _get_record(gi, ipnum);
178 }
179
180 GeoIPRecord * GeoIP_record_by_ipnum_v6 (GeoIP* gi, geoipv6_t ipnum) {
181 return _get_record_v6(gi, ipnum);
182 }
183
184 GeoIPRecord * GeoIP_record_by_addr (GeoIP* gi, const char *addr) {
185 unsigned long ipnum;
186 if (addr == NULL) {
187 return 0;
188 }
189 ipnum = _GeoIP_addr_to_num(addr);
190 return _get_record(gi, ipnum);
191 }
192
193 GeoIPRecord * GeoIP_record_by_addr_v6 (GeoIP* gi, const char *addr) {
194 geoipv6_t ipnum;
195 if (addr == NULL) {
196 return 0;
197 }
198 ipnum = _GeoIP_addr_to_num_v6(addr);
199 return _get_record_v6(gi, ipnum);
200 }
201
202 GeoIPRecord * GeoIP_record_by_name (GeoIP* gi, const char *name) {
203 unsigned long ipnum;
204 if (name == NULL) {
205 return 0;
206 }
207 ipnum = _GeoIP_lookupaddress(name);
208 return _get_record(gi, ipnum);
209 }
210
211 GeoIPRecord * GeoIP_record_by_name_v6 (GeoIP* gi, const char *name) {
212 geoipv6_t ipnum;
213 if (name == NULL) {
214 return 0;
215 }
216 ipnum = _GeoIP_lookupaddress_v6(name);
217 return _get_record_v6(gi, ipnum);
218 }
219
220 int GeoIP_record_id_by_addr (GeoIP* gi, const char *addr) {
221 unsigned long ipnum;
222 if (gi->databaseType != GEOIP_CITY_EDITION_REV0 &&
223 gi->databaseType != GEOIP_CITY_EDITION_REV1) {
224 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_CITY_EDITION_REV1]);
225 return 0;
226 }
227 if (addr == NULL) {
228 return 0;
229 }
230 ipnum = _GeoIP_addr_to_num(addr);
231 return _GeoIP_seek_record(gi, ipnum);
232 }
233
234 int GeoIP_record_id_by_addr_v6 (GeoIP* gi, const char *addr) {
235 geoipv6_t ipnum;
236 if (gi->databaseType != GEOIP_CITY_EDITION_REV0 &&
237 gi->databaseType != GEOIP_CITY_EDITION_REV1) {
238 printf("Invalid database type %s, expected %s\n", GeoIPDBDescription[(int)gi->databaseType], GeoIPDBDescription[GEOIP_CITY_EDITION_REV1]);
239 return 0;
240 }
241 if (addr == NULL) {
242 return 0;
243 }
244 ipnum = _GeoIP_addr_to_num_v6(addr);
245 return _GeoIP_seek_record_v6(gi, ipnum);
246 }
247
248 int GeoIP_init_record_iter (GeoIP* gi) {
249 return gi->databaseSegments[0] + 1;
250 }
251
252 int GeoIP_next_record (GeoIP* gi, GeoIPRecord **gir, int *record_iter) {
253 if (gi->cache != NULL) {
254 printf("GeoIP_next_record not supported in memory cache mode\n");
255 return 1;
256 }
257 *gir = _extract_record(gi, *record_iter, record_iter);
258 return 0;
259 }
260
261 void GeoIPRecord_delete (GeoIPRecord *gir) {
262 free(gir->region);
263 free(gir->city);
264 free(gir->postal_code);
265 free(gir);
266 }
267
268
269
270 char * _iso_8859_1__utf8(const char * iso) {
271 char c, k;
272 char * p;
273 char * t = (char *)iso;
274 int len = 0;
275 while ( ( c = *t++) ){
276 if ( c < 0 )
277 len++;
278 }
279 len += t - iso;
280 t = p = malloc( len );
281
282 if ( p ){
283 while ( ( c = *iso++ ) ) {
284 if (c < 0 ) {
285 k = 0xc2;
286 if (c >= -64 )
287 k++;
288 *t++ = k;
289 c &= ~0x40;
290 }
291 *t++ = c;
292 }
293 *t++ = 0x00;
294 }
295 return p;
296 }