Well, if someone ever checked log files of a web server, she might have asked this
question to herself as least once.
On every request, a browser generates, the HTTP header sections contains information
about the client. These information are available through a web server and useable
with any scripting language - like Active FoxPro Pages.
With Active FoxPro Pages we can easily access those information bits:
lcAgent = Request.ServerVariables("HTTP_USER_AGENT")
Hey, with which browser are you surfing today?
Xaldon WebSpider 2.7.b6
Notes:
While using any kind of proxy and/or firewall software the information inside an HTTP
request could be filtered or even modified in any fashion - here are two examples how
this might look like at the server:
User-Agent: Field blocked by Outpost (http://www.agnitum.com)
User-Agent: Ultra special configured browser! Have a nice day.
So each client's request provides us data, ie. which browser application is used and so on.
With this info we are capable to get a new version of a browser - just check the user-agent
against a table with known versions and if it's a new entry, send a mail.
This has only temporarly fun cause daily mail traffic is already heavy enough, but you
could do it this way. *g*
Yes, but what about the topic of this article? - Well, the answer to this question is very
simple: There are a lot of information inside the HTTP header like someone's IP address
or hostname which sent this request. And this IP - we just call it remote IP - has an
owner. Either the client itself or if not her provider owns this IP address.
Okay, the interesting part of this aspect is that any public available IP address is
registered at least one central internet organisation like RIPE or DE-NIC. If I recall
this correctly, it should be RIPE...
Well, it should be clear that not every single IP is registered but the net classes are.
And now, we have a registered owner - with location. *g*
Let's summarize this:
- Any request has a remote IP
- This IP belongs to someone
- This unknown someone is registered for this IP address
- There's a database with 'translation': IP to owner
- And maybe this anonymous owner noticed where this IP is used - maybe there is a
country information
- ...
Watson? - Finally we are just in need of this database with information about which
IPs are used in which country and that's all - in theory.
Puuuh, luckily enough there were others who thought about these aspects as well and spent
their time and work. And I bet we don't re-invent the wheel again, or do we?
Fine, let's gather one of those registry databases - short visit at our beloved friend
Google - and *flupp* one, two nice sources:
- http://ip2location.com
- http://maxmind.com
- ...and many others
Hum, hum, actually I don't remember were I got mine from... but it was definitely for
free. Just do some research - you'll finally find one for free as well.
In many cases this list is stored as 'super-phantastic' CSV list (comma separated values).
That's not really an act for AFP engine, but you know it best, a nice table with some
nice indizes, that's what your fox likes...
I named the resulting table simply 'country.dbf'. Depending on your csv source the field
names might differ - just apply the sample below.
Et voilá, here's the quintessence of this article:
*//- Returns country name for specified IP address.
Function Country
Lparameters tcIpAddress
Local lcReturn, lnIpAddress
Store "" To lcReturn
Store 0 To lnIpAddress
If Empty(m.tcIpAddress)
Return m.lcReturn
EndIf
*//- Split standard IP Address in Integer value
lnIpAddress = Int(Val(GetWordNum(m.tcIpAddress,1,"."))) * 256^3 + ;
Int(Val(GetWordNum(m.tcIpAddress,2,"."))) * 256^2 + ;
Int(Val(GetWordNum(m.tcIpAddress,3,"."))) * 256 + ;
Int(Val(GetWordNum(m.tcIpAddress,4,".")))
Select "country"
Locate For Between(m.lnIpAddress, Ip_From, Ip_To)
If Found()
lcReturn = Alltrim(cName)
EndIf
Return m.lcReturn
EndFunc
In many times those registration lists have decimal values of IP addresses and due to this
fact we convert the client's remote ip from its octal value to decimal before querying our
country table. In my list the country name is upper-case and so I use a VFP built-in
function named Proper() for better reasults:
lcReturn = Proper(m.lcReturn)
Well, that's it. Let's try to determine your location:
Germany
Hope that my list is still up to date. *g*
Due to some feedback and notes my mail the complete
source code with country table is available for download. Please not all at once...
And here's a live sample for you as well.
Enjoy the AFP FAQ, JoKi