<?php
class getIp
{
    public function __construct()
    {
    }

    /**
     * 不通过代理直接获取IP数据
     */
    public function getSip($ip)
    {
        $ip = strip_tags($ip);
        if ( is_numeric( $ip ) ) {
            $_ip = $this -> API_LONG2IP($ip);
            if ( $this -> isPublicIp( $_ip ) ) {
                $url = 'http://whatismyipaddress.com/ip/' . $_ip;
                $result = $this -> curlGet($url);
                echo json_encode($result);exit;
            } else {
                exit("非法请求!!!");
            }
        }
    }

    /**
     * GET 方式获取IP数据
     */
    public function curlGet($url, $timeout = 10, $ssl=false)
    {
        $curl = curl_init();
        $refer = 'http://whatismyipaddress.com/ip-lookup';
        $header = array('Host: whatismyipaddress.com');
        curl_setopt($curl, CURLOPT_HEADER, 1);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
        curl_setopt($curl, CURLOPT_REFERER, $refer);
        curl_setopt($curl, CURLINFO_HEADER_OUT, false);
        curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36");
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_FORBID_REUSE, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
        curl_setopt($curl, CURLOPT_TIMEOUT, $timeout);
        $data = curl_exec($curl);
        $curlErrno = curl_errno($curl);
        $curlError = curl_error($curl);
        curl_close($curl);
        if ($curlErrno > 0) {
            $gShow['errcode'] = 1;
            $gShow['errmsg']  = sprintf('警告：CURL错误 %s(%s)！', $curlError, $curlErrno);
            $gShow['data']    = '';

            return $gShow;
        }
        $result = $this -> parse_data( $data );
        if ($result) {
            $gShow['data']    = $result;
            $gShow['errmsg']  = 'success';
            $gShow['errcode'] = 0;
        } else {
            $gShow['data']    = '';
            $gShow['errmsg']  = 'parse error!';
            $gShow['errcode'] = 2;
        }

        return $gShow;
    }

    /**
     * [parse_data 解析返回HTML文本]
     * @param  [type]  $data [description]
     * @param  integer $page [description]
     * @return [type]  [description]
     */
    protected function parse_data($data)
    {
        $regx_general_ip_info = '/<form[^>]+action=[\"\']{0,1}[^>\"\'\s]*blacklist-check[\'\"]{0,1}[^>]*>([\w\W]*?)<\/form>/i';
        $regx_geo_info = "/Geolocation Information<\/h2>\W*?<table>([\w\W]*?)<\/table>/i";
        $ipData = array();
        preg_match($regx_general_ip_info, $data, $info_matches);

        if ($info_matches) {
            $info = $info_matches[1];
            preg_match('/<tr><th>Decimal\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $match);
            $ipData['decimal']      = self::filterMatch($match);
            preg_match('/<tr><th>Hostname\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $match);
            $ipData['hostname']     = self::filterMatch($match);
            preg_match('/<tr><th>ASN\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $match);
            $ipData['ASN']          = self::filterMatch($match);
            preg_match('/<tr><th>ISP\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $match);
            $ipData['ISP']          = self::filterMatch($match);
            preg_match('/<tr><th>Organization\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $match);
            $ipData['organization'] = self::filterMatch($match);
            preg_match('/<tr><th>Services\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $match);
            $ipData['services']     = self::filterMatch($match);
            preg_match('/<tr><th>Type\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $match);
            $ipData['type']         = self::filterMatch($match);
            preg_match('/<tr><th>Assignment\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $match);
            $ipData['assignment']   = self::filterMatch($match);
        }

        if ( preg_match($regx_geo_info, $data, $geo_matches) ) {
            $info = $geo_matches[1];
            preg_match('/<tr><th>Continent\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $_match);
            $ipData['continent'] = self::filterMatch($_match);
            preg_match('/<tr><th>Country\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $_match);
            $ipData['country']   = self::filterMatch($_match);
            preg_match('/<tr><th>State\/Region\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $_match);
            $ipData['state']     = self::filterMatch($_match);
            preg_match('/<tr><th>City\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $_match);
            $ipData['city']      = self::filterMatch($_match);
            preg_match('/<tr><th>Latitude\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $_match);
            $ipData['lat']       = self::filterMatch($_match);
            preg_match('/<tr><th>Longitude\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $_match);
            $ipData['log']       = self::filterMatch($_match);
            preg_match('/<tr><th>Postal Code\:<\/th><td>([\W\w]*?)<\/td><\/tr>/i', $info, $_match);
            $ipData['postcode']  = self::filterMatch($_match);
        }

        return $ipData;
    }

    protected function filterMatch($tmp)
    {
        return isset( $tmp[1] )? trim ( html_entity_decode( strip_tags ( $tmp[1] ) ) ):'';
    }

    /**
     * 返回数据结果
     * @param  [type] $jsonData [数据]
     * @param  [type] $type     [JSON/JSONP/HTML]
     * @return [type] [返回格式化数据]
     */
    public function returnJson($data, $type='', $json_option=0)
    {
        if(empty($type)) $type  =   'JSON'; //默认返回JSON数据
        switch (strtoupper($type)) {
            case 'JSON' :
                // 返回JSON数据格式到客户端 包含状态信息
                header('Content-Type:application/json; charset=utf-8');
                exit(json_encode($data, $json_option));
            case 'XML'  :
                // 返回xml格式数据
                header('Content-Type:text/xml; charset=utf-8');
                exit(xml_encode($data));
            case 'JSONP':
                // 返回JSON数据格式到客户端 包含状态信息
                header('Content-Type:application/json; charset=utf-8');
                $handler  =   isset($_GET['callback']) ? $_GET['callback'] : 'callback';
                exit($handler.'('.json_encode($data,$json_option).');');
            case 'EVAL' :
                // 返回可执行的js脚本
                header('Content-Type:text/html; charset=utf-8');
                exit($data);
        }
    }

    /**
     * [isPublicIp 判断是否是合法的公共IPv4地址，192.168.1.1这类的私有IP地址将会排除在外]
     * @return boolean [description]
     */
    public function isPublicIp($ip)
    {
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE)) {
            return true;
        }

        return false;
    }

    public function API_IP2LONG($a)
    {
        $d = 0.0;
        $b = explode(".", $a,4);
        for ($i = 0; $i < 4; $i++) {
            $d *= 256.0;
            $d += $b[$i];
        };

        return $d;
    }

    public function API_LONG2IP($a)
    {
        $b=array(0,0,0,0);
        $c = 16777216.0;
        $a += 0.0;
        for ($i = 0; $i < 4; $i++) {
            $k = (int) ($a / $c);
            $a -= $c * $k;
            $b[$i]= $k;
            $c /=256.0;
        };
        $d=join('.', $b);

        return($d);
    }
}
