Need help with website location identifing
I have a website and I want to make it identify the user's location and according to that move the user to the开发者_高级运维 correct subdomain. An example: If I go to the website from France, I want it to redirect me to www.website.com/France and throw on...
How can I do that please?
At the application server level you can find out which country the user is from by looking it up in a ip-2-country database. They are usually products you buy from a software company specializing in this with different databases for different needs.
Here is one: ip2country
You can also do this on a dns-level if you have a dns provider that can do this for you. This is probably what makes most sense for you. Then your visitors would at once be sent to the nearest server without having to contact a "dispatcher" server first (the dns server would be the router) and after that the correct ip would be cached at some way between the dns server responsible for the domain and dns server along the way all the way to the user.
Here is the solution I'm using on my site [www.vladonai.com][1], it's 100% free (using daily updated [www.zaigadgets.com/geoip][2] source), very fast (possibly much faster than MySQL could do), and requires no database. The database is stored in a binary file, so all what you need is any version of PHP.
The function to convert IP to Country name looks like this:
function GetCountryFromIP($ip = "")
{
if ($ip == "")
$ip = $_SERVER['REMOTE_ADDR'];
//the db obtained from ZaiGadgets.com and converted using convert_ip2country_db_from_csv_to_binary_file_format function
$db_file_path = ip2Country_binary_db_filename;
if (!file_exists($db_file_path))
return "";
$db_file_handle = fopen($db_file_path, "rb");
if (!$db_file_handle)
return "";
$one_record_size = 10; //bytes
$low = 0;
$high = (filesize($db_file_path) / $one_record_size) - 1;
$mid = 0;
$ipFrom = 0;
$ipTo = 0;
$ipArrParts = explode('.', $ip);
$ipLong = ($ipArrParts[0] * 0x1000000) + ($ipArrParts[1] * 0x10000) + ($ipArrParts[2] * 0x100) + ($ipArrParts[3]);
$country = ""; //result
while($low <= $high)
{
$mid = (int)(($low + $high) / 2);
$file_pos = $mid * $one_record_size;
fseek($db_file_handle, $file_pos, SEEK_SET);
$ipFrom = ipdbv2_read32($db_file_handle);
$ipTo = ipdbv2_read32($db_file_handle);
if ($ipFrom < 0)
$ipFrom += pow(2, 32);
if ($ipTo < 0)
$ipTo += pow(2, 32);
if (($ipLong >= $ipFrom) && ($ipLong < $ipTo))
{
//found IP range :)
//echo "Found!!!!!<br>";
$country = fread($db_file_handle, 2);
fclose($db_file_handle);
$country = GetCountryNameFromCountryCode($country);
return $country;
} else
{
if($ipLong <$ipFrom)
{
$high = $mid - 1;
} else
{
$low = $mid + 1;
}
}
}
fclose($db_file_handle);
return "";
}
function ipdbv2_read32($db_file_handle)
{
$data = fread($db_file_handle, 4);
$output = unpack('V', $data);
$val_32_bit = $output[1];
if ($val_32_bit < 0)
$val_32_bit += 4294967296; //correct signed/unsigned issue on 32-bit platforms
return $val_32_bit;
}
Before using the function above you'll need to compile the datbase file using function below:
define( "ip2Country_binary_db_filename", "ip2country_zaigadgets.bin" );
function convert_ip2country_db_from_csv_to_binary_file_format($input_file_path = "")
{
//convert dataf from ZaiGadgets.com to binary db format
if ($input_file_path == "")
$input_file_path = "db.csv";
$output_file_path = ip2Country_binary_db_filename;
$input_file_content = file_get_contents($input_file_path); //read_text_file_content($input_file_path);
if ($input_file_content == "")
{
echo "Error: empty input db - " . $input_file_path . "<br>";
return; //nothing to do
}
unlink($output_file_path); //delete file content
$out_fileHandle = fopen($output_file_path, "cb");
if (!$out_fileHandle)
{
echo "ERROR: Cannot Create file! " . $output_file_path . "<br>";
return;
}
$records_count = 0;
$input_file_lines = explode("\n", $input_file_content); //split it to lines
echo "Text lines count: " . count($input_file_lines) . "<br>";
//for ($input_line_n = 0; $input_line_n < 10; $input_line_n ++)
for ($input_line_n = 0; $input_line_n < count($input_file_lines); $input_line_n ++)
{
$sub_line = $input_file_lines[$input_line_n];
if (strlen($sub_line) > 0 && is_numeric($sub_line[0]))
{
$sub_values = explode(",", $input_file_lines[$input_line_n]);
if (count($sub_values) == 4)
{
$start_ip_addr = $sub_values[0];
$end_ip_addr = $sub_values[1];
$country_code = $sub_values[2];
if (strlen($country_code) == 2)
{
fwrite($out_fileHandle, pack("V", (float)$start_ip_addr), 4);
fwrite($out_fileHandle, pack("V", (float)$end_ip_addr), 4);
fwrite($out_fileHandle, $country_code, strlen($country_code));
$records_count ++;
} else
{
echo "Invalid line " . $input_line_n . " [wrong country len]: " . $sub_line . "<br>";
}
} else
{
echo "Invalid line " . $input_line_n . ": " . $sub_line . "<br>";
}
} else
if ($sub_line != "" && $sub_line[0] != '#' && $sub_line != "startip,endip,countrycode,countryname")
{
echo "Invalid line " . $input_line_n . ": " . $sub_line . "<br>";
}
}
fclose($out_fileHandle);
echo "Data size verification result: " . ($records_count * 10 == filesize($output_file_path) ? "OK" : "Error") . "<br>";
echo "Exported records (blocks) count: " . $records_count . "<br>";
echo "Exporting complete.<br>";
}
Now, if you like it, you can use function below to convert 2-letter country code to readable country name:
function GetCountryNameFromCountryCode($country_code, $b_very_strict = false)
{
$countries = array (
"ac" => "ASCENSION ISLAND",
"ad" => "ANDORRA",
"ae" => "UNITED ARAB EMIRATES",
"af" => "AFGHANISTAN",
"ag" => "ANTIGUA AND BARBUDA",
"ai" => "ANGUILLA",
"al" => "ALBANIA",
"am" => "ARMENIA",
"an" => "NETHERLANDS ANTILLES",
"ao" => "ANGOLA",
"aq" => "ANTARCTICA",
"ar" => "ARGENTINA",
"as" => "AMERICAN SAMOA",
"at" => "AUSTRIA",
"au" => "AUSTRALIA",
"aw" => "ARUBA",
"ax" => "ALAND",
"az" => "AZERBAIJAN",
"ba" => "BOSNIA AND HERZEGOVINA",
"bb" => "BARBADOS",
"bd" => "BANGLADESH",
"be" => "BELGIUM",
"bf" => "BURKINA FASO",
"bg" => "BULGARIA",
"bh" => "BAHRAIN",
"bi" => "BURUNDI",
"bj" => "BENIN",
"bl" => "SAINT BARTHELEMY",
"bm" => "BERMUDA",
"bn" => "BRUNEI DARUSSALAM",
"bo" => "BOLIVIA",
"bu" => "BONAIRE, SAINT EUSTATIUS AND SABA",
"br" => "BRAZIL",
"bs" => "BAHAMAS",
"bt" => "BHUTAN",
"bv" => "BOUVET ISLAND",
"bw" => "BOTSWANA",
"by" => "BELARUS",
"bz" => "BELIZE",
"ca" => "CANADA",
"cc" => "COCOS (KEELING) ISLANDS",
"cd" => "CONGO",
"cf" => "CENTRAL AFRICAN REPUBLIC",
"cg" => "REPUBLIC OF THE CONGO",
"ch" => "SWITZERLAND",
"ci" => "COTE D?VOIRE",
"ck" => "COOK ISLANDS",
"cl" => "CHILE",
"cm" => "CAMEROON",
"cn" => "CHINA",
"co" => "COLOMBIA",
"cr" => "COSTA RICA",
"cu" => "CUBA",
"cv" => "CAPE VERDE",
"cw" => "CURACAO",
"cx" => "CHRISTMAS ISLAND",
"cy" => "CYPRUS",
"cz" => "CZECH REPUBLIC",
"de" => "GERMANY",
"dj" => "DJIBOUTI",
"dk" => "DENMARK",
"dm" => "DOMINICA",
"do" => "DOMINICAN REPUBLIC",
"dz" => "ALGERIA",
"ec" => "ECUADOR",
"ee" => "ESTONIA",
"eg" => "EGYPT",
"eh" => "WESTERN SAHARA",
"er" => "ERITREA",
"eu" => "EUROPEAN UNION",
"es" => "SPAIN",
"et" => "ETHIOPIA",
"fi" => "FINLAND",
"fj" => "FIJI",
"fk" => "FALKLAND ISLANDS",
"fm" => "MICRONESIA",
"fo" => "FAROE ISLANDS",
"fr" => "FRANCE",
"ga" => "GABON",
"gb" => "UNITED KINGDOM",
"gd" => "GRENADA",
"ge" => "GEORGIA",
"gf" => "FRENCH GUIANA",
"gg" => "GUERNSEY",
"gh" => "GHANA",
"gi" => "GIBRALTAR",
"gl" => "GREENLAND",
"gm" => "THE GAMBIA",
"gn" => "GUINEA",
"gp" => "GUADELOUPE",
"gq" => "EQUATORIAL GUINEA",
"gr" => "GREECE",
"gs" => "SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS",
"gt" => "GUATEMALA",
"gu" => "GUAM",
"gw" => "GUINEA-BISSAU",
"gy" => "GUYANA",
"hk" => "HONG KONG",
"hn" => "HONDURAS",
"hr" => "CROATIA",
"ht" => "HAITI",
"hu" => "HUNGARY",
"id" => "INDONESIA",
"ie" => "IRELAND",
"il" => "ISRAEL",
"im" => "ISLE OF MAN",
"in" => "INDIA",
"io" => "BRITISH INDIAN OCEAN TERRITORY",
"iq" => "IRAQ",
"ir" => "IRAN",
"is" => "ICELAND",
"it" => "ITALY",
"je" => "JERSEY",
"jm" => "JAMAICA",
"jo" => "JORDAN",
"jp" => "JAPAN",
"ke" => "KENYA",
"kg" => "KYRGYZSTAN",
"kh" => "CAMBODIA",
"ki" => "KIRIBATI",
"km" => "COMOROS",
"kn" => "SAINT KITTS AND NEVIS",
"kp" => "KOREA, DEMOCRATIC PEOPLE'S REPUBLIC OF",
"kr" => "SOUTH KOREA",
"kw" => "KUWAIT",
"ky" => "CAYMAN ISLANDS",
"kz" => "KAZAKHSTAN",
"la" => "LAOS",
"lb" => "LEBANON",
"lc" => "SAINT LUCIA",
"li" => "LIECHTENSTEIN",
"lk" => "SRI LANKA",
"lr" => "LIBERIA",
"ls" => "LESOTHO",
"lt" => "LITHUANIA",
"lu" => "LUXEMBOURG",
"lv" => "LATVIA",
"ly" => "LIBYA",
"ma" => "MOROCCO",
"mc" => "MONACO",
"md" => "MOLDOVA",
"me" => "MONTENEGRO",
"mf" => "SAINT MARTIN (FRENCH PART)",
"mg" => "MADAGASCAR",
"mh" => "MARSHALL ISLANDS",
"mk" => "REPUBLIC OF MACEDONIA",
"ml" => "MALI",
"mm" => "MYANMAR",
"mn" => "MONGOLIA",
"mo" => "MACAO",
"mp" => "NORTHERN MARIANA ISLANDS",
"mq" => "MARTINIQUE",
"mr" => "MAURITANIA",
"ms" => "MONTSERRAT",
"mt" => "MALTA",
"mu" => "MAURITIUS",
"mv" => "MALDIVES",
"mw" => "MALAWI",
"mx" => "MEXICO",
"my" => "MALAYSIA",
"mz" => "MOZAMBIQUE",
"na" => "NAMIBIA",
"nc" => "NEW CALEDONIA",
"ne" => "NIGER",
"nf" => "NORFOLK ISLAND",
"ng" => "NIGERIA",
"ni" => "NICARAGUA",
"nl" => "NETHERLANDS",
"no" => "NORWAY",
"np" => "NEPAL",
"nr" => "NAURU",
"nu" => "NIUE",
"nz" => "NEW ZEALAND",
"om" => "OMAN",
"pa" => "PANAMA",
"pe" => "PERU",
"pf" => "FRENCH POLYNESIA",
"pg" => "PAPUA NEW GUINEA",
"ph" => "PHILIPPINES",
"pk" => "PAKISTAN",
"pl" => "POLAND",
"pm" => "SAINT PIERRE AND MIQUELON",
"pn" => "PITCAIRN ISLANDS",
"pr" => "PUERTO RICO",
"ps" => "PALESTINIAN TERRITORY, OCCUPIED",
"pt" => "PORTUGAL",
"pw" => "PALAU",
"py" => "PARAGUAY",
"qa" => "QATAR",
"re" => "REUNION",
"ro" => "ROMANIA",
"rs" => "SERBIA",
"ru" => "RUSSIA",
"rw" => "RWANDA",
"sa" => "SAUDI ARABIA",
"sb" => "SOLOMON ISLANDS",
"sc" => "SEYCHELLES",
"sd" => "SUDAN",
"se" => "SWEDEN",
"sg" => "SINGAPORE",
"sh" => "SAINT HELENA",
"si" => "SLOVENIA",
"sj" => "SVALBARD AND JAN MAYEN",
"sk" => "SLOVAKIA",
"sl" => "SIERRA LEONE",
"sm" => "SAN MARINO",
"sn" => "SENEGAL",
"so" => "SOMALIA",
"sr" => "SURINAME",
"st" => "SAO TOME AND PRINCIPE",
"su" => "RUSSIA", //ex-USSR, let's presume it's russia
"sv" => "EL SALVADOR",
"sx" => "SINT MAARTEN (DUTCH PART)",
"sy" => "SYRIA",
"sz" => "SWAZILAN",
"tc" => "TURKS AND CAICOS ISLANDS",
"td" => "CHAD",
"tf" => "FRENCH SOUTHERN TERRITORIES",
"tg" => "TOGO",
"th" => "THAILAND",
"tj" => "TAJIKISTAN",
"tk" => "TOKELAU",
"tl" => "EAST TIMOR",
"tm" => "TURKMENISTAN",
"tn" => "TUNISIA",
"to" => "TONGA",
"tp" => "EAST TIMOR",
"tr" => "TURKEY",
"tt" => "TRINIDAD AND TOBAGO",
//"tv" => "TUVALU", don't include it here - it conflicts with .tv domain!
"tw" => "TAIWAN",
"tz" => "TANZANIA",
"ua" => "UKRAINE",
"ug" => "UGANDA",
"uk" => "UNITED KINGDOM",
"um" => "UNITED STATES MINOR OUTLYING ISLAND",
"us" => "UNITED STATES",
"uy" => "URUGUAY",
"uz" => "UZBEKISTAN",
"va" => "VATICAN CITY STATE",
"vc" => "SAINT VINCENT AND THE GRENADINES",
"ve" => "VENEZUELA",
"vg" => "BRITISH VIRGIN ISLANDS",
"vi" => "U.S. VIRGIN ISLANDS",
"vn" => "VIETNAM",
"vu" => "VANUATU",
"wf" => "WALLIS AND FUTUNA",
"ws" => "SAMOA",
"ye" => "YEMEN",
"yt" => "MAYOTTE",
"yu" => "YUGOSLAVIA",
"za" => "SOUTH AFRICA",
"zm" => "ZAMBIA",
"zw" => "ZIMBABWE"
);
$country = $countries[strtolower($country_code)];
if ($country == "" && !$b_very_strict)
$country = $country_code; //return at least something
return $country;
}
Enjoy!
精彩评论