Mercurial > hg > nginx-mail
comparison src/http/modules/ngx_http_geoip_module.c @ 665:0b460e61bdcd default tip
Merge with nginx 1.0.0.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 25 Apr 2011 04:22:17 +0400 |
parents | bb20316269e4 |
children |
comparison
equal
deleted
inserted
replaced
572:06419a2298a9 | 665:0b460e61bdcd |
---|---|
28 | 28 |
29 static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r, | 29 static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r, |
30 ngx_http_variable_value_t *v, uintptr_t data); | 30 ngx_http_variable_value_t *v, uintptr_t data); |
31 static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r, | 31 static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r, |
32 ngx_http_variable_value_t *v, uintptr_t data); | 32 ngx_http_variable_value_t *v, uintptr_t data); |
33 static ngx_int_t ngx_http_geoip_region_name_variable(ngx_http_request_t *r, | |
34 ngx_http_variable_value_t *v, uintptr_t data); | |
35 static ngx_int_t ngx_http_geoip_city_float_variable(ngx_http_request_t *r, | |
36 ngx_http_variable_value_t *v, uintptr_t data); | |
37 static ngx_int_t ngx_http_geoip_city_int_variable(ngx_http_request_t *r, | |
38 ngx_http_variable_value_t *v, uintptr_t data); | |
39 static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r); | |
33 | 40 |
34 static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf); | 41 static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf); |
35 static void *ngx_http_geoip_create_conf(ngx_conf_t *cf); | 42 static void *ngx_http_geoip_create_conf(ngx_conf_t *cf); |
36 static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, | 43 static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, |
37 void *conf); | 44 void *conf); |
41 | 48 |
42 | 49 |
43 static ngx_command_t ngx_http_geoip_commands[] = { | 50 static ngx_command_t ngx_http_geoip_commands[] = { |
44 | 51 |
45 { ngx_string("geoip_country"), | 52 { ngx_string("geoip_country"), |
46 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, | 53 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12, |
47 ngx_http_geoip_country, | 54 ngx_http_geoip_country, |
48 NGX_HTTP_MAIN_CONF_OFFSET, | 55 NGX_HTTP_MAIN_CONF_OFFSET, |
49 0, | 56 0, |
50 NULL }, | 57 NULL }, |
51 | 58 |
52 { ngx_string("geoip_city"), | 59 { ngx_string("geoip_city"), |
53 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, | 60 NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12, |
54 ngx_http_geoip_city, | 61 ngx_http_geoip_city, |
55 NGX_HTTP_MAIN_CONF_OFFSET, | 62 NGX_HTTP_MAIN_CONF_OFFSET, |
56 0, | 63 0, |
57 NULL }, | 64 NULL }, |
58 | 65 |
91 }; | 98 }; |
92 | 99 |
93 | 100 |
94 static ngx_http_variable_t ngx_http_geoip_vars[] = { | 101 static ngx_http_variable_t ngx_http_geoip_vars[] = { |
95 | 102 |
96 { ngx_string("geoip_country_code"), NULL, ngx_http_geoip_country_variable, | 103 { ngx_string("geoip_country_code"), NULL, |
104 ngx_http_geoip_country_variable, | |
97 (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 }, | 105 (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 }, |
98 | 106 |
99 { ngx_string("geoip_country_code3"), NULL, ngx_http_geoip_country_variable, | 107 { ngx_string("geoip_country_code3"), NULL, |
108 ngx_http_geoip_country_variable, | |
100 (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 }, | 109 (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 }, |
101 | 110 |
102 { ngx_string("geoip_country_name"), NULL, ngx_http_geoip_country_variable, | 111 { ngx_string("geoip_country_name"), NULL, |
112 ngx_http_geoip_country_variable, | |
103 (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 }, | 113 (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 }, |
104 | 114 |
105 { ngx_string("geoip_city_country_code"), NULL, ngx_http_geoip_city_variable, | 115 { ngx_string("geoip_city_continent_code"), NULL, |
116 ngx_http_geoip_city_variable, | |
117 offsetof(GeoIPRecord, continent_code), 0, 0 }, | |
118 | |
119 { ngx_string("geoip_city_country_code"), NULL, | |
120 ngx_http_geoip_city_variable, | |
106 offsetof(GeoIPRecord, country_code), 0, 0 }, | 121 offsetof(GeoIPRecord, country_code), 0, 0 }, |
107 | 122 |
108 { ngx_string("geoip_city_country_code3"), NULL, | 123 { ngx_string("geoip_city_country_code3"), NULL, |
109 ngx_http_geoip_city_variable, | 124 ngx_http_geoip_city_variable, |
110 offsetof(GeoIPRecord, country_code3), 0, 0 }, | 125 offsetof(GeoIPRecord, country_code3), 0, 0 }, |
111 | 126 |
112 { ngx_string("geoip_city_country_name"), NULL, ngx_http_geoip_city_variable, | 127 { ngx_string("geoip_city_country_name"), NULL, |
128 ngx_http_geoip_city_variable, | |
113 offsetof(GeoIPRecord, country_name), 0, 0 }, | 129 offsetof(GeoIPRecord, country_name), 0, 0 }, |
114 | 130 |
115 { ngx_string("geoip_region"), NULL, | 131 { ngx_string("geoip_region"), NULL, |
116 ngx_http_geoip_city_variable, | 132 ngx_http_geoip_city_variable, |
117 offsetof(GeoIPRecord, region), 0, 0 }, | 133 offsetof(GeoIPRecord, region), 0, 0 }, |
118 | 134 |
135 { ngx_string("geoip_region_name"), NULL, | |
136 ngx_http_geoip_region_name_variable, | |
137 0, 0, 0 }, | |
138 | |
119 { ngx_string("geoip_city"), NULL, | 139 { ngx_string("geoip_city"), NULL, |
120 ngx_http_geoip_city_variable, | 140 ngx_http_geoip_city_variable, |
121 offsetof(GeoIPRecord, city), 0, 0 }, | 141 offsetof(GeoIPRecord, city), 0, 0 }, |
122 | 142 |
123 { ngx_string("geoip_postal_code"), NULL, | 143 { ngx_string("geoip_postal_code"), NULL, |
124 ngx_http_geoip_city_variable, | 144 ngx_http_geoip_city_variable, |
125 offsetof(GeoIPRecord, postal_code), 0, 0 }, | 145 offsetof(GeoIPRecord, postal_code), 0, 0 }, |
146 | |
147 { ngx_string("geoip_latitude"), NULL, | |
148 ngx_http_geoip_city_float_variable, | |
149 offsetof(GeoIPRecord, latitude), 0, 0 }, | |
150 | |
151 { ngx_string("geoip_longitude"), NULL, | |
152 ngx_http_geoip_city_float_variable, | |
153 offsetof(GeoIPRecord, longitude), 0, 0 }, | |
154 | |
155 { ngx_string("geoip_dma_code"), NULL, | |
156 ngx_http_geoip_city_int_variable, | |
157 offsetof(GeoIPRecord, dma_code), 0, 0 }, | |
158 | |
159 { ngx_string("geoip_area_code"), NULL, | |
160 ngx_http_geoip_city_int_variable, | |
161 offsetof(GeoIPRecord, area_code), 0, 0 }, | |
126 | 162 |
127 { ngx_null_string, NULL, NULL, 0, 0, 0 } | 163 { ngx_null_string, NULL, NULL, 0, 0, 0 } |
128 }; | 164 }; |
129 | 165 |
130 | 166 |
177 | 213 |
178 static ngx_int_t | 214 static ngx_int_t |
179 ngx_http_geoip_city_variable(ngx_http_request_t *r, | 215 ngx_http_geoip_city_variable(ngx_http_request_t *r, |
180 ngx_http_variable_value_t *v, uintptr_t data) | 216 ngx_http_variable_value_t *v, uintptr_t data) |
181 { | 217 { |
182 u_long addr; | 218 char *val; |
183 char *val; | 219 size_t len; |
184 size_t len; | 220 GeoIPRecord *gr; |
185 GeoIPRecord *gr; | 221 |
186 struct sockaddr_in *sin; | 222 gr = ngx_http_geoip_get_city_record(r); |
187 ngx_http_geoip_conf_t *gcf; | |
188 | |
189 gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module); | |
190 | |
191 if (gcf->city == NULL) { | |
192 goto not_found; | |
193 } | |
194 | |
195 if (r->connection->sockaddr->sa_family != AF_INET) { | |
196 goto not_found; | |
197 } | |
198 | |
199 sin = (struct sockaddr_in *) r->connection->sockaddr; | |
200 addr = ntohl(sin->sin_addr.s_addr); | |
201 | |
202 gr = GeoIP_record_by_ipnum(gcf->city, addr); | |
203 | |
204 if (gr == NULL) { | 223 if (gr == NULL) { |
205 goto not_found; | 224 goto not_found; |
206 } | 225 } |
207 | 226 |
208 val = *(char **) ((char *) gr + data); | 227 val = *(char **) ((char *) gr + data); |
209 | |
210 if (val == NULL) { | 228 if (val == NULL) { |
211 goto no_value; | 229 goto no_value; |
212 } | 230 } |
213 | 231 |
214 len = ngx_strlen(val); | 232 len = ngx_strlen(val); |
215 v->data = ngx_pnalloc(r->pool, len); | 233 v->data = ngx_pnalloc(r->pool, len); |
216 | |
217 if (v->data == NULL) { | 234 if (v->data == NULL) { |
218 GeoIPRecord_delete(gr); | 235 GeoIPRecord_delete(gr); |
219 return NGX_ERROR; | 236 return NGX_ERROR; |
220 } | 237 } |
221 | 238 |
237 not_found: | 254 not_found: |
238 | 255 |
239 v->not_found = 1; | 256 v->not_found = 1; |
240 | 257 |
241 return NGX_OK; | 258 return NGX_OK; |
259 } | |
260 | |
261 | |
262 static ngx_int_t | |
263 ngx_http_geoip_region_name_variable(ngx_http_request_t *r, | |
264 ngx_http_variable_value_t *v, uintptr_t data) | |
265 { | |
266 size_t len; | |
267 const char *val; | |
268 GeoIPRecord *gr; | |
269 | |
270 gr = ngx_http_geoip_get_city_record(r); | |
271 if (gr == NULL) { | |
272 goto not_found; | |
273 } | |
274 | |
275 val = GeoIP_region_name_by_code(gr->country_code, gr->region); | |
276 | |
277 GeoIPRecord_delete(gr); | |
278 | |
279 if (val == NULL) { | |
280 goto not_found; | |
281 } | |
282 | |
283 len = ngx_strlen(val); | |
284 v->data = ngx_pnalloc(r->pool, len); | |
285 if (v->data == NULL) { | |
286 return NGX_ERROR; | |
287 } | |
288 | |
289 ngx_memcpy(v->data, val, len); | |
290 | |
291 v->len = len; | |
292 v->valid = 1; | |
293 v->no_cacheable = 0; | |
294 v->not_found = 0; | |
295 | |
296 return NGX_OK; | |
297 | |
298 not_found: | |
299 | |
300 v->not_found = 1; | |
301 | |
302 return NGX_OK; | |
303 } | |
304 | |
305 | |
306 static ngx_int_t | |
307 ngx_http_geoip_city_float_variable(ngx_http_request_t *r, | |
308 ngx_http_variable_value_t *v, uintptr_t data) | |
309 { | |
310 float val; | |
311 GeoIPRecord *gr; | |
312 | |
313 gr = ngx_http_geoip_get_city_record(r); | |
314 if (gr == NULL) { | |
315 v->not_found = 1; | |
316 return NGX_OK; | |
317 } | |
318 | |
319 v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN + 5); | |
320 if (v->data == NULL) { | |
321 GeoIPRecord_delete(gr); | |
322 return NGX_ERROR; | |
323 } | |
324 | |
325 val = *(float *) ((char *) gr + data); | |
326 | |
327 v->len = ngx_sprintf(v->data, "%.4f", val) - v->data; | |
328 | |
329 GeoIPRecord_delete(gr); | |
330 | |
331 return NGX_OK; | |
332 } | |
333 | |
334 | |
335 static ngx_int_t | |
336 ngx_http_geoip_city_int_variable(ngx_http_request_t *r, | |
337 ngx_http_variable_value_t *v, uintptr_t data) | |
338 { | |
339 int val; | |
340 GeoIPRecord *gr; | |
341 | |
342 gr = ngx_http_geoip_get_city_record(r); | |
343 if (gr == NULL) { | |
344 v->not_found = 1; | |
345 return NGX_OK; | |
346 } | |
347 | |
348 v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN); | |
349 if (v->data == NULL) { | |
350 GeoIPRecord_delete(gr); | |
351 return NGX_ERROR; | |
352 } | |
353 | |
354 val = *(int *) ((char *) gr + data); | |
355 | |
356 v->len = ngx_sprintf(v->data, "%d", val) - v->data; | |
357 | |
358 GeoIPRecord_delete(gr); | |
359 | |
360 return NGX_OK; | |
361 } | |
362 | |
363 | |
364 static GeoIPRecord * | |
365 ngx_http_geoip_get_city_record(ngx_http_request_t *r) | |
366 { | |
367 u_long addr; | |
368 struct sockaddr_in *sin; | |
369 ngx_http_geoip_conf_t *gcf; | |
370 | |
371 gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module); | |
372 | |
373 if (gcf->city && r->connection->sockaddr->sa_family == AF_INET) { | |
374 | |
375 sin = (struct sockaddr_in *) r->connection->sockaddr; | |
376 addr = ntohl(sin->sin_addr.s_addr); | |
377 | |
378 return GeoIP_record_by_ipnum(gcf->city, addr); | |
379 } | |
380 | |
381 return NULL; | |
242 } | 382 } |
243 | 383 |
244 | 384 |
245 static ngx_int_t | 385 static ngx_int_t |
246 ngx_http_geoip_add_variables(ngx_conf_t *cf) | 386 ngx_http_geoip_add_variables(ngx_conf_t *cf) |
304 "GeoIO_open(\"%V\") failed", &value[1]); | 444 "GeoIO_open(\"%V\") failed", &value[1]); |
305 | 445 |
306 return NGX_CONF_ERROR; | 446 return NGX_CONF_ERROR; |
307 } | 447 } |
308 | 448 |
449 if (cf->args->nelts == 3) { | |
450 if (ngx_strcmp(value[2].data, "utf8") == 0) { | |
451 GeoIP_set_charset (gcf->country, GEOIP_CHARSET_UTF8); | |
452 | |
453 } else { | |
454 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
455 "invalid parameter \"%V\"", &value[2]); | |
456 return NGX_CONF_ERROR; | |
457 } | |
458 } | |
459 | |
309 switch (gcf->country->databaseType) { | 460 switch (gcf->country->databaseType) { |
310 | 461 |
311 case GEOIP_COUNTRY_EDITION: | 462 case GEOIP_COUNTRY_EDITION: |
312 case GEOIP_PROXY_EDITION: | 463 case GEOIP_PROXY_EDITION: |
313 case GEOIP_NETSPEED_EDITION: | 464 case GEOIP_NETSPEED_EDITION: |
343 "GeoIO_open(\"%V\") failed", &value[1]); | 494 "GeoIO_open(\"%V\") failed", &value[1]); |
344 | 495 |
345 return NGX_CONF_ERROR; | 496 return NGX_CONF_ERROR; |
346 } | 497 } |
347 | 498 |
499 if (cf->args->nelts == 3) { | |
500 if (ngx_strcmp(value[2].data, "utf8") == 0) { | |
501 GeoIP_set_charset (gcf->city, GEOIP_CHARSET_UTF8); | |
502 | |
503 } else { | |
504 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
505 "invalid parameter \"%V\"", &value[2]); | |
506 return NGX_CONF_ERROR; | |
507 } | |
508 } | |
509 | |
348 switch (gcf->city->databaseType) { | 510 switch (gcf->city->databaseType) { |
349 | 511 |
350 case GEOIP_CITY_EDITION_REV0: | 512 case GEOIP_CITY_EDITION_REV0: |
351 case GEOIP_CITY_EDITION_REV1: | 513 case GEOIP_CITY_EDITION_REV1: |
352 | 514 |