// Spludlow Software // Copyright © Samuel P. Ludlow 2020 All Rights Reserved // Distributed under the terms of the GNU General Public License version 3 // Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE // https://www.spludlow.co.uk/LICENCE.TXT // The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission // v1.14 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.IO; namespace Spludlow.Net { public class IPWhoIsRange { public Dictionary IpRanges = new Dictionary(); // start, end IP private string StoreDirectory = Spludlow.Config.ProgramData + @"\Data\IPWhoIsRange"; public IPWhoIsRange() { if (Directory.Exists(this.StoreDirectory) == false) Directory.CreateDirectory(this.StoreDirectory); foreach (string filename in Directory.GetFiles(this.StoreDirectory, "*.txt")) { uint[] range = ParseRangeFilename(filename); this.IpRanges.Add(range[0], range[1]); } } public static uint[] ParseRangeFilename(string filename) { filename = Path.GetFileNameWithoutExtension(filename); string[] parts = filename.Split(new char[] { '-' }); if (parts.Length != 2) throw new ApplicationException("IPWhoIsRange, ParseRangeFilename; did not split into 2 parts: " + filename); return new uint[] { Spludlow.Net.IP.IPAddressToInt(parts[0].Trim()), Spludlow.Net.IP.IPAddressToInt(parts[1].Trim()) }; } public string WhoIsQuery(string ipv4Address) { uint ip = Spludlow.Net.IP.IPAddressToInt(ipv4Address); uint[] starts; lock (this.IpRanges) { starts = this.IpRanges.Keys.ToArray(); } foreach (uint start in starts) { uint end = this.IpRanges[start]; if (ip >= start && ip <= end) { string existingFilename = this.StoreDirectory + @"\" + Spludlow.Net.IP.IntToIPAddress(start) + "-" + Spludlow.Net.IP.IntToIPAddress(end) + ".txt"; if (File.Exists(existingFilename) == false) throw new ApplicationException("IPWhoIsRange, ParseRangeFilename; did not find file: " + existingFilename); return File.ReadAllText(existingFilename); } } string whoIsText = Spludlow.Net.IpWhoIs.WhoIs(ipv4Address); string[] range = SplitINetNum(whoIsText); string filename = this.StoreDirectory + @"\" + range[0] + "-" + range[1] + ".txt"; uint rangeStart = Spludlow.Net.IP.IPAddressToInt(range[0]); lock (this.IpRanges) { if (this.IpRanges.ContainsKey(rangeStart) == false) // Not added elsewhere { File.WriteAllText(filename, whoIsText); this.IpRanges.Add(rangeStart, Spludlow.Net.IP.IPAddressToInt(range[1])); } } return whoIsText; } public string CountryCode(string ipv4Address) { string whoIsText = WhoIsQuery(ipv4Address); Dictionary> whoIs = Spludlow.Net.IpWhoIs.Parse(whoIsText); string code = ""; if (whoIs.ContainsKey("country") == true && whoIs["country"].Count > 0) { code = whoIs["country"][whoIs["country"].Count - 1]; code = code.ToUpper(); if (code.StartsWith("EU") == true) code = "EU"; } return code; } public static string[] SplitINetNum(string whoIsText) { Dictionary> whois = Spludlow.Net.IpWhoIs.Parse(whoIsText); if (whois.ContainsKey("inetnum") == false || whois["inetnum"].Count == 0) throw new ApplicationException("Did not find inetnum in whois"); string range = whois["inetnum"][whois["inetnum"].Count - 1]; string[] parts; if (range.Contains("/") == true) { parts = Spludlow.Net.IP.IPRangeFromCIDR(range); } else { parts = range.Split(new char[] { '-' }); parts[0] = parts[0].Trim(); parts[1] = parts[1].Trim(); } if (parts.Length != 2) throw new ApplicationException("inetnum did not split into 2 parts in whois: " + range); return new string[] { parts[0], parts[1] }; } } }