Kako Prepoznati Srbina

Sećate li se mog prijatelja Manu-a, amerikanca koji prati isključivo fudbal(i to ne američki) ?

Manu       15.12.20 20:34 usa stole a serb footballer

Manu       15.12.20 20:35 http://chivas.usa.mlsnet.com/players/bio.jsp?team
                               t120&player=kljestan_s&playerId=kle326299&statTyp
                               =current

dinke      15.12.20 20:35 Sacha Kljestan ? Serb ?

Manu       15.12.20 20:36 lol

Manu       15.12.20 20:36 you should know

Manu       15.12.20 20:36 that is serb name

Manu       15.12.20 20:36 that is not serb name

Manu       15.12.20 20:36 that is serb name

Manu       15.12.20 20:36 that is not serb name

Manu       15.12.20 20:36 to be or not to be a serb

Manu       15.12.20 20:36 that is the question

Nakon što mi je sinoć po n-ti put(gde n–>00) servirao vest o nekom mom “zemljaku”, morao sam da potrošim vreme i objasnim mu kako da prepozna Srbina u vestima(tim pre što u našem multinacionalnom timu imamo dvocifren broj ovdašnjih programera):

function isSerb($lastname)
{
	$found = preg_match("/^[\pL]+ić$/u", $lastname);
	
	if($found)
	{
		return true;
	}
	else
	{
		return false;
	}
}

Uvod u GeoIP

Verovatno ste već bili u prilici da koristite Google Analytics alat, gde između ostalog možete na mapi sveta videti odakle tačno dolaze posetioci vašeg sajta, ili ste tu i tamo posetili sajt koji bi Vam između ostalog izbacio podatke o Vašoj trenutnoj lokaciji. Naravno, nije u pitanju nikakva magija, tačna lokacija posetioca definisana je na osnovu njegove IP adrese, a tehnologija koja se koristi prilikom “lociranja” korisnika opšte je poznata pod nazivom GeoIP.

Danas ćemo pričati o tome kako “locirati” posetioca pomoću PHP-a i Max Mind-ove GeoIP baze. U primerima koji slede koristicemo besplatne(lite) verzije GeoIP baza, obzirom da se za pune verzije plaća $50USD + $12USD za update (GeoIP Country baza) i $370USD + $90USD za update (GeoIP City baza). Mana lite verzija je što nisu uvek 100% ažurne, ali će odlično poslužiti za naš tutorijal, a iz ličnog iskustva tvrdim da su upotrebljive i u većini live projekata.

MaxMind obezbeđuje API za nekoliko popularnih programskih jezika, (kompletna lista dostupna je ovde), a detalji o PHP API-u dostupni su ovde. Pored takozvanog “Pure PHP API-a” koji ćemo ovde koristiti, postoje i PECL ektstenzija kao i apache modul(mod_geoip), koji pružaju bolje perfomanse ali i komplikovaniji setup.

Za početak neophodno je da skinete sve fajlove koji se nalaze na http://www.maxmind.com/download/geoip/api/php/ i snimite ih negde unutar vašeg Web stabla(recimo /htdocs/geoip). Za korišćenje GeoIP Country treba skinuti lite bazu odavde, a za city GeoLiteCity bazu odavde. Radi jednostavnosti korišćenja, obe baze ćemo takođe raspakovati u isti direktorijum gde smo i snimili fajlove iz PHP API-a (/htdocs/geoip).

GeoIP Country
——————————–

Idemo sa primerom detekcije zemlje posetioca:

<?php
/**
 * Primer Koriscenja GeoIP Country Baze
 * 
 * @version $Id$
 * @package geoip
 * @copyright © 2006 Lampix.net
 * @author Dragan Dinic <dinke@lampix.net>
 */

require_once("geoip.inc");

$gi = geoip_open("GeoIP.dat", GEOIP_STANDARD);

