شركة التطبيقات المتكاملة لتصميم النظم البرمجية الخاصة

Integrated Applications Programming Company

Skip Navigation LinksHome » Code Library » Location

Public general use code classes and xml files that we've compiled and used over the years:

Geographic location related function, location, coordinates (latitude, longitude), bearing, degree and radian conversions, CMap value for resolution, and country geographic info-IP from MaxMind.

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