using System;
|
using System.Collections.Generic;
|
using System.Text;
|
using System.IO;
|
using System.Text.RegularExpressions;
|
|
|
namespace Pcb.Common.IPV2
|
{
|
public class IPLocationV2
|
{
|
public string IP { get; set; }
|
public string Country { get; set; }
|
public string Local { get; set; }
|
}
|
public class QQWryLocatorV2
|
{
|
private byte[] data;
|
Regex regex = new Regex(@"(((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))");
|
long firstStartIpOffset;
|
long lastStartIpOffset;
|
long ipCount;
|
public long Count { get { return ipCount; } }
|
|
|
/// <summary>
|
/// 取IP物理地址
|
/// </summary>
|
/// <param name="strIP"></param>
|
/// <returns></returns>
|
public string GetCurrentIpAddress()
|
{
|
try
|
{
|
string strIP = GetHttpContextIp();
|
if (strIP == "::1")
|
{
|
strIP = "127.0.0.1";
|
}
|
|
string ipDataFile = AppDomain.CurrentDomain.BaseDirectory + "\\Content\\qqwry.dat";
|
QQWryLocatorV2 qqWry = new QQWryLocatorV2(ipDataFile);//初始化数据库文件,并获得IP记录数,通过Count可以获得
|
|
IPLocationV2 ip = qqWry.Query(strIP); //查询一个IP地址
|
return ip.Country + " " + ip.Local;
|
}
|
catch (Exception ex)
|
{
|
// LogHelper.WriteLog("计算IP报错GetCurrentIpAddress()" + ex.ToString());
|
}
|
return string.Empty;
|
}
|
|
public string GetHttpContextIp()
|
{
|
if (System.Web.HttpContext.Current != null)
|
{
|
if (System.Web.HttpContext.Current.Request.Headers["X-Real-IP"] != null)
|
return System.Web.HttpContext.Current.Request.Headers["X-Real-IP"];
|
if (System.Web.HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
|
return System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].Split(new char[] { ',' })[0];
|
else
|
return System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
|
}
|
else
|
{
|
return string.Empty;
|
}
|
}
|
|
public QQWryLocatorV2()
|
{
|
string dataPath = AppDomain.CurrentDomain.BaseDirectory + "\\Content\\qqwry.dat";
|
using (FileStream fs = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
{
|
data = new byte[fs.Length];
|
fs.Read(data, 0, data.Length);
|
}
|
byte[] buffer = new byte[8];
|
Array.Copy(data, 0, buffer, 0, 8);
|
firstStartIpOffset = ((buffer[0] + (buffer[1] * 0x100)) + ((buffer[2] * 0x100) * 0x100)) + (((buffer[3] * 0x100) * 0x100) * 0x100);
|
lastStartIpOffset = ((buffer[4] + (buffer[5] * 0x100)) + ((buffer[6] * 0x100) * 0x100)) + (((buffer[7] * 0x100) * 0x100) * 0x100);
|
ipCount = Convert.ToInt64((double)(((double)(lastStartIpOffset - firstStartIpOffset)) / 7.0));
|
|
if (ipCount <= 1L)
|
{
|
throw new ArgumentException("ip FileDataError");
|
}
|
|
}
|
public QQWryLocatorV2(string dataPath)
|
{
|
using (FileStream fs = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
{
|
data = new byte[fs.Length];
|
fs.Read(data, 0, data.Length);
|
}
|
byte[] buffer = new byte[8];
|
Array.Copy(data, 0, buffer, 0, 8);
|
firstStartIpOffset = ((buffer[0] + (buffer[1] * 0x100)) + ((buffer[2] * 0x100) * 0x100)) + (((buffer[3] * 0x100) * 0x100) * 0x100);
|
lastStartIpOffset = ((buffer[4] + (buffer[5] * 0x100)) + ((buffer[6] * 0x100) * 0x100)) + (((buffer[7] * 0x100) * 0x100) * 0x100);
|
ipCount = Convert.ToInt64((double)(((double)(lastStartIpOffset - firstStartIpOffset)) / 7.0));
|
|
if (ipCount <= 1L)
|
{
|
throw new ArgumentException("ip FileDataError");
|
}
|
}
|
private static long IpToInt(string ip)
|
{
|
char[] separator = new char[] { '.' };
|
if (ip.Split(separator).Length == 3)
|
{
|
ip = ip + ".0";
|
}
|
string[] strArray = ip.Split(separator);
|
long num2 = ((long.Parse(strArray[0]) * 0x100L) * 0x100L) * 0x100L;
|
long num3 = (long.Parse(strArray[1]) * 0x100L) * 0x100L;
|
long num4 = long.Parse(strArray[2]) * 0x100L;
|
long num5 = long.Parse(strArray[3]);
|
return (((num2 + num3) + num4) + num5);
|
}
|
private static string IntToIP(long ip_Int)
|
{
|
long num = (long)((ip_Int & 0xff000000L) >> 0x18);
|
if (num < 0L)
|
{
|
num += 0x100L;
|
}
|
long num2 = (ip_Int & 0xff0000L) >> 0x10;
|
if (num2 < 0L)
|
{
|
num2 += 0x100L;
|
}
|
long num3 = (ip_Int & 0xff00L) >> 8;
|
if (num3 < 0L)
|
{
|
num3 += 0x100L;
|
}
|
long num4 = ip_Int & 0xffL;
|
if (num4 < 0L)
|
{
|
num4 += 0x100L;
|
}
|
return (num.ToString() + "." + num2.ToString() + "." + num3.ToString() + "." + num4.ToString());
|
}
|
public IPLocationV2 Query(string ip)
|
{
|
IPLocationV2 ipLocation = new IPLocationV2() { IP = ip };
|
try
|
{
|
if (!regex.Match(ip).Success)
|
{
|
throw new ArgumentException("IP格式错误");
|
}
|
|
long intIP = IpToInt(ip);
|
if ((intIP >= IpToInt("127.0.0.1") && (intIP <= IpToInt("127.255.255.255"))))
|
{
|
ipLocation.Country = "本机内部环回地址";
|
ipLocation.Local = "";
|
}
|
else
|
{
|
if ((((intIP >= IpToInt("0.0.0.0")) && (intIP <= IpToInt("2.255.255.255"))) || ((intIP >= IpToInt("64.0.0.0")) && (intIP <= IpToInt("126.255.255.255")))) ||
|
((intIP >= IpToInt("58.0.0.0")) && (intIP <= IpToInt("60.255.255.255"))))
|
{
|
ipLocation.Country = "网络保留地址";
|
ipLocation.Local = "";
|
}
|
}
|
long right = ipCount;
|
long left = 0L;
|
long middle = 0L;
|
long startIp = 0L;
|
long endIpOff = 0L;
|
long endIp = 0L;
|
int countryFlag = 0;
|
while (left < (right - 1L))
|
{
|
middle = (right + left) / 2L;
|
startIp = GetStartIp(middle, out endIpOff);
|
if (intIP == startIp)
|
{
|
left = middle;
|
break;
|
}
|
if (intIP > startIp)
|
{
|
left = middle;
|
}
|
else
|
{
|
right = middle;
|
}
|
}
|
startIp = GetStartIp(left, out endIpOff);
|
endIp = GetEndIp(endIpOff, out countryFlag);
|
if ((startIp <= intIP) && (endIp >= intIP))
|
{
|
string local;
|
ipLocation.Country = GetCountry(endIpOff, countryFlag, out local);
|
ipLocation.Local = local;
|
}
|
else
|
{
|
ipLocation.Country = "未知";
|
ipLocation.Local = "";
|
}
|
}
|
catch (Exception ex)
|
{
|
}
|
return ipLocation;
|
|
}
|
private long GetStartIp(long left, out long endIpOff)
|
{
|
long leftOffset = firstStartIpOffset + (left * 7L);
|
byte[] buffer = new byte[7];
|
Array.Copy(data, leftOffset, buffer, 0, 7);
|
endIpOff = (Convert.ToInt64(buffer[4].ToString()) + (Convert.ToInt64(buffer[5].ToString()) * 0x100L)) + ((Convert.ToInt64(buffer[6].ToString()) * 0x100L) * 0x100L);
|
return ((Convert.ToInt64(buffer[0].ToString()) + (Convert.ToInt64(buffer[1].ToString()) * 0x100L)) + ((Convert.ToInt64(buffer[2].ToString()) * 0x100L) * 0x100L)) + (((Convert.ToInt64(buffer[3].ToString()) * 0x100L) * 0x100L) * 0x100L);
|
}
|
private long GetEndIp(long endIpOff, out int countryFlag)
|
{
|
byte[] buffer = new byte[5];
|
Array.Copy(data, endIpOff, buffer, 0, 5);
|
countryFlag = buffer[4];
|
return ((Convert.ToInt64(buffer[0].ToString()) + (Convert.ToInt64(buffer[1].ToString()) * 0x100L)) + ((Convert.ToInt64(buffer[2].ToString()) * 0x100L) * 0x100L)) + (((Convert.ToInt64(buffer[3].ToString()) * 0x100L) * 0x100L) * 0x100L);
|
}
|
/// <summary>
|
/// Gets the country.
|
/// </summary>
|
/// <param name="endIpOff">The end ip off.</param>
|
/// <param name="countryFlag">The country flag.</param>
|
/// <param name="local">The local.</param>
|
/// <returns>country</returns>
|
private string GetCountry(long endIpOff, int countryFlag, out string local)
|
{
|
string country = "";
|
long offset = endIpOff + 4L;
|
switch (countryFlag)
|
{
|
case 1:
|
case 2:
|
country = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
|
offset = endIpOff + 8L;
|
local = (1 == countryFlag) ? "" : GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
|
break;
|
default:
|
country = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
|
local = GetFlagStr(ref offset, ref countryFlag, ref endIpOff);
|
break;
|
}
|
return country;
|
}
|
private string GetFlagStr(ref long offset, ref int countryFlag, ref long endIpOff)
|
{
|
int flag = 0;
|
byte[] buffer = new byte[3];
|
|
while (true)
|
{
|
//用于向前累加偏移量
|
long forwardOffset = offset;
|
flag = data[forwardOffset++];
|
//没有重定向
|
if (flag != 1 && flag != 2)
|
{
|
break;
|
}
|
Array.Copy(data, forwardOffset, buffer, 0, 3);
|
forwardOffset += 3;
|
if (flag == 2)
|
{
|
countryFlag = 2;
|
endIpOff = offset - 4L;
|
}
|
offset = (Convert.ToInt64(buffer[0].ToString()) + (Convert.ToInt64(buffer[1].ToString()) * 0x100L)) + ((Convert.ToInt64(buffer[2].ToString()) * 0x100L) * 0x100L);
|
}
|
if (offset < 12L)
|
{
|
return "";
|
}
|
return GetStr(ref offset);
|
}
|
private string GetStr(ref long offset)
|
{
|
byte lowByte = 0;
|
byte highByte = 0;
|
StringBuilder stringBuilder = new StringBuilder();
|
byte[] bytes = new byte[2];
|
Encoding encoding = Encoding.GetEncoding("GB2312");
|
while (true)
|
{
|
lowByte = data[offset++];
|
if (lowByte == 0)
|
{
|
return stringBuilder.ToString();
|
}
|
if (lowByte > 0x7f)
|
{
|
highByte = data[offset++];
|
bytes[0] = lowByte;
|
bytes[1] = highByte;
|
if (highByte == 0)
|
{
|
return stringBuilder.ToString();
|
}
|
stringBuilder.Append(encoding.GetString(bytes));
|
}
|
else
|
{
|
stringBuilder.Append((char)lowByte);
|
}
|
}
|
}
|
}
|
}
|