Нужна помощь с определением местоположения сайта - PullRequest
0 голосов
/ 11 ноября 2010

У меня есть веб-сайт, и я хочу, чтобы он определял местоположение пользователя и в соответствии с этим перемещал пользователя в правильный поддомен. Пример: Если я перейду на сайт из Франции, я хочу, чтобы он перенаправил меня на сайт www.website.com/France. и бросить на ...

Как я могу это сделать, пожалуйста?

Ответы [ 2 ]

0 голосов
/ 08 ноября 2011

Вот решение, которое я использую на своем сайте [www.vladonai.com] [1], оно 100% бесплатно (используется ежедневно обновляется [www.zaigadgets.com/geoip][2 ] source), очень быстро (возможно, намного быстрее, чем мог бы MySQL), и не требует базы данных . База данных хранится в двоичном файле, поэтому все, что вам нужно, это любая версия PHP.

Функция преобразования IP в название страны выглядит следующим образом:

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;
}

Перед использованием вышеуказанной функции вам необходимо скомпилировать файл базы данных, используя следующую функцию:

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>";
}

Теперь, если вам это нравится, вы можете использовать функцию ниже для преобразования двухбуквенного кода страны в читаемое название страны:

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;
}

Наслаждайтесь!

0 голосов
/ 11 ноября 2010

На уровне сервера приложений вы можете узнать, из какой страны пользователь, просмотрев его в базе данных ip-2-country.Обычно это продукты, которые вы покупаете у компании-разработчика программного обеспечения, специализирующейся на этом, с различными базами данных для различных нужд.

Вот один из них: ip2country

Вы также можете сделать это наУровень DNS, если у вас есть поставщик DNS, который может сделать это для вас.Это, наверное, то, что имеет для вас наибольшее значение.Тогда ваши посетители будут сразу же отправлены на ближайший сервер без необходимости сначала связываться с «диспетчерским» сервером (DNS-сервер будет маршрутизатором), и после этого правильный IP-адрес будет кэширован каким-либо образом между DNS-сервером, отвечающим заДомен и DNS-сервер на пути к пользователю.

...