$ip = $_SERVER['REMOTE_ADDR'];
//ako testirate u lokalu koristite ovaj ip radi testa
//posto ce $_SERVER['SERVER_ADDR'] biti 127.0.0.1
//$ip = "89.216.226.174";

$country_name = geoip_country_name_by_addr($gi, $ip);
$country_code = geoip_country_code_by_addr($gi, $ip);
if($country_name)
{
	echo "Zemlja iz koje nas posecujete je: $country_name <br />";
	echo "Skracena Oznaka: $country_code <br />";
}
else 
{
	echo "Nazalost, nismo bili u mogucnosti da vas lociramo.";
}

geoip_close($gi);
?>

Dakle, na početku uključujemo geoip.inc koji sadrži sve f-je potrebne za korišćenje GeoIP County baze, zatim kreiramo novu instancu GeoIP klase pomoću geoip_open f-je, i na kraju pozivamo odgovarajuće f-je (geoip_country_name_by_addr i geoip_country_code_by_addr) da bi smo dobili ime/kod zemlje u kojoj se nalazi ip adresa posetioca(u slučaju da testirate u lokalu nemojte koristiti $_SERVER[‘REMOTE_ADDR’]).

Kao izlaz skripta, trebalo bi da dobijemo nešto poput:

Zemlja iz koje nas posecujete je: Serbia and Montenegro 
Skracena Oznaka: CS

F-je koje smo koristili da bi dobili podatke o zemlji posetioca, samo su neke od f-ja koje su dostupne u API-u. Ostatak možete i sami pronaći jednostavnom analizom PHP sourca geoip.inc fajla.

GeoIP City
—————————-

A sada da proširimo podatke o zemlji sa tačnom lokacijom (grad, poštanski kod itd).

<?php
/**
 * Primer Koriscenja GeoIP City Baze
 * 
 * @version $Id$
 * @package geoip
 * @copyright © 2006 Lampix.net
 * @author Dragan Dinic <dinke@lampix.net>
 */

require_once("geoipcity.inc");

$gi = geoip_open("GeoLiteCity.dat", GEOIP_STANDARD);

$ip = $_SERVER['REMOTE_ADDR'];
//ako testirate u lokalu koristite ovaj ip radi testa
//posto ce $_SERVER['SERVER_ADDR'] biti 127.0.0.1
//$ip = "89.216.226.174";

$record = geoip_record_by_addr($gi, $ip);

if(!$record)
{
	echo "Nazalost, nismo bili u mogucnosti da vas lociramo.";
}
else
{
	echo "Zemlja: " .$record->country_name . "<br />";
	echo "Skracena Oznaka: " . $record->country_code . "<br />";
	echo "Skracena Oznaka2: " . $record->country_code3 . "<br />";
	echo "Region: " .$record->region . "<br />";
	echo "Grad: " .$record->city . "<br />";
	echo "Postanski Kod: " .$record->postal_code . "<br />";
	echo "Geog. Sirina: " .$record->latitude . "<br />";
	echo "Geog. Duzina: " .$record->longitude . "<br />";
}

geoip_close($gi);
?>

Kao što vidite, PHP kod je sličan kodu za detekciju zemlje, s tim što smo koristili geoipcity.inc kao i GeoLiteCity.dat bazu. F-ja geoip_record_by_addr($gi, $ip) vraća instancu klase ‘geoiprecord’ koja sadrži kao promenljive(osobine) podatke o lokaciji koje koristimo u gornjem kodu. Nakon pokretanja skripta trebalo bi da dobijemo nešto poput:

Zemlja: Serbia and Montenegro
Skracena Oznaka: CS
Skracena Oznaka2: SCG
Region: 02
Grad: Beograd
Postanski Kod: 
Geog. Sirina: 44.8186
Geog. Duzina: 20.4681

Napominjem da je GeoIP baza najažurnija kada su u pitanju gradovi sa severnoameričkog dela planete, dok je njena preciznost znatno manja kada se dođe do “egzotike” u koju nažalost spada i Srbija.

