1 /* 2 * This file is part of the "GKMap". 3 * GKMap project borrowed from GMap.NET (by radioman). 4 * 5 * Copyright (C) 2009-2018 by radioman (email@radioman.lt). 6 * This program is licensed under the FLAT EARTH License. 7 */ 8 9 using System; 10 using System.Collections.Generic; 11 using System.Diagnostics; 12 using System.IO; 13 using System.Net; 14 using System.Security.Cryptography; 15 using System.Text; 16 17 namespace GKMap.MapProviders 18 { 19 /// <summary> 20 /// base class for each map provider 21 /// </summary> 22 public abstract class GMapProvider 23 { 24 /// <summary> 25 /// Time to live of cache, in hours. Default: 240 (10 days). 26 /// </summary> 27 public static int TTLCache = 240; 28 29 private string fAuthorization = string.Empty; 30 private bool fIsInitialized; 31 32 private static string fLanguageStr = "en"; 33 private static LanguageType fLanguage = LanguageType.English; 34 35 /// <summary> 36 /// was provider initialized 37 /// </summary> 38 public bool IsInitialized 39 { 40 get { 41 return fIsInitialized; 42 } 43 internal set { 44 fIsInitialized = value; 45 } 46 } 47 48 /// <summary> 49 /// unique provider id 50 /// </summary> 51 public virtual Guid Id 52 { 53 get { 54 throw new NotImplementedException(); 55 } 56 } 57 58 /// <summary> 59 /// provider name 60 /// </summary> 61 public virtual string Name 62 { 63 get { 64 throw new NotImplementedException(); 65 } 66 } 67 68 /// <summary> 69 /// provider projection 70 /// </summary> 71 public virtual PureProjection Projection 72 { 73 get { 74 throw new NotImplementedException(); 75 } 76 } 77 78 /// <summary> 79 /// provider overlays 80 /// </summary> 81 public virtual GMapProvider[] Overlays 82 { 83 get { 84 throw new NotImplementedException(); 85 } 86 } 87 88 /// <summary> 89 /// gets tile image using implemented provider 90 /// </summary> 91 /// <param name="pos"></param> 92 /// <param name="zoom"></param> 93 /// <returns></returns> GetTileImage(GPoint pos, int zoom)94 public virtual PureImage GetTileImage(GPoint pos, int zoom) 95 { 96 throw new NotImplementedException(); 97 } 98 99 private static readonly List<GMapProvider> MapProviders = new List<GMapProvider>(); 100 GMapProvider()101 protected GMapProvider() 102 { 103 using (var HashProvider = new SHA1CryptoServiceProvider()) { 104 DbId = Math.Abs(BitConverter.ToInt32(HashProvider.ComputeHash(Id.ToByteArray()), 0)); 105 } 106 107 if (MapProviders.Exists(p => p.Id == Id || p.DbId == DbId)) { 108 throw new Exception("such provider id already exists, try regenerate your provider guid..."); 109 } 110 MapProviders.Add(this); 111 } 112 113 /// <summary> 114 /// id for database, a hash of provider guid 115 /// </summary> 116 public readonly int DbId; 117 118 /// <summary> 119 /// area of map 120 /// </summary> 121 public RectLatLng? Area; 122 123 /// <summary> 124 /// minimum level of zoom 125 /// </summary> 126 public int MinZoom; 127 128 /// <summary> 129 /// maximum level of zoom 130 /// </summary> 131 public int? MaxZoom = 17; 132 133 /// <summary> 134 /// proxy for net access 135 /// </summary> 136 public static IWebProxy WebProxy; 137 138 /// <summary> 139 /// Connect trough a SOCKS 4/5 proxy server 140 /// </summary> 141 public static bool IsSocksProxy = false; 142 143 /// <summary> 144 /// NetworkCredential for tile http access 145 /// </summary> 146 public static ICredentials Credential; 147 148 /// <summary> 149 /// Gets or sets the value of the User-agent HTTP header. 150 /// It's pseudo-randomized to avoid blockages... 151 /// </summary> 152 public static string UserAgent = string.Format("Mozilla/5.0 (Windows NT {1}.0; {2}rv:{0}.0) Gecko/20100101 Firefox/{0}.0", 153 Stuff.Random.Next(DateTime.Today.Year - 1969 - 5, DateTime.Today.Year - 1969), 154 Stuff.Random.Next(0, 10) % 2 == 0 ? 10 : 6, 155 Stuff.Random.Next(0, 10) % 2 == 1 ? string.Empty : "WOW64; "); 156 157 /// <summary> 158 /// timeout for provider connections 159 /// </summary> 160 public static int TimeoutMs = 10 * 1000; 161 162 /// <summary> 163 /// Gets or sets the value of the Referer HTTP header. 164 /// </summary> 165 public string RefererUrl = string.Empty; 166 167 public string Copyright = string.Empty; 168 169 /// <summary> 170 /// true if tile origin at BottomLeft, WMS-C 171 /// </summary> 172 public bool InvertedAxisY = false; 173 174 public static string LanguageStr 175 { 176 get { 177 return fLanguageStr; 178 } 179 } 180 181 /// <summary> 182 /// map language 183 /// </summary> 184 public static LanguageType Language 185 { 186 get { 187 return fLanguage; 188 } 189 set { 190 fLanguage = value; 191 fLanguageStr = Stuff.EnumToString(fLanguage); 192 } 193 } 194 195 private static readonly string RequestAccept = "*/*"; 196 private static readonly string ResponseContentType = "image"; 197 198 GMapProvider()199 static GMapProvider() 200 { 201 WebProxy = EmptyWebProxy.Instance; 202 } 203 204 /// <summary> 205 /// called before first use 206 /// </summary> OnInitialized()207 public virtual void OnInitialized() 208 { 209 // nice place to detect current provider version 210 } 211 CheckTileImageHttpResponse(WebResponse response)212 protected virtual bool CheckTileImageHttpResponse(WebResponse response) 213 { 214 //Debug.WriteLine(response.StatusCode + "/" + response.StatusDescription + "/" + response.ContentType + " -> " + response.ResponseUri); 215 return response.ContentType.Contains(ResponseContentType); 216 } 217 218 /// <summary> 219 /// http://blog.kowalczyk.info/article/at3/Forcing-basic-http-authentication-for-HttpWebReq.html 220 /// </summary> 221 /// <param name="userName"></param> 222 /// <param name="userPassword"></param> ForceBasicHttpAuthentication(string userName, string userPassword)223 public void ForceBasicHttpAuthentication(string userName, string userPassword) 224 { 225 fAuthorization = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(userName + ":" + userPassword)); 226 } 227 GetRequest(string url)228 private WebRequest GetRequest(string url) 229 { 230 WebRequest request = IsSocksProxy ? SocksHttpWebRequest.Create(url) : WebRequest.Create(url); 231 232 if (WebProxy != null) { 233 request.Proxy = WebProxy; 234 } 235 236 if (Credential != null) { 237 request.PreAuthenticate = true; 238 request.Credentials = Credential; 239 } 240 241 if (!string.IsNullOrEmpty(fAuthorization)) { 242 request.Headers.Set("Authorization", fAuthorization); 243 } 244 245 if (request is HttpWebRequest) { 246 var r = request as HttpWebRequest; 247 r.UserAgent = UserAgent; 248 r.ReadWriteTimeout = TimeoutMs * 6; 249 r.Accept = RequestAccept; 250 r.Referer = RefererUrl; 251 r.Timeout = TimeoutMs; 252 } else if (request is SocksHttpWebRequest) { 253 var r = request as SocksHttpWebRequest; 254 255 if (!string.IsNullOrEmpty(UserAgent)) { 256 r.Headers.Add("User-Agent", UserAgent); 257 } 258 259 if (!string.IsNullOrEmpty(RequestAccept)) { 260 r.Headers.Add("Accept", RequestAccept); 261 } 262 263 if (!string.IsNullOrEmpty(RefererUrl)) { 264 r.Headers.Add("Referer", RefererUrl); 265 } 266 } 267 268 return request; 269 } 270 GetTileImageUsingHttp(string url)271 protected PureImage GetTileImageUsingHttp(string url) 272 { 273 PureImage ret = null; 274 275 WebRequest request = GetRequest(url); 276 using (var response = request.GetResponse()) { 277 if (CheckTileImageHttpResponse(response)) { 278 using (Stream responseStream = response.GetResponseStream()) { 279 MemoryStream data = Stuff.CopyStream(responseStream, false); 280 281 Debug.WriteLine("Response[" + data.Length + " bytes]: " + url); 282 283 if (data.Length > 0) { 284 ret = GMaps.TileImageProxy.FromStream(data); 285 286 if (ret != null) { 287 ret.Data = data; 288 ret.Data.Position = 0; 289 } else { 290 data.Dispose(); 291 } 292 } 293 } 294 } else { 295 Debug.WriteLine("CheckTileImageHttpResponse[false]: " + url); 296 } 297 response.Close(); 298 } 299 return ret; 300 } 301 GetContentUsingHttp(string url)302 protected string GetContentUsingHttp(string url) 303 { 304 string ret; 305 306 WebRequest request = GetRequest(url); 307 using (var response = request.GetResponse()) { 308 using (Stream responseStream = response.GetResponseStream()) { 309 using (StreamReader read = new StreamReader(responseStream, Encoding.UTF8)) { 310 ret = read.ReadToEnd(); 311 } 312 } 313 response.Close(); 314 } 315 316 return ret; 317 } 318 GetServerNum(GPoint pos, int max)319 protected static int GetServerNum(GPoint pos, int max) 320 { 321 return (int)(pos.X + 2 * pos.Y) % max; 322 } 323 GetHashCode()324 public override int GetHashCode() 325 { 326 return DbId; 327 } 328 Equals(object obj)329 public override bool Equals(object obj) 330 { 331 if (obj is GMapProvider) { 332 return Id.Equals(((GMapProvider) obj).Id); 333 } 334 return false; 335 } 336 ToString()337 public override string ToString() 338 { 339 return Name; 340 } 341 } 342 } 343