Logo Search packages:      
Sourcecode: tclgeoip version File versions  Download package

geoiptcl.c

/*
 *
 *    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 <tcl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <GeoIP.h>
#include <GeoIPCity.h>
#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;
}

Generated by  Doxygen 1.6.0   Back to index