CaseStudy – Redirekcija na osnovu IP adrese
————————————————————–
Za kraj znanje stečeno ovde iskoristićemo u jednom pravom projektu. Naime cilj je da se na dvojezičnom sajtu(blogu) korisnici koji dolaze iz Srbije usmere na srpsku verziju sajta, dok će se svi ostali usmeriti na englesku verziju. Evo kako to izgleda:

<?php
/**
 * Case Study - Redirekcija na osnovu lokacije
 * 
 * @version $Id$
 * @package geoip
 * @copyright © 2006 Lampix.net
 * @author Dragan Dinic <dinke@lampix.net>
 */

require_once("geoip/geoip.inc");

$gi = geoip_open("geoip/GeoIP.dat",GEOIP_STANDARD);

$country_code = geoip_country_code_by_addr($gi, $_SERVER['REMOTE_ADDR']);

geoip_close($gi);

if($country_code == 'CS')
{
        header("HTTP/1.1 301 Moved Permanently");
        header('Location: http://www.dinke.net/blog/sr/');
}
else
{
        header("HTTP/1.1 301 Moved Permanently");
        header('Location: http://www.dinke.net/blog/en/');
}
?>

Primer koji vidite gore koristi se upravo na ovom blogu, kako bi sve korisnike koji ne dolaze iz Srbije automatski preusmerio na englesku verziju bloga. Slanje custom 301 redirection headera je važno kako bi botovi (Google i sl.) indeksirali strane na odgovarajući način.

PHP 5.2 upload progress meter

Yesterday I’ve spent considerable amount of time in order to find out more about the most interesting new PHP 5.2 feature – hook for upload progress meter. Except for this link I haven’t found anything else, no php source code example how to make one.

However, after I looked at internal php mailing list archive, I’ve found this thread, still no php data found, but Rasmus mentioned link with an example at http://progphp.com/progress.php. I immediately tried upload and it looked very cool. Then I looked at html source code and noticed one unusual thing there: APC_UPLOAD_PROGRESS hidden field inside of html source. I knew it must be important so I’ve googled for it, and insteresting enough first result was source code of Rasmus example above 🙂

So, I took complete source (I figured out later it is upload meter example made by Rasmus Lerdorf) and quickly tried to make it working under my fresh new installed PHP 5.2.0. Unfortunately, it didn’t work since it needed apc stuff installed. After I looked at apc documentation, I found that I need to grab it from list of pecl dll’s for windows php 5.2 version. Unfortunately, after I’ve downloaded it from here I’ve noticed apc dll is missing there ?!!

Again, I had to google for php_apc.dll and after a while found needed dll available at http://pecl4win.php.net/ext.php/php_apc.dll. In order to make it working, you have to save dll file under php/ext dir (i.e. c:\php\ext on windows) and put this to php.ini:

extension=php_apc.dll

Unfortunately, it still didn’t work, so I’ve looked at apc docs further. Finally on this page I’ve found apc have new “special feature” which is directly related to our new upload feature.

    apc.rfc1867             RFC1867 File Upload Progress hook handler is only available
                            if you compiled APC against PHP 5.2.0 or later.  When enabled
                            any file uploads which includes a field called 
                            APC_UPLOAD_PROGRESS before the file field in an upload form
                            will cause APC to automatically create an upload_
                            user cache entry where  is the value of the 
                            APC_UPLOAD_PROGRESS form entry.
                            (Default: 0)

After I figured out on my phpinfo page apc.rfc1867 setting is turned off, I’ve added

apc.rfc1867 = on 

in php.ini, and after restart was finally able to enjoy new fancy upload progress meter 🙂

upload progress meter

Btw, upload also depend of json turned on as well, but it was already turned on so I didn’t have any more problems.

About the code Rasmus used in his example, I am tired to analyze it more now, but obviously it use Yahoo! User Interface Library to create progress bar and json/apc to control it from php during file upload.

I hope this will be helpful for someone. Enjoy 😉