]>
jfr.im git - irc/quakenet/newserv.git/blob - geoip/libGeoIP/GeoIPCity.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
4 * Copyright (C) 2006 MaxMind LLC
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.
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.
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
22 #include <GeoIP_internal.h>
23 #include <GeoIPCity.h>
24 #if !defined(WIN32) && !defined(WIN64)
26 #include <netinet/in.h> /* For ntohl */
31 #include <sys/types.h> /* For uint32_t */
33 #include <stdint.h> /* For uint32_t */
37 const int FULL_RECORD_LENGTH
= 50;
40 GeoIPRecord
* _extract_record(GeoIP
* gi
, unsigned int seek_record
, int *next_record_ptr
) {
42 unsigned char *record_buf
= NULL
;
43 unsigned char *begin_record_buf
= NULL
;
47 double latitude
= 0, longitude
= 0;
48 int metroarea_combo
= 0;
50 if (seek_record
== gi
->databaseSegments
[0])
53 record
= malloc(sizeof(GeoIPRecord
));
54 memset(record
, 0, sizeof(GeoIPRecord
));
56 record
->charset
= gi
->charset
;
58 record_pointer
= seek_record
+ (2 * gi
->record_length
- 1) * gi
->databaseSegments
[0];
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
);
71 record_buf
= gi
->cache
+ (long)record_pointer
;
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]];
82 while (record_buf
[str_length
] != '\0')
85 record
->region
= malloc(str_length
+1);
86 strncpy(record
->region
, record_buf
, str_length
+1);
88 record_buf
+= str_length
+ 1;
92 while (record_buf
[str_length
] != '\0')
95 if ( gi
->charset
== GEOIP_CHARSET_UTF8
) {
96 record
->city
= _iso_8859_1__utf8( (const char * ) record_buf
);
98 record
->city
= malloc(str_length
+1);
99 strncpy(record
->city
, ( const char * ) record_buf
, str_length
+1);
102 record_buf
+= (str_length
+ 1);
105 /* get postal code */
106 while (record_buf
[str_length
] != '\0')
108 if (str_length
> 0) {
109 record
->postal_code
= malloc(str_length
+1);
110 strncpy(record
->postal_code
, record_buf
, str_length
+1);
112 record_buf
+= (str_length
+ 1);
115 for (j
= 0; j
< 3; ++j
)
116 latitude
+= (record_buf
[j
] << (j
* 8));
117 record
->latitude
= latitude
/10000 - 180;
121 for (j
= 0; j
< 3; ++j
)
122 longitude
+= (record_buf
[j
] << (j
* 8));
123 record
->longitude
= longitude
/10000 - 180;
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")) {
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;
136 if (gi
->cache
== NULL
)
137 free(begin_record_buf
);
139 /* Used for GeoIP_next_record */
140 if (next_record_ptr
!= NULL
)
141 *next_record_ptr
= seek_record
+ record_buf
- begin_record_buf
+ 3;
147 GeoIPRecord
* _get_record(GeoIP
* gi
, unsigned long ipnum
) {
148 unsigned int seek_record
;
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
]);
156 seek_record
= _GeoIP_seek_record(gi
, ipnum
);
157 return _extract_record(gi
, seek_record
, NULL
);
161 GeoIPRecord
* _get_record_v6(GeoIP
* gi
, geoipv6_t ipnum
) {
162 unsigned int seek_record
;
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
]);
170 seek_record
= _GeoIP_seek_record_v6(gi
, ipnum
);
171 return _extract_record(gi
, seek_record
, NULL
);
176 GeoIPRecord
* GeoIP_record_by_ipnum (GeoIP
* gi
, unsigned long ipnum
) {
177 return _get_record(gi
, ipnum
);
180 GeoIPRecord
* GeoIP_record_by_ipnum_v6 (GeoIP
* gi
, geoipv6_t ipnum
) {
181 return _get_record_v6(gi
, ipnum
);
184 GeoIPRecord
* GeoIP_record_by_addr (GeoIP
* gi
, const char *addr
) {
189 ipnum
= _GeoIP_addr_to_num(addr
);
190 return _get_record(gi
, ipnum
);
193 GeoIPRecord
* GeoIP_record_by_addr_v6 (GeoIP
* gi
, const char *addr
) {
198 ipnum
= _GeoIP_addr_to_num_v6(addr
);
199 return _get_record_v6(gi
, ipnum
);
202 GeoIPRecord
* GeoIP_record_by_name (GeoIP
* gi
, const char *name
) {
207 ipnum
= _GeoIP_lookupaddress(name
);
208 return _get_record(gi
, ipnum
);
211 GeoIPRecord
* GeoIP_record_by_name_v6 (GeoIP
* gi
, const char *name
) {
216 ipnum
= _GeoIP_lookupaddress_v6(name
);
217 return _get_record_v6(gi
, ipnum
);
220 int GeoIP_record_id_by_addr (GeoIP
* gi
, const char *addr
) {
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
]);
230 ipnum
= _GeoIP_addr_to_num(addr
);
231 return _GeoIP_seek_record(gi
, ipnum
);
234 int GeoIP_record_id_by_addr_v6 (GeoIP
* gi
, const char *addr
) {
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
]);
244 ipnum
= _GeoIP_addr_to_num_v6(addr
);
245 return _GeoIP_seek_record_v6(gi
, ipnum
);
248 int GeoIP_init_record_iter (GeoIP
* gi
) {
249 return gi
->databaseSegments
[0] + 1;
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");
257 *gir
= _extract_record(gi
, *record_iter
, record_iter
);
261 void GeoIPRecord_delete (GeoIPRecord
*gir
) {
264 free(gir
->postal_code
);
270 char * _iso_8859_1__utf8(const char * iso
) {
273 char * t
= (char *)iso
;
275 while ( ( c
= *t
++) ){
280 t
= p
= malloc( len
);
283 while ( ( c
= *iso
++ ) ) {