/* * * Author: Djihed Afifi * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include "geoiptcl.h" static int geoip_param_Cmd(ClientData clientData, Tcl_Interp *interp, int onjc, Tcl_Obj *const objv[]); static int load_suitable_database(Tcl_Interp *interp, int db_type, int db_flags); static GeoIP * gi; /* *---------------------------------------------------------------------- * * geoip_param_Cmd -- * Sets up geoip as the master command, and process a list of subcommands * and their arguments/flags. * *---------------------------------------------------------------------- */ static int geoip_param_Cmd( ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[] ) { static const char * geoip_subcmds[] = { "open", "close", /* done done */ "dbinfo", "dbedition", /* done done */ "db_avail", /* done */ "country_code_by_addr", "country_code_by_name", /* done done */ "country_code3_by_addr", "country_code3_by_name", /* done done */ "country_name_by_addr", "country_name_by_name", /* done done */ "region_by_addr", "region_by_name", /* done done */ "name_by_addr", "name_by_name", /* done done */ "record_by_addr", "record_by_name", /* done done */ NULL }; enum subcmd_index { open_idx, close_idx, dbinfo_idx, dbedition_idx, db_avail_idx, country_code_by_addr_idx, country_code_by_name_idx, country_code3_by_addr_idx, country_code3_by_name_idx, country_name_by_addr_idx, country_name_by_name_idx, region_by_addr_idx, region_by_name_idx, name_by_addr_idx, name_by_name_idx, record_by_addr_idx, record_by_name_idx, }; /* I didn't use GeoIP.h's GeoIPDBTypes arrangment directly because it: - starts with 1 - indexes rev0 editions that messe things up here because we would like to use abbreviations with Tcl_GetIndexFromObj, and having city_edition_rev1 and city_edition_rev0 will make them ambiguous. * Instead, we will later adjust indexes to make them correspond to GeoIPDBTypes */ static const char * valid_types[] = { "country_edition", "city_edition_rev1", "region_edition_rev1", "isp_edition", "org_edition", "proxy_edition", "asnum_edition", "netspeed_edition", "domain_edition", NULL }; int valid, subcmd; Tcl_Obj *result = Tcl_NewObj(); if(objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "subcmd ?arg arg ...?arg"); return TCL_ERROR; } valid = Tcl_GetIndexFromObj(interp, objv[1], geoip_subcmds, "subcmd", 0, (int *) &subcmd); if( valid != TCL_OK ) { return valid; } switch(subcmd) { case open_idx: { /* closing current database if already open */ if(gi != NULL) { GeoIP_delete(gi); } gi = NULL; int file_specd, type_specd, flags_specd; /* Has any been defined? */ int type_index; char * specd_file; char * specd_flags; int flags; Tcl_Obj * typeObj; /* defaults */ file_specd = type_specd = flags_specd = 0; type_index = GEOIP_ORG_EDITION; /*default to org */ specd_file = NULL; specd_flags = NULL; typeObj = NULL; int i; for (i = 2; i < objc; i++) { char * option = Tcl_GetStringFromObj(objv[i], NULL); if(strcasecmp(option, "-type") == 0) { type_specd = 1; i++; if (objc < i + 1) { Tcl_AppendResult(interp, "No type specified to argument -type", (char *)NULL); return TCL_ERROR; } typeObj = objv[i]; /* whole obj to be used in Tcl_GetIndexFromObj */ } else if(strcasecmp(option, "-file") == 0) { file_specd = 1; i++; if (objc < i + 1) { Tcl_AppendResult(interp, "No file specified to argument -file", (char *)NULL); return TCL_ERROR; } specd_file = Tcl_GetStringFromObj(objv[i], NULL); } else if(strcasecmp(option, "-flags") == 0) { flags_specd = 1; i++; if (objc < i + 1) { Tcl_AppendResult(interp, "No flags specified to argument -flags", (char *)NULL); return TCL_ERROR; } specd_flags = Tcl_GetStringFromObj(objv[i], NULL); } else { Tcl_AppendStringsToObj(result, "Invalid argument: ", Tcl_GetStringFromObj(objv[i], NULL), ". Must be one of -type -file -flags", NULL); Tcl_SetObjResult(interp, result); return TCL_ERROR; } } /* must not specifiy both a file name and a type */ if(file_specd == 1 && type_specd == 1) { Tcl_AppendResult(interp, "Must not specify both a database path and type.", (char *)NULL); return TCL_ERROR; } /* valid types? */ if(type_specd != 0) { int validtype; validtype = Tcl_GetIndexFromObj(interp, typeObj, valid_types, "type", 0, (int *) &type_index); if( validtype != TCL_OK ) { return validtype; } /* Adjust type_index to meet GeoIP.h GeoIPDBTypes */ if(type_index < 5) { type_index += 1; } else /* Jump the rev0 indexes */ { type_index += 3; } } /* process flags to -flags */ flags = 0; /* default is standard */ if(flags_specd == 1) { char * substring; substring = strtok (specd_flags,":"); while (substring != NULL) { if(strcasecmp(substring, "STANDARD") == 0) {} else if(strcasecmp(substring, "MEMORY_CACHE") == 0) {flags = (flags | GEOIP_MEMORY_CACHE);} else if(strcasecmp(substring, "CHECK_CACHE") == 0) {flags = (flags | GEOIP_CHECK_CACHE);} else if(strcasecmp(substring, "INDEX_CACHE") == 0) {flags = (flags | GEOIP_INDEX_CACHE);} else { Tcl_AppendResult(interp, "Unknown flag.", (char *)NULL); return TCL_ERROR; } substring = strtok (NULL, ":"); } } /* finally, attempt to open the datbase */ if (file_specd) { gi = GeoIP_open(specd_file, flags); } else if(type_specd) { gi = GeoIP_open_type(type_index, flags); } else /* open a standard org database by default? */ { gi = GeoIP_open_type(type_index, flags); } if (gi == NULL) { return TCL_ERROR; } /* Stay silent please */ /* Tcl_AppendStringsToObj(result, "Database loaded." , NULL); */ Tcl_SetObjResult(interp, result); return TCL_OK; } case close_idx: { if ( objc != 2 ) { Tcl_WrongNumArgs(interp, 2, objv, NULL); } if(gi != NULL) { /* stay silent please */ /* Tcl_AppendResult(interp, "Closing GeoIP database.", (char *)NULL);*/ GeoIP_delete(gi); } else { Tcl_AppendResult(interp, "No database loaded.", (char *)NULL); } gi = NULL; return TCL_OK; } case dbinfo_idx: { if ( objc != 2 ) { Tcl_WrongNumArgs(interp, 2, objv, NULL); } if (gi == NULL) { Tcl_AppendResult(interp, "Error: No database opened.", (char *) NULL); /* return TCL_ERROR; */ /*should it really quit? */ } char * info; info = GeoIP_database_info(gi); if (info == NULL) { Tcl_AppendResult(interp, "Error getting info.", (char *) NULL); } else { Tcl_AppendResult(interp, info, (char *)NULL); } return TCL_OK; } case dbedition_idx: { if ( objc != 2 ) { Tcl_WrongNumArgs(interp, 2, objv, NULL); } if (gi == NULL) { Tcl_AppendResult(interp, "Error: No database opened.", (char *) NULL); /* return TCL_ERROR; */ /*should it really quit? */ } unsigned char editionchar; editionchar = GeoIP_database_edition(gi); char * edition; /* Types taken from GeoIP.h */ switch( editionchar ) { case GEOIP_COUNTRY_EDITION : edition = "GEOIP_COUNTRY_EDITION"; break; case GEOIP_REGION_EDITION_REV0 : edition = "GEOIP_REGION_EDITION_REV0"; break; case GEOIP_CITY_EDITION_REV0 : edition = "GEOIP_CITY_EDITION_REV0"; break; case GEOIP_ORG_EDITION : edition = "GEOIP_ORG_EDITION"; break; case GEOIP_ISP_EDITION : edition = "GEOIP_ISP_EDITION"; break; case GEOIP_CITY_EDITION_REV1 : edition = "GEOIP_CITY_EDITION_REV1"; break; case GEOIP_REGION_EDITION_REV1 : edition = "GEOIP_REGION_EDITION_REV1"; break; case GEOIP_PROXY_EDITION : edition = "GEOIP_PROXY_EDITION"; break; case GEOIP_ASNUM_EDITION : edition = "GEOIP_ASNUM_EDITION"; break; case GEOIP_NETSPEED_EDITION : edition = "GEOIP_NETSPEED_EDITION"; break; case GEOIP_DOMAIN_EDITION : edition = "GEOIP_DOMAIN_EDITION"; break; default : edition = "UNKNOWN EDITION"; } Tcl_AppendResult(interp, edition, (char *)NULL); return TCL_OK; } case db_avail_idx: { char * given_type; if ( objc != 3 ) { Tcl_WrongNumArgs(interp, 0, objv, "geoip db_avail ?edition?"); return TCL_ERROR; } else { given_type = Tcl_GetStringFromObj(objv[2], NULL); } int db_type; if(strcasecmp(given_type, "COUNTRY_EDITION") == 0) { db_type = GEOIP_COUNTRY_EDITION;} else if(strcasecmp(given_type, "REGION_EDITION_REV0") == 0) { db_type = GEOIP_REGION_EDITION_REV0;} else if(strcasecmp(given_type, "CITY_EDITION_REV0") == 0) { db_type = GEOIP_CITY_EDITION_REV0;} else if(strcasecmp(given_type, "ORG_EDITION") == 0) { db_type = GEOIP_ORG_EDITION;} else if(strcasecmp(given_type, "ISP_EDITION") == 0) { db_type = GEOIP_ISP_EDITION;} else if(strcasecmp(given_type, "CITY_EDITION_REV1") == 0) { db_type = GEOIP_CITY_EDITION_REV1;} else if(strcasecmp(given_type, "REGION_EDITION_REV1") == 0) { db_type = GEOIP_REGION_EDITION_REV1;} else if(strcasecmp(given_type, "PROXY_EDITION") == 0) { db_type = GEOIP_PROXY_EDITION;} else if(strcasecmp(given_type, "ASNUM_EDITION") == 0) { db_type = GEOIP_ASNUM_EDITION;} else if(strcasecmp(given_type, "NETSPEED_EDITION") == 0) { db_type = GEOIP_NETSPEED_EDITION;} else if(strcasecmp(given_type, "DOMAIN_EDITION") == 0) { db_type = GEOIP_DOMAIN_EDITION;} else { Tcl_AppendResult(interp, "Unknown database type.", (char *)NULL); return TCL_OK; } int available; /* SEGFAULT BUG */ _GeoIP_setup_dbfilename(); available = GeoIP_db_avail(db_type); Tcl_ListObjAppendElement(interp,result, Tcl_NewIntObj(available)); Tcl_SetObjResult(interp, result); return TCL_OK; } case country_code_by_addr_idx: { int testOpen; testOpen = load_suitable_database(interp, GEOIP_COUNTRY_EDITION, GEOIP_STANDARD); if(testOpen != TCL_OK) { return TCL_ERROR; } char * ipAddress; const char * returnedCountry; if(objc != 3) { Tcl_AppendResult(interp, "Wrong number of arguments.", (char *) NULL); return TCL_ERROR; } else { ipAddress = Tcl_GetStringFromObj(objv[2], NULL); } returnedCountry = GeoIP_country_code_by_addr(gi, ipAddress); /* return error when supplied IP is not valid/not an IP? */ if (returnedCountry == NULL) { Tcl_AppendResult(interp, "N/A", (char *) NULL); } else { Tcl_AppendResult(interp, returnedCountry, (char *)NULL); } return TCL_OK; } case country_code3_by_addr_idx: { int testOpen; testOpen = load_suitable_database(interp, GEOIP_COUNTRY_EDITION, GEOIP_STANDARD); if(testOpen != TCL_OK) { return TCL_ERROR; } char * ipAddress; const char * returnedCountry; if(objc != 3) { Tcl_AppendResult(interp, "Wrong number of arguments.", (char *) NULL); return TCL_ERROR; } else { ipAddress = Tcl_GetStringFromObj(objv[2], NULL); } returnedCountry = GeoIP_country_code3_by_addr(gi, ipAddress); if (returnedCountry == NULL) { Tcl_AppendResult(interp, "N/A", (char *) NULL); } else { Tcl_AppendResult(interp, returnedCountry, (char *)NULL); } return TCL_OK; } case country_code_by_name_idx: { int testOpen; testOpen = load_suitable_database(interp, GEOIP_COUNTRY_EDITION, GEOIP_STANDARD); if(testOpen != TCL_OK) { return TCL_ERROR; } char * name; const char * returnedCountry; if(objc != 3) { Tcl_AppendResult(interp, "Wrong number of arguments.", (char *) NULL); return TCL_ERROR; } else { name = Tcl_GetStringFromObj(objv[2], NULL); } returnedCountry = GeoIP_country_code_by_name(gi, name); if (returnedCountry == NULL) { Tcl_AppendResult(interp, "N/A", (char *) NULL); } else { Tcl_AppendResult(interp, returnedCountry, (char *)NULL); } return TCL_OK; } case country_code3_by_name_idx: { int testOpen; testOpen = load_suitable_database(interp, GEOIP_COUNTRY_EDITION, GEOIP_STANDARD); if(testOpen != TCL_OK) { return TCL_ERROR; } char * name; const char * returnedCountry; if(objc != 3) { Tcl_AppendResult(interp, "Wrong number of arguments.", (char *) NULL); return TCL_ERROR; } else { name = Tcl_GetStringFromObj(objv[2], NULL); } returnedCountry = GeoIP_country_code3_by_name(gi, name); if (returnedCountry == NULL) { Tcl_AppendResult(interp, "N/A", (char *) NULL); } else { Tcl_AppendResult(interp, returnedCountry, (char *)NULL); } return TCL_OK; } case country_name_by_name_idx: { int testOpen; testOpen = load_suitable_database(interp, GEOIP_COUNTRY_EDITION, GEOIP_STANDARD); if(testOpen != TCL_OK) { return TCL_ERROR; } char * name; const char * returnedCountry; if(objc != 3) { Tcl_AppendResult(interp, "Wrong number of arguments.", (char *) NULL); return TCL_ERROR; } else { name = Tcl_GetStringFromObj(objv[2], NULL); } returnedCountry = GeoIP_country_name_by_name(gi, name); if (returnedCountry == NULL) { Tcl_AppendResult(interp, "N/A", (char *) NULL); } else { Tcl_AppendResult(interp, returnedCountry, (char *)NULL); } return TCL_OK; } case country_name_by_addr_idx: { int testOpen; testOpen = load_suitable_database(interp, GEOIP_COUNTRY_EDITION, GEOIP_STANDARD); if(testOpen != TCL_OK) { return TCL_ERROR; } char * ipAddress; const char * returnedCountry; if(objc != 3) { Tcl_AppendResult(interp, "Wrong number of arguments.", (char *) NULL); return TCL_ERROR; } else { ipAddress = Tcl_GetStringFromObj(objv[2], NULL); } returnedCountry = GeoIP_country_name_by_addr(gi, ipAddress); if (returnedCountry == NULL) { Tcl_AppendResult(interp, "N/A", (char *) NULL); } else { Tcl_AppendResult(interp, returnedCountry, (char *)NULL); } return TCL_OK; } case name_by_addr_idx: { /* db ok if Org, ISP or ISnum according to GeoIP.h */ int testOpen; if (gi == NULL || (gi->databaseType != GEOIP_ORG_EDITION && gi->databaseType != GEOIP_ISP_EDITION && gi->databaseType != GEOIP_ASNUM_EDITION )) { /* default, go with the org edition */ testOpen = load_suitable_database(interp, GEOIP_ORG_EDITION, GEOIP_STANDARD); if(testOpen != TCL_OK) { return TCL_ERROR; } } char * ipAddress; const char * returnedName; if(objc != 3) { Tcl_AppendResult(interp, "Wrong number of arguments.", (char *) NULL); return TCL_ERROR; } else { ipAddress = Tcl_GetStringFromObj(objv[2], NULL); } returnedName = GeoIP_name_by_addr(gi, ipAddress); if (returnedName == NULL) { Tcl_AppendResult(interp, "N/A", (char *) NULL); } else { Tcl_AppendResult(interp, returnedName, (char *)NULL); } return TCL_OK; } case name_by_name_idx: { /* db ok if Org, ISP or ISnum according to GeoIP.h */ int testOpen; if (gi == NULL || (gi->databaseType != GEOIP_ORG_EDITION && gi->databaseType != GEOIP_ISP_EDITION && gi->databaseType != GEOIP_ASNUM_EDITION )) { /* default, go with the org edition */ testOpen = load_suitable_database(interp, GEOIP_ORG_EDITION, GEOIP_STANDARD); if(testOpen != TCL_OK) { return TCL_ERROR; } } char * hostname; const char * returnedName; if(objc != 3) { Tcl_AppendResult(interp, "Wrong number of arguments.", (char *) NULL); return TCL_ERROR; } else { hostname = Tcl_GetStringFromObj(objv[2], NULL); } returnedName = GeoIP_name_by_name(gi, hostname); if (returnedName == NULL) { Tcl_AppendResult(interp, "N/A", (char *) NULL); } else { Tcl_AppendResult(interp, returnedName, (char *)NULL); } return TCL_OK; } case record_by_name_idx: { int testOpen; /* city edition rev0 or rev1: REV1 according to output of command without db.*/ testOpen = load_suitable_database(interp, GEOIP_CITY_EDITION_REV1, GEOIP_STANDARD); if(testOpen != TCL_OK) { return TCL_ERROR; } GeoIPRecord * retRecord; char * hostname; if(objc != 3) { Tcl_AppendResult(interp, "Wrong number of arguments.", (char *) NULL); return TCL_ERROR; } else { hostname = Tcl_GetStringFromObj(objv[2], NULL); } retRecord = GeoIP_record_by_name(gi, hostname); if (retRecord == NULL) { Tcl_AppendResult(interp, "N/A", (char *) NULL); } else { Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("code", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRecord->country_code, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("code3", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRecord->country_code3, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("country", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRecord->country_name, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("region", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRecord->region, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("city", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRecord->city, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("postcode", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRecord->postal_code, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("latitude", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewDoubleObj(retRecord->latitude)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("longitude", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewDoubleObj(retRecord->longitude)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("dma", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewIntObj(retRecord->dma_code)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("area", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewIntObj(retRecord->area_code)); Tcl_SetObjResult(interp, result); } return TCL_OK; } case record_by_addr_idx: { int testOpen; /* city edition rev0 or rev1: REV1 according to output of command without db.*/ testOpen = load_suitable_database(interp, GEOIP_CITY_EDITION_REV1, GEOIP_STANDARD); if(testOpen != TCL_OK) { return TCL_ERROR; } GeoIPRecord * retRecord; char * ipAddress; if(objc != 3) { Tcl_AppendResult(interp, "Wrong number of arguments.", (char *) NULL); return TCL_ERROR; } else { ipAddress = Tcl_GetStringFromObj(objv[2], NULL); } retRecord = GeoIP_record_by_name(gi, ipAddress); if (retRecord == NULL) { Tcl_AppendResult(interp, "N/A", (char *) NULL); } else { Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("code", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRecord->country_code, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("code3", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRecord->country_code3, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("country", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRecord->country_name, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("region", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRecord->region, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("city", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRecord->city, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("postcode", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRecord->postal_code, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("latitude", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewDoubleObj(retRecord->latitude)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("longitude", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewDoubleObj(retRecord->longitude)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("dma", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewIntObj(retRecord->dma_code)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("area", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewIntObj(retRecord->area_code)); Tcl_SetObjResult(interp, result); } return TCL_OK; } case region_by_name_idx: { int testOpen; /* city edition rev0 or rev1: REV1 according to output of command without db.*/ testOpen = load_suitable_database(interp, GEOIP_REGION_EDITION_REV1, GEOIP_STANDARD); if(testOpen != TCL_OK) { return TCL_ERROR; } GeoIPRegion * retRegion; char * hostname; if(objc != 3) { Tcl_AppendResult(interp, "Wrong number of arguments.", (char *) NULL); return TCL_ERROR; } else { hostname = Tcl_GetStringFromObj(objv[2], NULL); } retRegion = GeoIP_region_by_name(gi, hostname); if (retRegion == NULL) { Tcl_AppendResult(interp, "N/A", (char *) NULL); } else { Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("country", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRegion->country_code, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj("region", -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRegion->region, -1)); Tcl_SetObjResult(interp, result); } return TCL_OK; } case region_by_addr_idx: { int testOpen; /* city edition rev0 or rev1: REV1 according to output of command without db.*/ testOpen = load_suitable_database(interp, GEOIP_REGION_EDITION_REV1, GEOIP_STANDARD); if(testOpen != TCL_OK) { return TCL_ERROR; } GeoIPRegion * retRegion; char * ipAddress; if(objc != 3) { Tcl_AppendResult(interp, "Wrong number of arguments.", (char *) NULL); return TCL_ERROR; } else { ipAddress = Tcl_GetStringFromObj(objv[2], NULL); } retRegion = GeoIP_region_by_name(gi, ipAddress); if (retRegion == NULL) { Tcl_AppendResult(interp, "N/A", (char *) NULL); } else { Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRegion->country_code, -1)); Tcl_ListObjAppendElement(interp,result, Tcl_NewStringObj(retRegion->region, -1)); Tcl_SetObjResult(interp, result); } return TCL_OK; } default: { /* somehow we got here */ return TCL_ERROR; } } } /* * load_suitable_database -- * * Checks whether there is an open database, if not open a default one suitable * to process the call. * * Parameters: * As they are passed to the caller. * * Results: * A standard Tcl result */ static int load_suitable_database(Tcl_Interp *interp, int db_type, int db_flags) { /* if already opened but not with the needed type, then open a new one.*/ if( gi == NULL || gi->databaseType != db_type) { gi = GeoIP_open_type(db_type, db_flags); } /* if still no gi, return error, should alreayd be caught in the call*/ if(gi == NULL) { Tcl_AppendResult(interp, "Could not open database.", (char *) NULL); return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * Geoip_Init -- * * Initialize the new package. * * Results: * A standard Tcl result * * Side effects: * The geoip package is created. * One new command "geoip" is added to the Tcl interpreter (with its own subs) * *---------------------------------------------------------------------- */ int Tclgeoip_Init(Tcl_Interp *interp) { if (Tcl_InitStubs(interp, "8.1", 0) == NULL) { return TCL_ERROR; } if (Tcl_PkgRequire(interp, "Tcl", "8.1", 0) == NULL) { return TCL_ERROR; } if (Tcl_PkgProvide(interp, "geoip", PACKAGE_VERSION) != TCL_OK) { return TCL_ERROR; } gi = NULL; Tcl_CreateObjCommand(interp, "geoip", (Tcl_ObjCmdProc *) geoip_param_Cmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); return TCL_OK; }