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:
120: /// <summary>
121: /// Distance between two coordinates in meters.
122: /// </summary>
123: public double GetDistanceTo(Location otherLocation)
124: {
125: double distance;
126: GeoCoordinate gc1, gc2;
127:
128: gc1 = new GeoCoordinate(this.Latitude, this.Longitude);
129: gc2 = new GeoCoordinate(otherLocation.Latitude, otherLocation.Longitude);
130:
131: distance = gc1.GetDistanceTo(gc2);
132:
133: return distance;
134: }
135: */
136:
137: ////////////////////////////////////////////////////////////////////////////
138:
139: /// <summary>
140: ///
141: /// </summary>
142: private static double DegreeToRadian(double angle)
143: {
144: return Math.PI * angle / 180.0;
145: }
146:
147: ////////////////////////////////////////////////////////////////////////////
148:
149: /// <summary>
150: ///
151: /// </summary>
152: private static double RadianToDegree(double angle)
153: {
154: return angle * (180.0 / Math.PI);
155: }
156:
157: ////////////////////////////////////////////////////////////////////////////
158:
159: /// <summary>
160: ///
161: /// </summary>
162: public static string ReturnCMapValueForResolutionAndCoordinates(int resolution, double latitude, double longitude)
163: {
164: Location location;
165:
166: location = new Location(latitude, longitude);
167:
168: return location.ReturnCMapValueForResolution(resolution);
169: }
170:
171: ////////////////////////////////////////////////////////////////////////////
172:
173: /// <summary>
174: /// Converting latitude/longitude pairs to equivalent C-Squares
175: /// <remark ref="http://en.wikipedia.org/wiki/C-squares"/>
176: /// <remark ref="http://www.cmar.csiro.au/csquares/Point_java.txt"/>
177: /// </summary>
178: public string ReturnCMapValueForResolution(double resolution)
179: {
180: int i, j;
181: double llat, llon;
182: StringBuilder sb = new StringBuilder();
183:
184: if (latitude.DegreeDecimal >= 0)
185: {
186: if (longitude.DegreeDecimal >= 0) sb.Append('1');
187: else sb.Append('7');
188: }
189: else
190: {
191: if (longitude.DegreeDecimal >= 0) sb.Append('3');
192: else sb.Append('5');
193: }
194:
195: llat = Math.Abs(latitude.DegreeDecimal);
196:
197: if (llat >= 90) llat = 89.9;
198:
199: llon = Math.Abs(longitude.DegreeDecimal);
200:
201: if (llon >= 180) llon = 179.9;
202:
203: i = (int)(llat / 10);
204:
205: sb.Append(i);
206:
207: j = (int)(llon / 10);
208:
209: if (j < 10) sb.Append('0');
210:
211: sb.Append(j);
212:
213: if (resolution == 10)
214: {
215: return sb.ToString();
216: }
217: else
218: {
219: sb.Append(':');
220:
221: llat -= i * 10;
222:
223: llon -= j * 10;
224:
225: i = (int)llat;
226:
227: j = (int)llon;
228:
229: if (i < 5)
230: {
231: if (j < 5) sb.Append('1');
232: else sb.Append('2');
233: }
234: else
235: {
236: if (j < 5) sb.Append('3');
237: else sb.Append('4');
238: }
239:
240: if (resolution == 5)
241: {
242: return sb.ToString();
243: }
244: else
245: {
246: sb.Append(i);
247:
248: sb.Append(j);
249:
250: if (resolution == 1)
251: {
252: return sb.ToString();
253: }
254: else
255: {
256: sb.Append(':');
257:
258: i = (int)((llat - i) * 10);
259:
260: j = (int)((llon - j) * 10);
261:
262: if (i < 5)
263: {
264: if (j < 5) sb.Append('1');
265: else sb.Append('2');
266: }
267: else
268: {
269: if (j < 5) sb.Append('3');
270: else sb.Append('4');
271: }
272:
273: if (resolution == 0.5)
274: {
275: return sb.ToString();
276: }
277: else
278: {
279: sb.Append(i);
280: sb.Append(j);
281:
282: return sb.ToString();
283: }
284: }
285: }
286: }
287: }
288:
289: ////////////////////////////////////////////////////////////////////////////
290: ////////////////////////////////////////////////////////////////////////////
291: }
292:
293:
294: ////////////////////////////////////////////////////////////////////////////
295: ////////////////////////////////////////////////////////////////////////////
296:
297: /// <summary>
298: ///
299: /// <remark ref="http://en.wikipedia.org/wiki/Geographic_coordinate_conversion"/>
300: /// </summary>
301: public class Coordinate
302: {
303: private double degreeDecimal;
304: private CoordinateType coordinateType { get; set; }
305:
306: private enum CoordinateType { Latitude, Longitude, Unknown };
307:
308: /// <summary/>
309: public bool IsNegative { get; set; }
310:
311: /// <summary/>
312: public int Degrees { get; set; }
313:
314: /// <summary/>
315: public int Minutes { get; set; }
316:
317: /// <summary/>
318: public int Seconds { get; set; }
319:
320: /// <summary/>
321: public int Milliseconds { get; set; }
322:
323: /*
324: * There are three basic forms of a coordinate.
325: *
326: * Coordinate containing degrees (integer), minutes (integer), and seconds (integer, or real number) (DMS).
327: * Coordinate containing degrees (integer) and minutes (real number) (MinDec).
328: * Coordinate containing only degrees (real number) (DegDec).
329: *
330: */
331:
332: ////////////////////////////////////////////////////////////////////////////
333:
334: /// <summary>
335: ///
336: /// </summary>
337: public Coordinate()
338: {
339: }
340:
341: ////////////////////////////////////////////////////////////////////////////
342:
343: /// <summary>
344: ///
345: /// </summary>
346: public Coordinate(double locationInDegreeDecimal)
347: {
348: degreeDecimal = locationInDegreeDecimal;
349:
350: // ensure the value will fall within the primary range [-180.0..+180.0]
351: while (locationInDegreeDecimal < -180.0) locationInDegreeDecimal += 360.0;
352:
353: while (locationInDegreeDecimal > 180.0) locationInDegreeDecimal -= 360.0;
354:
355: // switch the value to positive
356: IsNegative = locationInDegreeDecimal < 0;
357: locationInDegreeDecimal = Math.Abs(locationInDegreeDecimal);
358:
359: // gets the degree
360: Degrees = (int)Math.Floor(locationInDegreeDecimal);
361: var delta = locationInDegreeDecimal - Degrees;
362:
363: // gets minutes and seconds
364: var seconds = (int)Math.Floor(3600.0 * delta);
365: Seconds = seconds % 60;
366: Minutes = (int)Math.Floor(seconds / 60.0);
367: delta = delta * 3600.0 - seconds;
368:
369: // gets fractions
370: Milliseconds = (int)(1000.0 * delta);
371:
372: coordinateType = CoordinateType.Unknown;
373: }
374:
375: ////////////////////////////////////////////////////////////////////////////
376:
377: /// <summary>
378: ///
379: /// </summary>
380: public Coordinate(string locationInDegreeMinuteDecimalSecond)
381: {
382: double d;
383: string sign, r;
384: Match m;
385:
386: sign = "";
387:
388: /*
389: * All of the following are valid and acceptable ways to write geographic coordinates:
390: * 40°26'47"N 79°58'36"W
391: * 40°26′47″N 79°58′36″W
392: * 40:26:46N,79:56:55W
393: * 40:26:46.302N 79:56:55.903W
394:
395: * 40d 26′ 47″ N 79d 58′ 36″ W
396: * 40.446195N 79.948862W
397: * 40.446195, -79.948862
398: * 40° 26.7717, -79° 56.93172
399: */
400:
401: m = Regex.Match(locationInDegreeMinuteDecimalSecond, @"(\d{1,3})°(\d{1,2})['′](.{1,})[""″]([NSEW])");
402:
403: if (m.Success) { }
404: else m = Regex.Match(locationInDegreeMinuteDecimalSecond, @"(\d{1,3})[: ](\d{1,2})[: ](.{1,})([NSEW])");
405:
406: if (m.Success)
407: {
408: try
409: {
410: Degrees = int.Parse(m.Groups[1].Captures[0].Value);
411: Minutes = int.Parse(m.Groups[2].Captures[0].Value);
412:
413: d = double.Parse(m.Groups[3].Captures[0].Value);
414:
415: Seconds = (int)d;
416:
417: d = d - Seconds;
418:
419: Milliseconds = (int)(d * 1000);
420:
421: // the sign
422: sign = m.Groups[4].Captures[0].Value;
423: }
424: catch (Exception ex)
425: {
426: #if DEBUG
427: r = "Error: " + ex.ToString();
428: #else
429: r = "Error: " + ex.Message;
430: #endif
431: }
432: finally
433: {
434: }
435: }
436: else
437: {
438: m = Regex.Match(locationInDegreeMinuteDecimalSecond, @"(\d{1,3})°(\d{1,2})['′]([NSEW])");
439:
440: if (m.Success) { }
441: else m = Regex.Match(locationInDegreeMinuteDecimalSecond, @"(\d{1,3})[: ](\d{1,2})[: ]([NSEW])");
442:
443: if (m.Success)
444: {
445: try
446: {
447: Degrees = int.Parse(m.Groups[1].Captures[0].Value);
448: Minutes = int.Parse(m.Groups[2].Captures[0].Value);
449:
450: Seconds = 0;
451: Milliseconds = 0;
452:
453: // the sign
454: sign = m.Groups[3].Captures[0].Value;
455: }
456: catch (Exception ex)
457: {
458: #if DEBUG
459: r = "Error: " + ex.ToString();
460: #else
461: r = "Error: " + ex.Message;
462: #endif
463: }
464: finally
465: {
466: }
467: }
468: }
469:
470: if (sign == "N" || sign == "E")
471: {
472: IsNegative = false;
473: coordinateType = CoordinateType.Latitude;
474: }
475: else if (sign == "S" || sign == "W")
476: {
477: IsNegative = true;
478: coordinateType = CoordinateType.Longitude;
479: }
480: else
481: {
482: coordinateType = CoordinateType.Unknown;
483: //throw new Exception();
484: }
485: }
486:
487: ////////////////////////////////////////////////////////////////////////////
488:
489: /// <summary>
490: ///
491: /// </summary>
492: public double DegreeDecimal
493: {
494: get
495: {
496: double d;
497:
498: //return degreeDecimal;
499:
500: // Calculate the total number of seconds:
501: d = Milliseconds / 1000.0 + Seconds + Minutes * 60;
502:
503: // The fractional part is total number of seconds divided by 3600:
504: d = d / 3600;
505:
506: // Add fractional degrees to whole degrees to produce the final result:
507: d = Degrees + d;
508:
509: // switch the value to positive
510: if (IsNegative) d = -d;
511:
512: return Math.Round(d, 6);
513: }
514: }
515:
516: ////////////////////////////////////////////////////////////////////////////
517:
518: /// <summary>
519: ///
520: /// </summary>
521: public string DegreeMinuteSecond()
522: {
523: switch (coordinateType)
524: {
525: case CoordinateType.Latitude:
526: return string.Format(
527: "{0}°{1:00}'{2:00}\"{3}",
528: this.Degrees,
529: this.Minutes,
530: this.Seconds,
531: this.IsNegative ? 'S' : 'N');
532:
533: case CoordinateType.Longitude:
534: return string.Format(
535: "{0}°{1:00}'{2:00}\"{3}",
536: this.Degrees,
537: this.Minutes,
538: this.Seconds,
539: this.IsNegative ? 'W' : 'E');
540:
541: default:
542: return string.Format(
543: "{0}°{1:00}'{2:00}\"",
544: this.Degrees,
545: this.Minutes,
546: this.Seconds);
547: }
548: }
549:
550: ////////////////////////////////////////////////////////////////////////////
551:
552: /// <summary>
553: ///
554: /// </summary>
555: public string DegreeMinuteDecimalSecond()
556: {
557: switch (coordinateType)
558: {
559: case CoordinateType.Latitude:
560: return string.Format(
561: "{0}°{1:00}'{2:00}.{3:000}\"{4}",
562: this.Degrees,
563: this.Minutes,
564: this.Seconds,
565: this.Milliseconds,
566: this.IsNegative ? 'S' : 'N');
567:
568: case CoordinateType.Longitude:
569: return string.Format(
570: "{0}°{1:00}'{2:00}.{3:000}\"{4}",
571: this.Degrees,
572: this.Minutes,
573: this.Seconds,
574: this.Milliseconds,
575: this.IsNegative ? 'W' : 'E');
576:
577: default:
578: return string.Format(
579: "{0}°{1:00}'{2:00}.{3:000}\"",
580: this.Degrees,
581: this.Minutes,
582: this.Seconds,
583: this.Milliseconds);
584: }
585: }
586:
587: ////////////////////////////////////////////////////////////////////////////
588:
589: /// <summary>
590: ///
591: /// </summary>
592: public string DegreeMinuteSecondDecimalMilliSecond()
593: {
594: switch (coordinateType)
595: {
596: case CoordinateType.Latitude:
597: return string.Format(
598: "{0}°{1:00}'{2:00}\"0.{3:000}{4}",
599: this.Degrees,
600: this.Minutes,
601: this.Seconds,
602: this.Milliseconds,
603: this.IsNegative ? 'S' : 'N');
604:
605: case CoordinateType.Longitude:
606: return string.Format(
607: "{0}°{1:00}'{2:00}\"0.{3:000}{4}",
608: this.Degrees,
609: this.Minutes,
610: this.Seconds,
611: this.Milliseconds,
612: this.IsNegative ? 'W' : 'E');
613:
614: default:
615: return string.Format(
616: "{0}°{1:00}'{2:00}\"0.{3:000}",
617: this.Degrees,
618: this.Minutes,
619: this.Seconds,
620: this.Milliseconds);
621: }
622: }
623:
624: ////////////////////////////////////////////////////////////////////////////
625: ////////////////////////////////////////////////////////////////////////////
626: }
627:
628: ////////////////////////////////////////////////////////////////////////////
629: ////////////////////////////////////////////////////////////////////////////
630:
631: /* CountryLookup.cs
632: *
633: * Copyright (C) 2008 MaxMind, Inc. All Rights Reserved.
634: *
635: * This library is free software; you can redistribute it and/or
636: * modify it under the terms of the GNU General Public
637: * License as published by the Free Software Foundation; either
638: * version 2 of the License, or (at your option) any later version.
639: *
640: * This library is distributed in the hope that it will be useful,
641: * but WITHOUT ANY WARRANTY; without even the implied warranty of
642: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
643: * General Public License for more details.
644: *
645: * You should have received a copy of the GNU General Public
646: * License along with this library; if not, write to the Free Software
647: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
648: */
649:
650: ////////////////////////////////////////////////////////////////////////////
651:
652: /// <summary>
653: ///
654: /// </summary>
655: public class GeoIp
656: {
657: private FileStream fileInput;
658: private long COUNTRY_BEGIN = 16776960;
659: private string[] countryCode =
660: { "--","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",
661: "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",
662: "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",
663: "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",
664: "O1","AX","GG","IM","JE","BL","MF"
665: };
666: private string[] countryName =
667: {"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",
668: "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",
669: "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)",
670: "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",
671: "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",
672: "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",
673: "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",
674: "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",
675: "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",
676: "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",
677: "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",
678: "Other","Aland Islands","Guernsey","Isle of Man","Jersey","Saint Barthelemy","Saint Martin"};
679:
680:
681: ////////////////////////////////////////////////////////////////////////////
682:
683: /// <summary>
684: ///
685: /// </summary>
686: public GeoIp(string fileName)
687: {
688: string path;
689:
690: try
691: {
692: path = Ia.Cl.Model.Default.AbsolutePath();
693:
694: fileInput = new FileStream(path + fileName, FileMode.Open, FileAccess.Read);
695: }
696: catch (FileNotFoundException)
697: {
698: Console.WriteLine("File " + fileName + " not found");
699: }
700: }
701:
702: ////////////////////////////////////////////////////////////////////////////
703:
704: /// <summary>
705: ///
706: /// </summary>
707: public string LookupCountryCode(string str)
708: {
709: IPAddress addr;
710:
711: try
712: {
713: addr = IPAddress.Parse(str);
714: }
715: catch (FormatException)
716: {
717: return "--";
718: }
719:
720: return LookupCountryCode(addr);
721: }
722:
723: ////////////////////////////////////////////////////////////////////////////
724:
725: /// <summary>
726: ///
727: /// </summary>
728: private long IPAddressToNumber(IPAddress addr)
729: {
730: long ipnum = 0;
731: //byte[] b = BitConverter.GetBytes(addr.Address);
732: byte[] b = addr.GetAddressBytes();
733:
734: for (int i = 0; i < 4; ++i)
735: {
736: long y = b[i];
737: if (y < 0)
738: {
739: y += 256;
740: }
741: ipnum += y << ((3 - i) * 8);
742: }
743: Console.WriteLine(ipnum);
744: return ipnum;
745: }
746:
747: ////////////////////////////////////////////////////////////////////////////
748:
749: /// <summary>
750: ///
751: /// </summary>
752: public string LookupCountryCode(IPAddress addr)
753: {
754: return (countryCode[(int)SeekCountry(0, IPAddressToNumber(addr), 31)]);
755: }
756:
757: ////////////////////////////////////////////////////////////////////////////
758:
759: /// <summary>
760: ///
761: /// </summary>
762: public string LookupCountryName(string str)
763: {
764: IPAddress addr;
765: try
766: {
767: addr = IPAddress.Parse(str);
768: }
769: catch (FormatException)
770: {
771: return "N/A";
772: }
773: return LookupCountryName(addr);
774: }
775:
776: ////////////////////////////////////////////////////////////////////////////
777:
778: /// <summary>
779: ///
780: /// </summary>
781: public string LookupCountryName(IPAddress addr)
782: {
783: return (countryName[(int)SeekCountry(0, IPAddressToNumber(addr), 31)]);
784: }
785:
786: ////////////////////////////////////////////////////////////////////////////
787:
788: /// <summary>
789: ///
790: /// </summary>
791: private long SeekCountry(long offset, long ipnum, int depth)
792: {
793: byte[] buf = new byte[6];
794: long[] x = new long[2];
795: if (depth == 0)
796: {
797: Console.WriteLine("Error seeking country.");
798: }
799:
800: try
801: {
802: fileInput.Seek(6 * offset, 0);
803: fileInput.Read(buf, 0, 6);
804: }
805: catch (IOException)
806: {
807: Console.WriteLine("IO Exception");
808: }
809:
810: for (int i = 0; i < 2; i++)
811: {
812: x[i] = 0;
813: for (int j = 0; j < 3; j++)
814: {
815: int y = buf[i * 3 + j];
816: if (y < 0)
817: {
818: y += 256;
819: }
820: x[i] += (y << (j * 8));
821: }
822: }
823:
824: if ((ipnum & (1 << depth)) > 0)
825: {
826: if (x[1] >= COUNTRY_BEGIN)
827: {
828: return x[1] - COUNTRY_BEGIN;
829: }
830: return SeekCountry(x[1], ipnum, depth - 1);
831: }
832: else
833: {
834: if (x[0] >= COUNTRY_BEGIN)
835: {
836: return x[0] - COUNTRY_BEGIN;
837: }
838: return SeekCountry(x[0], ipnum, depth - 1);
839: }
840: }
841:
842: ////////////////////////////////////////////////////////////////////////////
843: ////////////////////////////////////////////////////////////////////////////
844: }
845: }