4

I'm looking to query the geoip database (city, country, org) for a bunch of IP addresses. I looked at http://www.maxmind.com/download/geoip/api/pascal/Sample.pas and modified it:

function LookupCountry(IPAddr: string) : string;
var
   GeoIP: TGeoIP;
   GeoIPCountry: TGeoIPCountry;
begin
  GeoIP := TGeoIP.Create('C:\Users\Albert\Documents\RAD Studio\Projects\Parser\geoip\GeoIP.dat');
  try
    if GeoIP.GetCountry(IPAddr, GeoIPCountry) = GEOIP_SUCCESS then
    begin
      Result := GeoIPCountry.CountryName;
    end
    else
    begin
      Result := IPAddr;
    end;
  finally
    GeoIP.Free;
  end;
end;

but I get no results on over 50'000 queries. I know that the address has to be manipulated when working with csv, but I have the binary db version. What am I missing?

Thanks!

asg2012
  • 315
  • 1
  • 6
  • 15
  • What returns you `GeoIP.GetDatabaseInfo` ? – TLama Aug 13 '12 at 13:36
  • Gibberish unfortunately: http://s13.postimage.org/r0ihjezev/geoipdbinfo.png – asg2012 Aug 13 '12 at 13:42
  • And you have Delphi 2009+ and using [`a unit`](http://www.maxmind.com/download/geoip/api/pascal/GeoIP.pas) that was created before your Delphi version. So it seems like an ANSI/Unicode mismatch. – TLama Aug 13 '12 at 13:45
  • @user582118, where did you found `GeoIPAPI.pas` ? I've [`browsed`](http://www.maxmind.com/download/geoip/api/pascal/) through the repository from the link in the question, but there's no `GeoIPAPI.pas`... – TLama Aug 13 '12 at 14:01
  • @user582118 Pchar is most painfull thing, but i think he should also change Char to AnsiChar and String to AnsiString. if he gonna use *var_string[10]* for example or even worse *@var_string[10]* – Arioch 'The Aug 14 '12 at 15:44

1 Answers1

6

You've encountered well known ANSI/Unicode mismatch problem. You're using Unicode version of Delphi (version 2009+) and the unit that is dated before the Unicode version of Delphi was released.

In Delphi below 2009 (non Unicode) were types like string or PChar mapped to the ANSI versions of these types whilst since Delphi 2009 to Unicode ones.

1. mass replace:

To fix this GeoIP.pas unit, as first, replace all occurences of:

 PChar  -> PAnsiChar
 string -> AnsiString

2. minor change:

After you're done with the replace, change the AnsiString type on line 93 back to the string type:

 92  public
 93    constructor Create(const FileName: AnsiString); // <- string
 94  ...

And the same do also on line 138:

138  constructor TGeoIP.Create(const FileName: AnsiString); // <- string
139  begin
140    inherited Create;
TLama
  • 75,147
  • 17
  • 214
  • 392
  • 1
    No *all* occurrences. For example, the call to `inet_addr` shouldn't change, and changing `string` to `AnsiString` probably isn't necessary in *any* cases. – Rob Kennedy Aug 13 '12 at 15:34
  • @Rob, yeah, that's right; except `inet_addr` all method parameters doesn't need to be changed. Feel free to post your answer to this... I'll delete this one. But I'm afraid this won't be so easy to describe without posting a new version of the unit. – TLama Aug 13 '12 at 15:39
  • @Rob, now looking on it again, the [`inet_add`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms738563(v=vs.85).aspx) must be changed, because it is defined as `char*` so the `PAnsiChar` is correct here. And the `IPAddr` string parameters should also remain in their ANSI versions since they're passed just to the `inet_add` function inside of the methods. So as the only thing to change after that *mass* replace is the `TGeoIP.Create` constructor, where the `FileName` parameter is used to create a file stream. – TLama Aug 15 '12 at 00:50
  • If inet_addr required PAnsiChar, then the original, unchanged code wouldn't have compiled in the first place. But we already know it did compile, since the program ran, so it must accept PChar. – Rob Kennedy Aug 15 '12 at 03:04
  • @Rob, then must OP do some sort of *just to compile blind* modification, because it actually cannot be compiled without that change on Unicode Delphi. Just verified... – TLama Aug 15 '12 at 03:12