1: using System;
2: using System.Device.Location;
3: using System.IO;
4: using System.Net;
5: using System.Text;
6: using System.Text.RegularExpressions;
7:
8: namespace Ia.Cl.Model.Geography
9: {
10: ////////////////////////////////////////////////////////////////////////////
11:
12: /// <summary publish="true">
13: /// Geographic location related function, location, coordinates (latitude, longitude), bearing, degree and radian conversions, CMap value for resolution, and country geographic info-IP from MaxMind.
14: /// </summary>
15: ///
16: /// <see href="http://en.wikipedia.org/wiki/Geographic_coordinate_conversion"/>
17: ///
18: /// <remarks>
19: /// Copyright © 2001-2015 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
20: ///
21: /// This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
22: /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
23: ///
24: /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
25: /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
26: ///
27: /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
28: ///
29: /// Copyright notice: This notice may not be removed or altered from any source distribution.
30: /// </remarks>
31: public class Location
32: {
33: //private GeoCoordinate latitude2, longitude2;
34: private Coordinate latitude, longitude;
35:
36: private CoordinateType coordinateType { get; set; }
37:
38: private enum CoordinateType { Latitude, Longitude, Unknown };
39:
40: /// <summary/>
41: public double Latitude { get { return latitude.DegreeDecimal; } }
42:
43: /// <summary/>
44: public double Longitude { get { return longitude.DegreeDecimal; } }
45:
46: ////////////////////////////////////////////////////////////////////////////
47:
48: /// <summary>
49: ///
50: /// </summary>
51: public Location(double latitudeLocationInDegreeDecimal, double longitudeLocationInDegreeDecimal)
52: {
53: latitude = new Coordinate(latitudeLocationInDegreeDecimal);
54: longitude = new Coordinate(longitudeLocationInDegreeDecimal);
55: }
56:
57: ////////////////////////////////////////////////////////////////////////////
58:
59: /// <summary>
60: ///
61: /// </summary>
62: public Location(string latitudeLocationInDegreeMinuteDecimalSecond, string longitudeLocationInDegreeMinuteDecimalSecond)
63: {
64: latitude = new Coordinate(latitudeLocationInDegreeMinuteDecimalSecond);
65: longitude = new Coordinate(longitudeLocationInDegreeMinuteDecimalSecond);
66: }
67:
68: ////////////////////////////////////////////////////////////////////////////
69:
70: /// <summary>
71: ///
72: /// </summary>
73: public static double[] ConvertWgs84ToGoogleBing(double lat, double lon)
74: {
75: double x = lon * 20037508.34 / 180;
76: double y = Math.Log(Math.Tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);
77: y = y * 20037508.34 / 180;
78:
79: return new double[] { x, y };
80: }
81:
82: ////////////////////////////////////////////////////////////////////////////
83:
84: /// <summary>
85: ///
86: /// </summary>
87: public static double[] ConvertGoogleBingToWgs84Mercator(double x, double y)
88: {
89: double lon = (x / 20037508.34) * 180;
90: double lat = (y / 20037508.34) * 180;
91:
92: lat = 180 / Math.PI * (2 * Math.Atan(Math.Exp(lat * Math.PI / 180)) - Math.PI / 2);
93:
94: return new double[] { lon, lat };
95: }
96:
97: ////////////////////////////////////////////////////////////////////////////
98:
99: /// <summary>
100: /// Accepts two coordinates in degrees.
101: /// </summary>
102: /// <returns>A double value in degrees from 0 to 360.</returns>
103: public static Double Bearing(Location coordinate1, Location coordinate2)
104: {
105: var latitude1 = DegreeToRadian(coordinate1.Latitude);
106: var latitude2 = DegreeToRadian(coordinate2.Latitude);
107:
108: var longitudeDifference = DegreeToRadian((coordinate2.Longitude - coordinate1.Longitude));
109:
110: var y = Math.Sin(longitudeDifference) * Math.Cos(latitude2);
111: var x = Math.Cos(latitude1) * Math.Sin(latitude2) -
112: Math.Sin(latitude1) * Math.Cos(latitude2) * Math.Cos(longitudeDifference);
113:
114: return (RadianToDegree(Math.Atan2(y, x)) + 360) % 360;
115: }
116:
117: ////////////////////////////////////////////////////////////////////////////
118:
119: /// <summary>
120: /// Distance between two coordinates in meters.
121: /// </summary>
122: public double GetDistanceTo(Location otherLocation)
123: {
124: double distance;
125: GeoCoordinate gc1, gc2;
126:
127: gc1 = new GeoCoordinate(this.Latitude, this.Longitude);
128: gc2 = new GeoCoordinate(otherLocation.Latitude, otherLocation.Longitude);
129:
130: distance = gc1.GetDistanceTo(gc2);
131:
132: return distance;
133: }
134:
135: ////////////////////////////////////////////////////////////////////////////
136:
137: /// <summary>
138: ///
139: /// </summary>
140: private static double DegreeToRadian(double angle)
141: {
142: return Math.PI * angle / 180.0;
143: }
144:
145: ////////////////////////////////////////////////////////////////////////////
146:
147: /// <summary>
148: ///
149: /// </summary>
150: private static double RadianToDegree(double angle)
151: {
152: return angle * (180.0 / Math.PI);
153: }
154:
155: ////////////////////////////////////////////////////////////////////////////
156:
157: /// <summary>
158: ///
159: /// </summary>
160: public static string ReturnCMapValueForResolutionAndCoordinates(int resolution, double latitude, double longitude)
161: {
162: Location location;
163:
164: location = new Location(latitude, longitude);
165:
166: return location.ReturnCMapValueForResolution(resolution);
167: }
168:
169: ////////////////////////////////////////////////////////////////////////////
170:
171: /// <summary>
172: /// Converting latitude/longitude pairs to equivalent C-Squares
173: /// <remark ref="http://en.wikipedia.org/wiki/C-squares"/>
174: /// <remark ref="http://www.cmar.csiro.au/csquares/Point_java.txt"/>
175: /// </summary>
176: public string ReturnCMapValueForResolution(double resolution)
177: {
178: int i, j;
179: double llat, llon;
180: StringBuilder sb = new StringBuilder();
181:
182: if (latitude.DegreeDecimal >= 0)
183: {
184: if (longitude.DegreeDecimal >= 0) sb.Append('1');
185: else sb.Append('7');
186: }
187: else
188: {
189: if (longitude.DegreeDecimal >= 0) sb.Append('3');
190: else sb.Append('5');
191: }
192:
193: llat = Math.Abs(latitude.DegreeDecimal);
194:
195: if (llat >= 90) llat = 89.9;
196:
197: llon = Math.Abs(longitude.DegreeDecimal);
198:
199: if (llon >= 180) llon = 179.9;
200:
201: i = (int)(llat / 10);
202:
203: sb.Append(i);
204:
205: j = (int)(llon / 10);
206:
207: if (j < 10) sb.Append('0');
208:
209: sb.Append(j);
210:
211: if (resolution == 10)
212: {
213: return sb.ToString();
214: }
215: else
216: {
217: sb.Append(':');
218:
219: llat -= i * 10;
220:
221: llon -= j * 10;
222:
223: i = (int)llat;
224:
225: j = (int)llon;
226:
227: if (i < 5)
228: {
229: if (j < 5) sb.Append('1');
230: else sb.Append('2');
231: }
232: else
233: {
234: if (j < 5) sb.Append('3');
235: else sb.Append('4');
236: }
237:
238: if (resolution == 5)
239: {
240: return sb.ToString();
241: }
242: else
243: {
244: sb.Append(i);
245:
246: sb.Append(j);
247:
248: if (resolution == 1)
249: {
250: return sb.ToString();
251: }
252: else
253: {
254: sb.Append(':');
255:
256: i = (int)((llat - i) * 10);
257:
258: j = (int)((llon - j) * 10);
259:
260: if (i < 5)
261: {
262: if (j < 5) sb.Append('1');
263: else sb.Append('2');
264: }
265: else
266: {
267: if (j < 5) sb.Append('3');
268: else sb.Append('4');
269: }
270:
271: if (resolution == 0.5)
272: {
273: return sb.ToString();
274: }
275: else
276: {
277: sb.Append(i);
278: sb.Append(j);
279:
280: return sb.ToString();
281: }
282: }
283: }
284: }
285: }
286:
287: ////////////////////////////////////////////////////////////////////////////
288: ////////////////////////////////////////////////////////////////////////////
289: }
290:
291:
292: ////////////////////////////////////////////////////////////////////////////
293: ////////////////////////////////////////////////////////////////////////////
294:
295: /// <summary>
296: ///
297: /// <remark ref="http://en.wikipedia.org/wiki/Geographic_coordinate_conversion"/>
298: /// </summary>
299: public class Coordinate
300: {
301: private double degreeDecimal;
302: private CoordinateType coordinateType { get; set; }
303:
304: private enum CoordinateType { Latitude, Longitude, Unknown };
305:
306: /// <summary/>
307: public bool IsNegative { get; set; }
308:
309: /// <summary/>
310: public int Degrees { get; set; }
311:
312: /// <summary/>
313: public int Minutes { get; set; }
314:
315: /// <summary/>
316: public int Seconds { get; set; }
317:
318: /// <summary/>
319: public int Milliseconds { get; set; }
320:
321: /*
322: * There are three basic forms of a coordinate.
323: *
324: * Coordinate containing degrees (integer), minutes (integer), and seconds (integer, or real number) (DMS).
325: * Coordinate containing degrees (integer) and minutes (real number) (MinDec).
326: * Coordinate containing only degrees (real number) (DegDec).
327: *
328: */
329:
330: ////////////////////////////////////////////////////////////////////////////
331:
332: /// <summary>
333: ///
334: /// </summary>
335: public Coordinate()
336: {
337: }
338:
339: ////////////////////////////////////////////////////////////////////////////
340:
341: /// <summary>
342: ///
343: /// </summary>
344: public Coordinate(double locationInDegreeDecimal)
345: {
346: degreeDecimal = locationInDegreeDecimal;
347:
348: // ensure the value will fall within the primary range [-180.0..+180.0]
349: while (locationInDegreeDecimal < -180.0) locationInDegreeDecimal += 360.0;
350:
351: while (locationInDegreeDecimal > 180.0) locationInDegreeDecimal -= 360.0;
352:
353: // switch the value to positive
354: IsNegative = locationInDegreeDecimal < 0;
355: locationInDegreeDecimal = Math.Abs(locationInDegreeDecimal);
356:
357: // gets the degree
358: Degrees = (int)Math.Floor(locationInDegreeDecimal);
359: var delta = locationInDegreeDecimal - Degrees;
360:
361: // gets minutes and seconds
362: var seconds = (int)Math.Floor(3600.0 * delta);
363: Seconds = seconds % 60;
364: Minutes = (int)Math.Floor(seconds / 60.0);
365: delta = delta * 3600.0 - seconds;
366:
367: // gets fractions
368: Milliseconds = (int)(1000.0 * delta);
369:
370: coordinateType = CoordinateType.Unknown;
371: }
372:
373: ////////////////////////////////////////////////////////////////////////////
374:
375: /// <summary>
376: ///
377: /// </summary>
378: public Coordinate(string locationInDegreeMinuteDecimalSecond)
379: {
380: double d;
381: string sign, r;
382: Match m;
383:
384: sign = "";
385:
386: /*
387: * All of the following are valid and acceptable ways to write geographic coordinates:
388: * 40°26'47"N 79°58'36"W
389: * 40°26′47″N 79°58′36″W
390: * 40:26:46N,79:56:55W
391: * 40:26:46.302N 79:56:55.903W
392:
393: * 40d 26′ 47″ N 79d 58′ 36″ W
394: * 40.446195N 79.948862W
395: * 40.446195, -79.948862
396: * 40° 26.7717, -79° 56.93172
397: */
398:
399: m = Regex.Match(locationInDegreeMinuteDecimalSecond, @"(\d{1,3})°(\d{1,2})['′](.{1,})[""″]([NSEW])");
400:
401: if (m.Success) { }
402: else m = Regex.Match(locationInDegreeMinuteDecimalSecond, @"(\d{1,3})[: ](\d{1,2})[: ](.{1,})([NSEW])");
403:
404: if (m.Success)
405: {
406: try
407: {
408: Degrees = int.Parse(m.Groups[1].Captures[0].Value);
409: Minutes = int.Parse(m.Groups[2].Captures[0].Value);
410:
411: d = double.Parse(m.Groups[3].Captures[0].Value);
412:
413: Seconds = (int)d;
414:
415: d = d - Seconds;
416:
417: Milliseconds = (int)(d * 1000);
418:
419: // the sign
420: sign = m.Groups[4].Captures[0].Value;
421: }
422: catch (Exception ex)
423: {
424: #if DEBUG
425: r = "Error: " + ex.ToString();
426: #else
427: r = "Error: " + ex.Message;
428: #endif
429: }
430: finally
431: {
432: }
433: }
434: else
435: {
436: m = Regex.Match(locationInDegreeMinuteDecimalSecond, @"(\d{1,3})°(\d{1,2})['′]([NSEW])");
437:
438: if (m.Success) { }
439: else m = Regex.Match(locationInDegreeMinuteDecimalSecond, @"(\d{1,3})[: ](\d{1,2})[: ]([NSEW])");
440:
441: if (m.Success)
442: {
443: try
444: {
445: Degrees = int.Parse(m.Groups[1].Captures[0].Value);
446: Minutes = int.Parse(m.Groups[2].Captures[0].Value);
447:
448: Seconds = 0;
449: Milliseconds = 0;
450:
451: // the sign
452: sign = m.Groups[3].Captures[0].Value;
453: }
454: catch (Exception ex)
455: {
456: #if DEBUG
457: r = "Error: " + ex.ToString();
458: #else
459: r = "Error: " + ex.Message;
460: #endif
461: }
462: finally
463: {
464: }
465: }
466: }
467:
468: if (sign == "N" || sign == "E")
469: {
470: IsNegative = false;
471: coordinateType = CoordinateType.Latitude;
472: }
473: else if (sign == "S" || sign == "W")
474: {
475: IsNegative = true;
476: coordinateType = CoordinateType.Longitude;
477: }
478: else
479: {
480: coordinateType = CoordinateType.Unknown;
481: //throw new Exception();
482: }
483: }
484:
485: ////////////////////////////////////////////////////////////////////////////
486:
487: /// <summary>
488: ///
489: /// </summary>
490: public double DegreeDecimal
491: {
492: get
493: {
494: double d;
495:
496: //return degreeDecimal;
497:
498: // Calculate the total number of seconds:
499: d = Milliseconds / 1000.0 + Seconds + Minutes * 60;
500:
501: // The fractional part is total number of seconds divided by 3600:
502: d = d / 3600;
503:
504: // Add fractional degrees to whole degrees to produce the final result:
505: d = Degrees + d;
506:
507: // switch the value to positive
508: if (IsNegative) d = -d;
509:
510: return Math.Round(d, 6);
511: }
512: }
513:
514: ////////////////////////////////////////////////////////////////////////////
515:
516: /// <summary>
517: ///
518: /// </summary>
519: public string DegreeMinuteSecond()
520: {
521: switch (coordinateType)
522: {
523: case CoordinateType.Latitude:
524: return string.Format(
525: "{0}°{1:00}'{2:00}\"{3}",
526: this.Degrees,
527: this.Minutes,
528: this.Seconds,
529: this.IsNegative ? 'S' : 'N');
530:
531: case CoordinateType.Longitude:
532: return string.Format(
533: "{0}°{1:00}'{2:00}\"{3}",
534: this.Degrees,
535: this.Minutes,
536: this.Seconds,
537: this.IsNegative ? 'W' : 'E');
538:
539: default:
540: return string.Format(
541: "{0}°{1:00}'{2:00}\"",
542: this.Degrees,
543: this.Minutes,
544: this.Seconds);
545: }
546: }
547:
548: ////////////////////////////////////////////////////////////////////////////
549:
550: /// <summary>
551: ///
552: /// </summary>
553: public string DegreeMinuteDecimalSecond()
554: {
555: switch (coordinateType)
556: {
557: case CoordinateType.Latitude:
558: return string.Format(
559: "{0}°{1:00}'{2:00}.{3:000}\"{4}",
560: this.Degrees,
561: this.Minutes,
562: this.Seconds,
563: this.Milliseconds,
564: this.IsNegative ? 'S' : 'N');
565:
566: case CoordinateType.Longitude:
567: return string.Format(
568: "{0}°{1:00}'{2:00}.{3:000}\"{4}",
569: this.Degrees,
570: this.Minutes,
571: this.Seconds,
572: this.Milliseconds,
573: this.IsNegative ? 'W' : 'E');
574:
575: default:
576: return string.Format(
577: "{0}°{1:00}'{2:00}.{3:000}\"",
578: this.Degrees,
579: this.Minutes,
580: this.Seconds,
581: this.Milliseconds);
582: }
583: }
584:
585: ////////////////////////////////////////////////////////////////////////////
586:
587: /// <summary>
588: ///
589: /// </summary>
590: public string DegreeMinuteSecondDecimalMilliSecond()
591: {
592: switch (coordinateType)
593: {
594: case CoordinateType.Latitude:
595: return string.Format(
596: "{0}°{1:00}'{2:00}\"0.{3:000}{4}",
597: this.Degrees,
598: this.Minutes,
599: this.Seconds,
600: this.Milliseconds,
601: this.IsNegative ? 'S' : 'N');
602:
603: case CoordinateType.Longitude:
604: return string.Format(
605: "{0}°{1:00}'{2:00}\"0.{3:000}{4}",
606: this.Degrees,
607: this.Minutes,
608: this.Seconds,
609: this.Milliseconds,
610: this.IsNegative ? 'W' : 'E');
611:
612: default:
613: return string.Format(
614: "{0}°{1:00}'{2:00}\"0.{3:000}",
615: this.Degrees,
616: this.Minutes,
617: this.Seconds,
618: this.Milliseconds);
619: }
620: }
621:
622: ////////////////////////////////////////////////////////////////////////////
623: ////////////////////////////////////////////////////////////////////////////
624: }
625:
626: ////////////////////////////////////////////////////////////////////////////
627: ////////////////////////////////////////////////////////////////////////////
628:
629: /* CountryLookup.cs
630: *
631: * Copyright (C) 2008 MaxMind, Inc. All Rights Reserved.
632: *
633: * This library is free software; you can redistribute it and/or
634: * modify it under the terms of the GNU General Public
635: * License as published by the Free Software Foundation; either
636: * version 2 of the License, or (at your option) any later version.
637: *
638: * This library is distributed in the hope that it will be useful,
639: * but WITHOUT ANY WARRANTY; without even the implied warranty of
640: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
641: * General Public License for more details.
642: *
643: * You should have received a copy of the GNU General Public
644: * License along with this library; if not, write to the Free Software
645: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
646: */
647:
648: ////////////////////////////////////////////////////////////////////////////
649:
650: /// <summary>
651: ///
652: /// </summary>
653: public class GeoIp
654: {
655: private FileStream fileInput;
656: private long COUNTRY_BEGIN = 16776960;
657: private string[] countryCode =
658: { "--","AP","EU","AD","AE","AF","AG","AI","AL","AM","AN","AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB","BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO","BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD","CF","CG","CH","CI","CK","CL","CM","CN","CO","CR","CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO","DZ",
659: "EC","EE","EG","EH","ER","ES","ET","FI","FJ","FK","FM","FO","FR","FX","GA","GB","GD","GE","GF","GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT","GU","GW","GY","HK","HM","HN","HR","HT","HU","ID","IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO","JP","KE","KG","KH","KI","KM","KN","KP","KR","KW","KY","KZ",
660: "LA","LB","LC","LI","LK","LR","LS","LT","LU","LV","LY","MA","MC","MD","MG","MH","MK","ML","MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV","MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI","NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF","PG","PH","PK","PL","PM","PN","PR","PS","PT","PW","PY","QA",
661: "RE","RO","RU","RW","SA","SB","SC","SD","SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO","SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH","TJ","TK","TM","TN","TO","TL","TR","TT","TV","TW","TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE","VG","VI","VN","VU","WF","WS","YE","YT","RS","ZA","ZM","ME","ZW","A1","A2",
662: "O1","AX","GG","IM","JE","BL","MF"
663: };
664: private string[] countryName =
665: {"N/A","Asia/Pacific Region","Europe","Andorra","United Arab Emirates","Afghanistan","Antigua and Barbuda","Anguilla","Albania","Armenia","Netherlands Antilles","Angola","Antarctica","Argentina","American Samoa","Austria","Australia","Aruba","Azerbaijan","Bosnia and Herzegovina","Barbados","Bangladesh","Belgium",
666: "Burkina Faso","Bulgaria","Bahrain","Burundi","Benin","Bermuda","Brunei Darussalam","Bolivia","Brazil","Bahamas","Bhutan","Bouvet Island","Botswana","Belarus","Belize","Canada","Cocos (Keeling) Islands","Congo, The Democratic Republic of the","Central African Republic","Congo","Switzerland","Cote D'Ivoire",
667: "Cook Islands","Chile","Cameroon","China","Colombia","Costa Rica","Cuba","Cape Verde","Christmas Island","Cyprus","Czech Republic","Germany","Djibouti","Denmark","Dominica","Dominican Republic","Algeria","Ecuador","Estonia","Egypt","Western Sahara","Eritrea","Spain","Ethiopia","Finland","Fiji","Falkland Islands (Malvinas)",
668: "Micronesia, Federated States of","Faroe Islands","France","France, Metropolitan","Gabon","United Kingdom","Grenada","Georgia","French Guiana","Ghana","Gibraltar","Greenland","Gambia","Guinea","Guadeloupe","Equatorial Guinea","Greece","South Georgia and the South Sandwich Islands","Guatemala","Guam","Guinea-Bissau","Guyana",
669: "Hong Kong","Heard Island and McDonald Islands","Honduras","Croatia","Haiti","Hungary","Indonesia","Ireland","Israel","India","British Indian Ocean Territory","Iraq","Iran, Islamic Republic of","Iceland","Italy","Jamaica","Jordan","Japan","Kenya","Kyrgyzstan","Cambodia","Kiribati","Comoros","Saint Kitts and Nevis",
670: "Korea, Democratic People's Republic of","Korea, Republic of","Kuwait","Cayman Islands","Kazakstan","Lao People's Democratic Republic","Lebanon","Saint Lucia","Liechtenstein","Sri Lanka","Liberia","Lesotho","Lithuania","Luxembourg","Latvia","Libyan Arab Jamahiriya","Morocco","Monaco","Moldova, Republic of","Madagascar",
671: "Marshall Islands","Macedonia","Mali","Myanmar","Mongolia","Macau","Northern Mariana Islands","Martinique","Mauritania","Montserrat","Malta","Mauritius","Maldives","Malawi","Mexico","Malaysia","Mozambique","Namibia","New Caledonia","Niger","Norfolk Island","Nigeria","Nicaragua","Netherlands",
672: "Norway","Nepal","Nauru","Niue","New Zealand","Oman","Panama","Peru","French Polynesia","Papua New Guinea","Philippines","Pakistan","Poland","Saint Pierre and Miquelon","Pitcairn Islands","Puerto Rico","Palestinian Territory","Portugal","Palau","Paraguay","Qatar","Reunion","Romania","Russian Federation","Rwanda","Saudi Arabia",
673: "Solomon Islands","Seychelles","Sudan","Sweden","Singapore","Saint Helena","Slovenia","Svalbard and Jan Mayen","Slovakia","Sierra Leone","San Marino","Senegal","Somalia","Suriname","Sao Tome and Principe","El Salvador","Syrian Arab Republic","Swaziland","Turks and Caicos Islands","Chad","French Southern Territories","Togo",
674: "Thailand","Tajikistan","Tokelau","Turkmenistan","Tunisia","Tonga","Timor-Leste","Turkey","Trinidad and Tobago","Tuvalu","Taiwan","Tanzania, United Republic of","Ukraine","Uganda","United States Minor Outlying Islands","United States","Uruguay","Uzbekistan","Holy See (Vatican City State)","Saint Vincent and the Grenadines",
675: "Venezuela","Virgin Islands, British","Virgin Islands, U.S.","Vietnam","Vanuatu","Wallis and Futuna","Samoa","Yemen","Mayotte","Serbia","South Africa","Zambia","Montenegro","Zimbabwe","Anonymous Proxy","Satellite Provider",
676: "Other","Aland Islands","Guernsey","Isle of Man","Jersey","Saint Barthelemy","Saint Martin"};
677:
678:
679: ////////////////////////////////////////////////////////////////////////////
680:
681: /// <summary>
682: ///
683: /// </summary>
684: public GeoIp(string fileName)
685: {
686: string path;
687:
688: try
689: {
690: path = Ia.Cl.Model.Default.AbsolutePath();
691:
692: fileInput = new FileStream(path + fileName, FileMode.Open, FileAccess.Read);
693: }
694: catch (FileNotFoundException)
695: {
696: Console.WriteLine("File " + fileName + " not found");
697: }
698: }
699:
700: ////////////////////////////////////////////////////////////////////////////
701:
702: /// <summary>
703: ///
704: /// </summary>
705: public string LookupCountryCode(string str)
706: {
707: IPAddress addr;
708:
709: try
710: {
711: addr = IPAddress.Parse(str);
712: }
713: catch (FormatException)
714: {
715: return "--";
716: }
717:
718: return LookupCountryCode(addr);
719: }
720:
721: ////////////////////////////////////////////////////////////////////////////
722:
723: /// <summary>
724: ///
725: /// </summary>
726: private long IPAddressToNumber(IPAddress addr)
727: {
728: long ipnum = 0;
729: //byte[] b = BitConverter.GetBytes(addr.Address);
730: byte[] b = addr.GetAddressBytes();
731:
732: for (int i = 0; i < 4; ++i)
733: {
734: long y = b[i];
735: if (y < 0)
736: {
737: y += 256;
738: }
739: ipnum += y << ((3 - i) * 8);
740: }
741: Console.WriteLine(ipnum);
742: return ipnum;
743: }
744:
745: ////////////////////////////////////////////////////////////////////////////
746:
747: /// <summary>
748: ///
749: /// </summary>
750: public string LookupCountryCode(IPAddress addr)
751: {
752: return (countryCode[(int)SeekCountry(0, IPAddressToNumber(addr), 31)]);
753: }
754:
755: ////////////////////////////////////////////////////////////////////////////
756:
757: /// <summary>
758: ///
759: /// </summary>
760: public string LookupCountryName(string str)
761: {
762: IPAddress addr;
763: try
764: {
765: addr = IPAddress.Parse(str);
766: }
767: catch (FormatException)
768: {
769: return "N/A";
770: }
771: return LookupCountryName(addr);
772: }
773:
774: ////////////////////////////////////////////////////////////////////////////
775:
776: /// <summary>
777: ///
778: /// </summary>
779: public string LookupCountryName(IPAddress addr)
780: {
781: return (countryName[(int)SeekCountry(0, IPAddressToNumber(addr), 31)]);
782: }
783:
784: ////////////////////////////////////////////////////////////////////////////
785:
786: /// <summary>
787: ///
788: /// </summary>
789: private long SeekCountry(long offset, long ipnum, int depth)
790: {
791: byte[] buf = new byte[6];
792: long[] x = new long[2];
793: if (depth == 0)
794: {
795: Console.WriteLine("Error seeking country.");
796: }
797:
798: try
799: {
800: fileInput.Seek(6 * offset, 0);
801: fileInput.Read(buf, 0, 6);
802: }
803: catch (IOException)
804: {
805: Console.WriteLine("IO Exception");
806: }
807:
808: for (int i = 0; i < 2; i++)
809: {
810: x[i] = 0;
811: for (int j = 0; j < 3; j++)
812: {
813: int y = buf[i * 3 + j];
814: if (y < 0)
815: {
816: y += 256;
817: }
818: x[i] += (y << (j * 8));
819: }
820: }
821:
822: if ((ipnum & (1 << depth)) > 0)
823: {
824: if (x[1] >= COUNTRY_BEGIN)
825: {
826: return x[1] - COUNTRY_BEGIN;
827: }
828: return SeekCountry(x[1], ipnum, depth - 1);
829: }
830: else
831: {
832: if (x[0] >= COUNTRY_BEGIN)
833: {
834: return x[0] - COUNTRY_BEGIN;
835: }
836: return SeekCountry(x[0], ipnum, depth - 1);
837: }
838: }
839:
840: ////////////////////////////////////////////////////////////////////////////
841: ////////////////////////////////////////////////////////////////////////////
842: }
843: }