mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-04-02 01:52:10 +09:00
Add Korea class and Korean IP range database
This commit is contained in:
parent
45457cbb55
commit
cd057527ac
6 changed files with 5107 additions and 0 deletions
3863
common/defaults/korea.ipv4.php
Normal file
3863
common/defaults/korea.ipv4.php
Normal file
File diff suppressed because it is too large
Load diff
503
common/defaults/korea.ipv6.php
Normal file
503
common/defaults/korea.ipv6.php
Normal file
|
|
@ -0,0 +1,503 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Source: https://ip.kisa.or.kr/ip_cate_stat/stat_05_05.act
|
||||
* Last Updated: 2016-03-18
|
||||
*/
|
||||
return array (
|
||||
0 =>
|
||||
array (
|
||||
0 => '2001000000000000',
|
||||
1 => '2001000fffffffff',
|
||||
),
|
||||
1 =>
|
||||
array (
|
||||
0 => '2001022000000000',
|
||||
1 => '20010220ffffffff',
|
||||
),
|
||||
2 =>
|
||||
array (
|
||||
0 => '2001023000000000',
|
||||
1 => '20010230ffffffff',
|
||||
),
|
||||
3 =>
|
||||
array (
|
||||
0 => '2001027000000000',
|
||||
1 => '20010270ffffffff',
|
||||
),
|
||||
4 =>
|
||||
array (
|
||||
0 => '2001028000000000',
|
||||
1 => '20010280ffffffff',
|
||||
),
|
||||
5 =>
|
||||
array (
|
||||
0 => '2001029000000000',
|
||||
1 => '20010290ffffffff',
|
||||
),
|
||||
6 =>
|
||||
array (
|
||||
0 => '200102b000000000',
|
||||
1 => '200102b0ffffffff',
|
||||
),
|
||||
7 =>
|
||||
array (
|
||||
0 => '200102b800000000',
|
||||
1 => '200102b8ffffffff',
|
||||
),
|
||||
8 =>
|
||||
array (
|
||||
0 => '200102d800000000',
|
||||
1 => '200102d8ffffffff',
|
||||
),
|
||||
9 =>
|
||||
array (
|
||||
0 => '2001032000000000',
|
||||
1 => '20010320ffffffff',
|
||||
),
|
||||
10 =>
|
||||
array (
|
||||
0 => '2001033000000000',
|
||||
1 => '20010330ffffffff',
|
||||
),
|
||||
11 =>
|
||||
array (
|
||||
0 => '2001037800000000',
|
||||
1 => '20010378ffffffff',
|
||||
),
|
||||
12 =>
|
||||
array (
|
||||
0 => '2001039000000000',
|
||||
1 => '20010390ffffffff',
|
||||
),
|
||||
13 =>
|
||||
array (
|
||||
0 => '200103a800000000',
|
||||
1 => '200103a8ffffffff',
|
||||
),
|
||||
14 =>
|
||||
array (
|
||||
0 => '200107fa00000002',
|
||||
1 => '200107fa00000002',
|
||||
),
|
||||
15 =>
|
||||
array (
|
||||
0 => '200107fa00080000',
|
||||
1 => '200107fa0008ffff',
|
||||
),
|
||||
16 =>
|
||||
array (
|
||||
0 => '20010c4800000000',
|
||||
1 => '20010c48ffffffff',
|
||||
),
|
||||
17 =>
|
||||
array (
|
||||
0 => '20010c9800000000',
|
||||
1 => '20010c98ffffffff',
|
||||
),
|
||||
18 =>
|
||||
array (
|
||||
0 => '20010cf000000000',
|
||||
1 => '20010cf0ffffffff',
|
||||
),
|
||||
19 =>
|
||||
array (
|
||||
0 => '20010d3800000000',
|
||||
1 => '20010d38ffffffff',
|
||||
),
|
||||
20 =>
|
||||
array (
|
||||
0 => '20010dc500000000',
|
||||
1 => '20010dc5ffffffff',
|
||||
),
|
||||
21 =>
|
||||
array (
|
||||
0 => '20010dcc00000000',
|
||||
1 => '20010dccffffffff',
|
||||
),
|
||||
22 =>
|
||||
array (
|
||||
0 => '20010ea000000000',
|
||||
1 => '20010ea0ffffffff',
|
||||
),
|
||||
23 =>
|
||||
array (
|
||||
0 => '20010ea800000000',
|
||||
1 => '20010ea8ffffffff',
|
||||
),
|
||||
24 =>
|
||||
array (
|
||||
0 => '20010eb800000000',
|
||||
1 => '20010eb8ffffffff',
|
||||
),
|
||||
25 =>
|
||||
array (
|
||||
0 => '20010ed000000000',
|
||||
1 => '20010ed0ffffffff',
|
||||
),
|
||||
26 =>
|
||||
array (
|
||||
0 => '20010ee800000000',
|
||||
1 => '20010ee8ffffffff',
|
||||
),
|
||||
27 =>
|
||||
array (
|
||||
0 => '20010ef000000000',
|
||||
1 => '20010ef0ffffffff',
|
||||
),
|
||||
28 =>
|
||||
array (
|
||||
0 => '20010ef800000000',
|
||||
1 => '20010ef8ffffffff',
|
||||
),
|
||||
29 =>
|
||||
array (
|
||||
0 => '20010f2800000000',
|
||||
1 => '20010f28ffffffff',
|
||||
),
|
||||
30 =>
|
||||
array (
|
||||
0 => '20010f4800000000',
|
||||
1 => '20010f48ffffffff',
|
||||
),
|
||||
31 =>
|
||||
array (
|
||||
0 => '24033e0000000000',
|
||||
1 => '24033e00ffffffff',
|
||||
),
|
||||
32 =>
|
||||
array (
|
||||
0 => '2001443000000000',
|
||||
1 => '20014430ffffffff',
|
||||
),
|
||||
33 =>
|
||||
array (
|
||||
0 => '2400000000000000',
|
||||
1 => '24000fffffffffff',
|
||||
),
|
||||
34 =>
|
||||
array (
|
||||
0 => '2400180000000000',
|
||||
1 => '24001800ffffffff',
|
||||
),
|
||||
35 =>
|
||||
array (
|
||||
0 => '2400330000000000',
|
||||
1 => '24003300ffffffff',
|
||||
),
|
||||
36 =>
|
||||
array (
|
||||
0 => '2400478000000000',
|
||||
1 => '24004780ffffffff',
|
||||
),
|
||||
37 =>
|
||||
array (
|
||||
0 => '2400498000000000',
|
||||
1 => '24004980ffffffff',
|
||||
),
|
||||
38 =>
|
||||
array (
|
||||
0 => '24009f8000000000',
|
||||
1 => '24009f80ffffffff',
|
||||
),
|
||||
39 =>
|
||||
array (
|
||||
0 => '2400a58000000000',
|
||||
1 => '2400a580ffffffff',
|
||||
),
|
||||
40 =>
|
||||
array (
|
||||
0 => '2400ab0000000000',
|
||||
1 => '2400ab00ffffffff',
|
||||
),
|
||||
41 =>
|
||||
array (
|
||||
0 => '2400cf0000000000',
|
||||
1 => '2400cf00ffffffff',
|
||||
),
|
||||
42 =>
|
||||
array (
|
||||
0 => '2400fd8000000000',
|
||||
1 => '2400fd80ffffffff',
|
||||
),
|
||||
43 =>
|
||||
array (
|
||||
0 => '2401270000000000',
|
||||
1 => '24012700ffffffff',
|
||||
),
|
||||
44 =>
|
||||
array (
|
||||
0 => '2401400000000000',
|
||||
1 => '24014000ffffffff',
|
||||
),
|
||||
45 =>
|
||||
array (
|
||||
0 => '2401a00000000000',
|
||||
1 => '2401a000ffffffff',
|
||||
),
|
||||
46 =>
|
||||
array (
|
||||
0 => '2401a80000000000',
|
||||
1 => '2401a800ffffffff',
|
||||
),
|
||||
47 =>
|
||||
array (
|
||||
0 => '2401c50000000000',
|
||||
1 => '2401c500ffffffff',
|
||||
),
|
||||
48 =>
|
||||
array (
|
||||
0 => '2402000000000000',
|
||||
1 => '240200ffffffffff',
|
||||
),
|
||||
49 =>
|
||||
array (
|
||||
0 => '24021a0000000000',
|
||||
1 => '24021a00ffffffff',
|
||||
),
|
||||
50 =>
|
||||
array (
|
||||
0 => '2402310000000000',
|
||||
1 => '24023100ffffffff',
|
||||
),
|
||||
51 =>
|
||||
array (
|
||||
0 => '2402580000000000',
|
||||
1 => '24025800ffffffff',
|
||||
),
|
||||
52 =>
|
||||
array (
|
||||
0 => '2402610000000000',
|
||||
1 => '24026100ffffffff',
|
||||
),
|
||||
53 =>
|
||||
array (
|
||||
0 => '2402700000000000',
|
||||
1 => '24027000ffffffff',
|
||||
),
|
||||
54 =>
|
||||
array (
|
||||
0 => '2402be0000000000',
|
||||
1 => '2402be00ffffffff',
|
||||
),
|
||||
55 =>
|
||||
array (
|
||||
0 => '2402de0000000000',
|
||||
1 => '2402de00ffffffff',
|
||||
),
|
||||
56 =>
|
||||
array (
|
||||
0 => '2402f40000000000',
|
||||
1 => '2402f400ffffffff',
|
||||
),
|
||||
57 =>
|
||||
array (
|
||||
0 => '2403370000000000',
|
||||
1 => '24033700ffffffff',
|
||||
),
|
||||
58 =>
|
||||
array (
|
||||
0 => '2403630000000000',
|
||||
1 => '24036300ffffffff',
|
||||
),
|
||||
59 =>
|
||||
array (
|
||||
0 => '2403650000000000',
|
||||
1 => '24036500ffffffff',
|
||||
),
|
||||
60 =>
|
||||
array (
|
||||
0 => '2404000000000000',
|
||||
1 => '2404000fffffffff',
|
||||
),
|
||||
61 =>
|
||||
array (
|
||||
0 => '2404080000000000',
|
||||
1 => '24040800ffffffff',
|
||||
),
|
||||
62 =>
|
||||
array (
|
||||
0 => '2404230000000000',
|
||||
1 => '24042300ffffffff',
|
||||
),
|
||||
63 =>
|
||||
array (
|
||||
0 => '2404460000000000',
|
||||
1 => '24044600ffffffff',
|
||||
),
|
||||
64 =>
|
||||
array (
|
||||
0 => '2405350000000000',
|
||||
1 => '24053500ffffffff',
|
||||
),
|
||||
65 =>
|
||||
array (
|
||||
0 => '2405430000000000',
|
||||
1 => '24054300ffffffff',
|
||||
),
|
||||
66 =>
|
||||
array (
|
||||
0 => '2405580000000000',
|
||||
1 => '24055800ffffffff',
|
||||
),
|
||||
67 =>
|
||||
array (
|
||||
0 => '20010e6000000000',
|
||||
1 => '20010e60ffffffff',
|
||||
),
|
||||
68 =>
|
||||
array (
|
||||
0 => '20010e7000000000',
|
||||
1 => '20010e70ffffffff',
|
||||
),
|
||||
69 =>
|
||||
array (
|
||||
0 => '20010e7800000000',
|
||||
1 => '20010e78ffffffff',
|
||||
),
|
||||
70 =>
|
||||
array (
|
||||
0 => '20010e9800000000',
|
||||
1 => '20010e98ffffffff',
|
||||
),
|
||||
71 =>
|
||||
array (
|
||||
0 => '24009e8000000000',
|
||||
1 => '24009e80ffffffff',
|
||||
),
|
||||
72 =>
|
||||
array (
|
||||
0 => '2400e18000000000',
|
||||
1 => '2400e180ffffffff',
|
||||
),
|
||||
73 =>
|
||||
array (
|
||||
0 => '2401e20000000000',
|
||||
1 => '2401e200ffffffff',
|
||||
),
|
||||
74 =>
|
||||
array (
|
||||
0 => '24053d0000000000',
|
||||
1 => '24053d00ffffffff',
|
||||
),
|
||||
75 =>
|
||||
array (
|
||||
0 => '24055f0000000000',
|
||||
1 => '24055f00ffffffff',
|
||||
),
|
||||
76 =>
|
||||
array (
|
||||
0 => '24057b0000000000',
|
||||
1 => '24057b00ffffffff',
|
||||
),
|
||||
77 =>
|
||||
array (
|
||||
0 => '2405860000000000',
|
||||
1 => '24058600ffffffff',
|
||||
),
|
||||
78 =>
|
||||
array (
|
||||
0 => '2405950000000000',
|
||||
1 => '24059500ffffffff',
|
||||
),
|
||||
79 =>
|
||||
array (
|
||||
0 => '2405c00000000000',
|
||||
1 => '2405c000ffffffff',
|
||||
),
|
||||
80 =>
|
||||
array (
|
||||
0 => '2406400000000000',
|
||||
1 => '24064000ffffffff',
|
||||
),
|
||||
81 =>
|
||||
array (
|
||||
0 => '2406590000000000',
|
||||
1 => '24065900ffffffff',
|
||||
),
|
||||
82 =>
|
||||
array (
|
||||
0 => '2406660000000000',
|
||||
1 => '24066600ffffffff',
|
||||
),
|
||||
83 =>
|
||||
array (
|
||||
0 => '2406680000000000',
|
||||
1 => '24066800ffffffff',
|
||||
),
|
||||
84 =>
|
||||
array (
|
||||
0 => '24066a0000000000',
|
||||
1 => '24066a00ffffffff',
|
||||
),
|
||||
85 =>
|
||||
array (
|
||||
0 => '2406ad0000000000',
|
||||
1 => '2406ad00ffffffff',
|
||||
),
|
||||
86 =>
|
||||
array (
|
||||
0 => '2406b00000000000',
|
||||
1 => '2406b000ffffffff',
|
||||
),
|
||||
87 =>
|
||||
array (
|
||||
0 => '2406d00000000000',
|
||||
1 => '2406d000ffffffff',
|
||||
),
|
||||
88 =>
|
||||
array (
|
||||
0 => '2406d70000000000',
|
||||
1 => '2406d700ffffffff',
|
||||
),
|
||||
89 =>
|
||||
array (
|
||||
0 => '24070b0000000000',
|
||||
1 => '24070b00ffffffff',
|
||||
),
|
||||
90 =>
|
||||
array (
|
||||
0 => '2407200000000000',
|
||||
1 => '24072000ffffffff',
|
||||
),
|
||||
91 =>
|
||||
array (
|
||||
0 => '2407350000000000',
|
||||
1 => '24073500ffffffff',
|
||||
),
|
||||
92 =>
|
||||
array (
|
||||
0 => '2407650000000000',
|
||||
1 => '24076500ffffffff',
|
||||
),
|
||||
93 =>
|
||||
array (
|
||||
0 => '2407670000000000',
|
||||
1 => '24076700ffffffff',
|
||||
),
|
||||
94 =>
|
||||
array (
|
||||
0 => '2407910000000000',
|
||||
1 => '24079100ffffffff',
|
||||
),
|
||||
95 =>
|
||||
array (
|
||||
0 => '2407b20000000000',
|
||||
1 => '2407b200ffffffff',
|
||||
),
|
||||
96 =>
|
||||
array (
|
||||
0 => '2407b80000000000',
|
||||
1 => '2407b800ffffffff',
|
||||
),
|
||||
97 =>
|
||||
array (
|
||||
0 => '2407c00000000000',
|
||||
1 => '2407c000ffffffff',
|
||||
),
|
||||
98 =>
|
||||
array (
|
||||
0 => '2407c70000000000',
|
||||
1 => '2407c700ffffffff',
|
||||
),
|
||||
);
|
||||
453
common/framework/korea.php
Normal file
453
common/framework/korea.php
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
<?php
|
||||
|
||||
namespace Rhymix\Framework;
|
||||
|
||||
/**
|
||||
* Class for validating Korea-specific information.
|
||||
*/
|
||||
class Korea
|
||||
{
|
||||
/**
|
||||
* Format a phone number.
|
||||
*
|
||||
* @param string $num
|
||||
* @return string
|
||||
*/
|
||||
public static function formatPhoneNumber($num)
|
||||
{
|
||||
// Remove all non-numbers.
|
||||
$num = preg_replace('/[^0-9]/', '', $num);
|
||||
|
||||
// Remove the country code.
|
||||
if (strncmp($num, '82', 2) === 0)
|
||||
{
|
||||
$num = substr($num, 2);
|
||||
if (strncmp($num, '0', 1) !== 0)
|
||||
{
|
||||
$num = '0' . $num;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply different format based on the number of digits.
|
||||
switch (strlen($num))
|
||||
{
|
||||
case 8:
|
||||
return substr($num, 0, 4) . '-' . substr($num, 4);
|
||||
case 9:
|
||||
return substr($num, 0, 2) . '-' . substr($num, 2, 3) . '-' . substr($num, 5);
|
||||
case 10:
|
||||
if (substr($num, 0, 2) === '02')
|
||||
{
|
||||
return substr($num, 0, 2) . '-' . substr($num, 2, 4) . '-' . substr($num, 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
return substr($num, 0, 3) . '-' . substr($num, 3, 3) . '-' . substr($num, 6);
|
||||
}
|
||||
default:
|
||||
if (substr($num, 0, 4) === '0303' || substr($num, 0, 3) === '050')
|
||||
{
|
||||
return substr($num, 0, 4) . '-' . substr($num, 4, 3) . '-' . substr($num, 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
return substr($num, 0, 3) . '-' . substr($num, 3, 4) . '-' . substr($num, 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Korean phone number contains a valid area code and the correct number of digits.
|
||||
*
|
||||
* @param string $num
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidPhoneNumber($num)
|
||||
{
|
||||
$num = str_replace('-', '', self::formatPhoneNumber($num));
|
||||
if (preg_match('/^1[0-9]{7}$/', $num))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (preg_match('/^02[2-9][0-9]{6,7}$/', $num))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (preg_match('/^0[13-8][0-9][2-9][0-9]{6,7}$/', $num))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Korean phone number is a mobile phone number.
|
||||
*
|
||||
* @param string $num
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidMobilePhoneNumber($num)
|
||||
{
|
||||
$num = str_replace('-', '', self::formatPhoneNumber($num));
|
||||
$len = strlen($num);
|
||||
return preg_match('/^01[016789][2-9][0-9]{6,7}$/', $num) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given string is a valid resident registration number (주민등록번호)
|
||||
* or foreigner registration number (외국인등록번호).
|
||||
*
|
||||
* This method only checks the format.
|
||||
* It does not check that the number is actually in use.
|
||||
*
|
||||
* @param string $code
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidJuminNumber($code)
|
||||
{
|
||||
// Return false if the format is obviously wrong.
|
||||
if (!preg_match('/^[0-9]{6}-?[0-9]{7}$/', $code))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove hyphen.
|
||||
$code = str_replace('-', '', $code);
|
||||
|
||||
// Return false if the date of birth is in the future.
|
||||
if (in_array((int)($code[6]), array(3, 4, 7, 8)) && intval(substr($code, 0, 6), 10) > date('ymd'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculate the checksum.
|
||||
$sum = 0;
|
||||
for ($i = 0; $i < 12; $i++)
|
||||
{
|
||||
$sum += $code[$i] * (($i % 8) + 2);
|
||||
}
|
||||
$checksum = (11 - ($sum % 11)) % 10;
|
||||
if (in_array((int)($code[6]), array(1, 2, 3, 4, 9, 0)))
|
||||
{
|
||||
return $checksum === (int)($code[12]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (substr($code, 7, 2) % 2 !== 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (($checksum + 2) % 10) === (int)($code[12]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given string is a valid corporation registration number (법인등록번호).
|
||||
*
|
||||
* This method only checks the format.
|
||||
* It does not check that the number is actually in use.
|
||||
*
|
||||
* @param string $code
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidCorporationNumber($code)
|
||||
{
|
||||
// Return false if the format is obviously wrong.
|
||||
if (!preg_match('/^[0-9]{6}-?[0-9]{7}$/', $code))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove hyphen.
|
||||
$code = str_replace('-', '', $code);
|
||||
|
||||
// Calculate the checksum.
|
||||
$sum = 0;
|
||||
for ($i = 0; $i < 12; $i++)
|
||||
{
|
||||
$sum += $code[$i] * (($i % 2) + 1);
|
||||
}
|
||||
$checksum = (10 - ($sum % 10)) % 10;
|
||||
|
||||
// Check the 7th and 13th digits.
|
||||
if ($code[6] !== '0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return $checksum === (int)($code[12]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given string is a valid business registration number (사업자등록번호).
|
||||
*
|
||||
* This method only checks the format.
|
||||
* It does not check that the number is actually in use.
|
||||
*
|
||||
* @param string $code
|
||||
* @return bool
|
||||
*/
|
||||
public static function isValidBusinessNumber($code)
|
||||
{
|
||||
// Return false if the format is obviously wrong.
|
||||
if (!preg_match('/^[0-9]{3}-?[0-9]{2}-?[0-9]{5}$/', $code))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove hyphen.
|
||||
$code = str_replace('-', '', $code);
|
||||
|
||||
// Calculate the checksum.
|
||||
$sum = 0;
|
||||
$sum += $code[0] + ($code[1] * 3) + ($code[2] * 7);
|
||||
$sum += $code[3] + ($code[4] * 3) + ($code[5] * 7);
|
||||
$sum += $code[6] + ($code[7] * 3) + ($code[8] * 5);
|
||||
$sum += floor(($code[8] * 5) / 10);
|
||||
$checksum = (10 - ($sum % 10)) % 10;
|
||||
|
||||
// Check the last digit.
|
||||
return $checksum === (int)($code[9]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given IP address is Korean.
|
||||
*
|
||||
* This method may return incorrect results if the IP allocation databases
|
||||
* (korea.ipv4.php, korea.ipv6.php) are out of date.
|
||||
*
|
||||
* @param string $ip
|
||||
* @return bool
|
||||
*/
|
||||
public static function isKoreanIP($ip)
|
||||
{
|
||||
// Extract the IPv4 address from an "IPv4-mapped IPv6" address.
|
||||
if (preg_match('/::ffff:(?:0+:)?([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$/', $ip, $matches)) $ip = $matches[1];
|
||||
|
||||
// Return false if the IP address is not in the right format.
|
||||
if (!filter_var($ip, \FILTER_VALIDATE_IP)) return false;
|
||||
|
||||
// Check IPv4.
|
||||
if (filter_var($ip, \FILTER_VALIDATE_IP, ['flags' => \FILTER_FLAG_IPV4]))
|
||||
{
|
||||
// Convert to integer.
|
||||
$ipnum = sprintf('%u', ip2long($ip));
|
||||
|
||||
// Treat local addresses as Korean.
|
||||
if ($ipnum >= 167772160 && $ipnum <= 184549375) return true; // 10.0.0.0/8
|
||||
if ($ipnum >= 2130706432 && $ipnum <= 2147483647) return true; // 127.0.0.0/8
|
||||
if ($ipnum >= 3232235520 && $ipnum <= 3232301055) return true; // 192.168.0.0/16
|
||||
if ($ipnum >= 2886729728 && $ipnum <= 2887778303) return true; // 172.16.0.0/20
|
||||
|
||||
// Check the IPv4 allocation database.
|
||||
$ranges = (include \RX_BASEDIR . 'common/defaults/korea.ipv4.php');
|
||||
foreach ($ranges as $range)
|
||||
{
|
||||
if ($ipnum >= $range[0] && $ipnum <= $range[1]) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check IPv6.
|
||||
elseif (function_exists('inet_pton'))
|
||||
{
|
||||
// Convert to hexadecimal format.
|
||||
$ipbin = strtolower(bin2hex(inet_pton($ip)));
|
||||
|
||||
// Treat local addresses as Korean.
|
||||
if ($ipbin == '00000000000000000000000000000001') return true; // ::1
|
||||
if (preg_match('/^f(?:[cd]|e80{13})/', $ipbin)) return true; // fc00::/8, fd00::/8, fe80::/64
|
||||
|
||||
// Check the IPv6 allocation database.
|
||||
$ranges = (include \RX_BASEDIR . 'common/defaults/korea.ipv6.php');
|
||||
foreach ($ranges as $range)
|
||||
{
|
||||
if (strncmp($ipbin, $range[0], 16) >= 0 && strncmp($ipbin, $range[1], 16) <= 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given email address is hosted by a Korean portal site.
|
||||
*
|
||||
* This can be used to tell which recipients may subscribe to the KISA RBL (kisarbl.or.kr).
|
||||
* If the domain is not found, this method returns false.
|
||||
*
|
||||
* @param string $domain
|
||||
* @param bool $clear_cache (optional)
|
||||
* @return bool
|
||||
*/
|
||||
public static function isKoreanEmailAddress($email_address, $clear_cache = false)
|
||||
{
|
||||
// Clear the cache if requested.
|
||||
if ($clear_cache)
|
||||
{
|
||||
self::$_domain_cache = array();
|
||||
}
|
||||
|
||||
// Get the domain from the email address.
|
||||
if ($pos = strpos($email_address, '@'))
|
||||
{
|
||||
$domain = substr($email_address, $pos + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$domain = $email_address;
|
||||
}
|
||||
$domain = rtrim(strtolower($domain), '.');
|
||||
|
||||
// Return cached result if available.
|
||||
if (array_key_exists($domain, self::$_domain_cache))
|
||||
{
|
||||
return self::$_domain_cache[$domain];
|
||||
}
|
||||
|
||||
// Shortcut for known domains.
|
||||
if (in_array($domain, self::$known_korean))
|
||||
{
|
||||
return self::$_domain_cache[$domain] = true;
|
||||
}
|
||||
if (in_array($domain, self::$known_foreign))
|
||||
{
|
||||
return self::$_domain_cache[$domain] = false;
|
||||
}
|
||||
|
||||
// For unknown domains, check the MX record.
|
||||
$mx = self::_getDNSRecords($domain, \DNS_MX);
|
||||
|
||||
$i = 0;
|
||||
foreach ($mx as $mx)
|
||||
{
|
||||
$mx = rtrim($mx, '.');
|
||||
foreach (self::$known_korean as $portal)
|
||||
{
|
||||
if ($mx === $portal || ends_with('.' . $portal, $mx))
|
||||
{
|
||||
return self::$_domain_cache[$domain] = true;
|
||||
}
|
||||
}
|
||||
foreach (self::$known_foreign as $portal)
|
||||
{
|
||||
if ($mx === $portal || ends_with('.' . $portal, $mx))
|
||||
{
|
||||
return self::$_domain_cache[$domain] = false;
|
||||
}
|
||||
}
|
||||
foreach (self::_getDNSRecords($domain, \DNS_A) as $mx_ip)
|
||||
{
|
||||
return self::$_domain_cache[$domain] = self::isKoreanIP($mx_ip);
|
||||
}
|
||||
if (++$i > 2)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return self::$_domain_cache[$domain] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the DNS records of a domain.
|
||||
*
|
||||
* @param string $domain
|
||||
* @param int $type
|
||||
* @return array
|
||||
*/
|
||||
protected static function _getDNSRecords($domain, $type)
|
||||
{
|
||||
$records = dns_get_record($domain, $type);
|
||||
if (!$records)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach ($records as $record)
|
||||
{
|
||||
if (isset($record['pri']) && isset($record['target']))
|
||||
{
|
||||
$result[intval($record['pri'])] = $record['target'];
|
||||
}
|
||||
elseif (isset($record['target']))
|
||||
{
|
||||
$result[] = $record['target'];
|
||||
}
|
||||
elseif (isset($record['ip']) || isset($record['ipv6']))
|
||||
{
|
||||
$result[] = isset($record['ip']) ? $record['ip'] : $record['ipv6'];
|
||||
}
|
||||
elseif (isset($record['txt']))
|
||||
{
|
||||
$result[] = $record['txt'];
|
||||
}
|
||||
}
|
||||
|
||||
ksort($result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent multiple lookups for the same domain.
|
||||
*/
|
||||
protected static $_domain_cache = array();
|
||||
|
||||
/**
|
||||
* Domains known to be Korean and subscribed to the KISA RBL.
|
||||
*/
|
||||
public static $known_korean = array(
|
||||
'hanmail.net',
|
||||
'hanmail2.net',
|
||||
'daum.net',
|
||||
'paran.com',
|
||||
'tistory.com',
|
||||
'naver.com',
|
||||
'navercorp.com',
|
||||
'nate.com',
|
||||
'cyworld.com',
|
||||
'dreamwiz.com',
|
||||
'korea.com',
|
||||
'dreamx.com',
|
||||
'chol.com',
|
||||
'chollian.net',
|
||||
'hanmir.com',
|
||||
'hitel.com',
|
||||
'freechal.com',
|
||||
'empas.com',
|
||||
'empal.com',
|
||||
'hanafos.com',
|
||||
);
|
||||
|
||||
/**
|
||||
* Domains known to be foreign.
|
||||
*/
|
||||
public static $known_foreign = array(
|
||||
'gmail.com',
|
||||
'googlemail.com',
|
||||
'google.com',
|
||||
'yahoo.com',
|
||||
'yahoo.co.kr',
|
||||
'hotmail.com',
|
||||
'hotmail.co.kr',
|
||||
'live.com',
|
||||
'outlook.com',
|
||||
'msn.com',
|
||||
'me.com',
|
||||
'mac.com',
|
||||
'icloud.com',
|
||||
'facebook.com',
|
||||
'aol.com',
|
||||
'gmx.com',
|
||||
'mail.com',
|
||||
'fastmail.com',
|
||||
'fastmail.fm',
|
||||
'runbox.com',
|
||||
'inbox.com',
|
||||
'lycos.com',
|
||||
'zoho.com',
|
||||
);
|
||||
}
|
||||
107
tests/unit/framework/KoreaTest.php
Normal file
107
tests/unit/framework/KoreaTest.php
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
class KoreaTest extends \Codeception\TestCase\Test
|
||||
{
|
||||
public function testFormatPhoneNumber()
|
||||
{
|
||||
$this->assertEquals('1588-0000', Rhymix\Framework\Korea::formatPhoneNumber('1588-0000'));
|
||||
$this->assertEquals('02-345-6789', Rhymix\Framework\Korea::formatPhoneNumber('+82 23456789'));
|
||||
$this->assertEquals('02-3000-5000', Rhymix\Framework\Korea::formatPhoneNumber('0230005000'));
|
||||
$this->assertEquals('031-222-3333', Rhymix\Framework\Korea::formatPhoneNumber('82-0312-2233-33'));
|
||||
$this->assertEquals('031-2222-3333', Rhymix\Framework\Korea::formatPhoneNumber('03122223333'));
|
||||
$this->assertEquals('011-444-5555', Rhymix\Framework\Korea::formatPhoneNumber('011 444 5555'));
|
||||
$this->assertEquals('010-6666-7777', Rhymix\Framework\Korea::formatPhoneNumber('82+1066667777'));
|
||||
$this->assertEquals('0303-456-7890', Rhymix\Framework\Korea::formatPhoneNumber('03034567890'));
|
||||
$this->assertEquals('0505-987-6543', Rhymix\Framework\Korea::formatPhoneNumber('050-5987-6543'));
|
||||
$this->assertEquals('070-7432-1000', Rhymix\Framework\Korea::formatPhoneNumber('0707-432-1000'));
|
||||
}
|
||||
|
||||
public function testIsValidPhoneNumber()
|
||||
{
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('1588-0000'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('02-345-6789'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('+82-2-345-6789'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('+82-02-2345-6789'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('053-444-5555'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('053-4444-5555'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('011-444-5555'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidPhoneNumber('010-4444-5555'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('010-4444-55555'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('010-1234-5678'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('02-123-4567'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('02-123456'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('03-456-7890'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidPhoneNumber('090-9876-5432'));
|
||||
}
|
||||
|
||||
public function testIsValidMobilePhoneNumber()
|
||||
{
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidMobilePhoneNumber('011-345-6789'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidMobilePhoneNumber('010-2345-6789'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidMobilePhoneNumber('+82-11-345-6789'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidMobilePhoneNumber('82 010-2345-6789'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidMobilePhoneNumber('010-1111-1111'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidMobilePhoneNumber('02-345-6789'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidMobilePhoneNumber('063-9876-5432'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidMobilePhoneNumber('070-7654-3210'));
|
||||
}
|
||||
|
||||
public function testIsValidJuminNumber()
|
||||
{
|
||||
// These numbers are fake.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidJuminNumber('123456-3456787'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidJuminNumber('123456-3456788'));
|
||||
}
|
||||
|
||||
public function testIsValidCorporationNumber()
|
||||
{
|
||||
// These numbers are fake.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidCorporationNumber('123456-0123453'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidCorporationNumber('123456-0123454'));
|
||||
}
|
||||
|
||||
public function testIsValidBusinessNumber()
|
||||
{
|
||||
// These numbers are fake.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isValidBusinessNumber('123-45-67891'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isValidBusinessNumber('123-45-67892'));
|
||||
}
|
||||
|
||||
public function testIsKoreanIP()
|
||||
{
|
||||
// Private IP ranges.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('10.12.34.210'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('127.0.123.45'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('192.168.10.1'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('::1'));
|
||||
|
||||
// Korean IP ranges.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('115.71.233.0'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('114.207.12.3'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('2001:0320::1'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanIP('2407:B800::F'));
|
||||
|
||||
// Foreign IP ranges.
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanIP('216.58.197.0'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanIP('170.14.168.0'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanIP('2001:41d0:8:e8ad::1'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanIP('2404:6800:4005:802::200e'));
|
||||
}
|
||||
|
||||
public function testIsKoreanEmailAddress()
|
||||
{
|
||||
// Test Korean portals.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanEmailAddress('test@naver.com'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanEmailAddress('test@hanmail.net'));
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanEmailAddress('test@worksmobile.com'));
|
||||
|
||||
// Test foreign portals.
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanEmailAddress('test@gmail.com'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanEmailAddress('test@hotmail.com'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanEmailAddress('test@yahoo.com'));
|
||||
|
||||
// Test third-party MX services.
|
||||
$this->assertTrue(Rhymix\Framework\Korea::isKoreanEmailAddress('test@woorimail.com'));
|
||||
$this->assertFalse(Rhymix\Framework\Korea::isKoreanEmailAddress('test@rhymix.org'));
|
||||
}
|
||||
}
|
||||
89
tools/korea_ip_ranges/korea.ipv4.parser.php
Normal file
89
tools/korea_ip_ranges/korea.ipv4.parser.php
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Do not allow execution over the web.
|
||||
*/
|
||||
if (PHP_SAPI !== 'cli')
|
||||
{
|
||||
exit 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the latest IPv4 data from libkrisp.
|
||||
*/
|
||||
$download_url = 'https://mirror.oops.org/pub/oops/libkrisp/data/v2/krisp.csv.gz';
|
||||
$referer_url = 'https://mirror.oops.org/pub/oops/libkrisp/data/v2/';
|
||||
$content = file_get_contents($download_url, false, stream_context_create(array(
|
||||
'http' => array(
|
||||
'user_agent' => 'Mozilla/5.0 (compatible; IP range generator)',
|
||||
'header' => 'Referer: ' . $referer_url . "\r\n",
|
||||
),
|
||||
)));
|
||||
$content = gzdecode($content);
|
||||
if (!$content)
|
||||
{
|
||||
exit 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load IP range data.
|
||||
*/
|
||||
$ranges = array();
|
||||
$content = explode("\n", $content);
|
||||
foreach ($content as $line)
|
||||
{
|
||||
$line = explode("\t", $line);
|
||||
if (count($line) < 2) continue;
|
||||
$start = trim($line[0]);
|
||||
$end = trim($line[1]);
|
||||
$ranges[$start] = array($start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the ranges.
|
||||
*/
|
||||
ksort($ranges);
|
||||
$ranges = array_values($ranges);
|
||||
$count = count($ranges);
|
||||
|
||||
/**
|
||||
* Merge adjacent ranges.
|
||||
*/
|
||||
for ($i = 0; $i < $count; $i++)
|
||||
{
|
||||
if ($i == 0) continue;
|
||||
$previous_i = $i - 1;
|
||||
while (true)
|
||||
{
|
||||
if ($ranges[$previous_i] !== null) break;
|
||||
$previous_i--;
|
||||
}
|
||||
|
||||
if ($ranges[$i][0] == $ranges[$previous_i][1] + 1)
|
||||
{
|
||||
$ranges[$previous_i][1] = $ranges[$i][1];
|
||||
$ranges[$i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Organize into final format.
|
||||
*/
|
||||
$ranges_final = array();
|
||||
foreach ($ranges as $range)
|
||||
{
|
||||
if ($range !== null) $ranges_final[] = $range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save to file.
|
||||
*/
|
||||
$content = '<' . '?php' . "\n\n" . '/**' . "\n" . ' * Source: ' . $referer_url . "\n";
|
||||
$content .= ' * Last Updated: ' . date('Y-m-d') . "\n" . ' */' . "\n";
|
||||
$content .= 'return ' . var_export($ranges_final, true) . ';' . "\n";
|
||||
file_put_contents('korea.ipv4.php', $content);
|
||||
|
||||
/**
|
||||
* Report status.
|
||||
*/
|
||||
echo count($ranges_final) . ' IPv4 ranges saved.' . PHP_EOL;
|
||||
92
tools/korea_ip_ranges/korea.ipv6.parser.php
Normal file
92
tools/korea_ip_ranges/korea.ipv6.parser.php
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Do not allow execution over the web.
|
||||
*/
|
||||
if (PHP_SAPI !== 'cli')
|
||||
{
|
||||
exit 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the latest IPv6 data from KISA.
|
||||
*/
|
||||
$download_url = 'https://ip.kisa.or.kr/ip_cate_stat/stat_05_05_toexcel.act';
|
||||
$referer_url = 'https://ip.kisa.or.kr/ip_cate_stat/stat_05_05.act';
|
||||
$content = file_get_contents($download_url, false, stream_context_create(array(
|
||||
'http' => array(
|
||||
'user_agent' => 'Mozilla/5.0 (compatible; IP range generator)',
|
||||
'header' => 'Referer: ' . $referer_url . "\r\n",
|
||||
),
|
||||
)));
|
||||
if (!$content)
|
||||
{
|
||||
exit 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the HTML/Excel document.
|
||||
*/
|
||||
$regex = '#<tr>\\s*<td [^>]+>([0-9a-f:]+::)</td>\\s*<td [^>]+>(/[0-9]+)</td>#iU';
|
||||
preg_match_all($regex, $content, $matches, PREG_SET_ORDER);
|
||||
|
||||
/**
|
||||
* Extract the address and netmask for each range.
|
||||
*/
|
||||
$ranges = array();
|
||||
foreach ($matches as $match)
|
||||
{
|
||||
$start = str_pad(str_replace(':', '', strtolower($match[1])), 16, '0', STR_PAD_RIGHT);
|
||||
$mask = str_repeat('f', ((64 - trim($match[2], '/')) / 4));
|
||||
$end = substr($start, 0, 16 - strlen($mask)) . $mask;
|
||||
$ranges[$start] = array($start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the ranges.
|
||||
*/
|
||||
ksort($ranges);
|
||||
$ranges = array_values($ranges);
|
||||
$count = count($ranges);
|
||||
|
||||
/**
|
||||
* Merge adjacent ranges.
|
||||
*/
|
||||
for ($i = 0; $i < $count; $i++)
|
||||
{
|
||||
if ($i == 0) continue;
|
||||
$previous_i = $i - 1;
|
||||
while (true)
|
||||
{
|
||||
if ($ranges[$previous_i] !== null) break;
|
||||
$previous_i--;
|
||||
}
|
||||
|
||||
if (hexdec($ranges[$i][0]) == hexdec($ranges[$previous_i][1]) + 1)
|
||||
{
|
||||
$ranges[$previous_i][1] = $ranges[$i][1];
|
||||
$ranges[$i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Organize into final format.
|
||||
*/
|
||||
$ranges_final = array();
|
||||
foreach ($ranges as $range)
|
||||
{
|
||||
if ($range !== null) $ranges_final[] = $range;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save to file.
|
||||
*/
|
||||
$content = '<' . '?php' . "\n\n" . '/**' . "\n" . ' * Source: ' . $referer_url . "\n";
|
||||
$content .= ' * Last Updated: ' . date('Y-m-d') . "\n" . ' */' . "\n";
|
||||
$content .= 'return ' . var_export($ranges_final, true) . ';' . "\n";
|
||||
file_put_contents('korea.ipv6.php', $content);
|
||||
|
||||
/**
|
||||
* Report status.
|
||||
*/
|
||||
echo count($ranges_final) . ' IPv6 ranges saved.' . PHP_EOL;
|
||||
Loading…
Add table
Add a link
Reference in a new issue