Beispiel #1
0
        /// <summary>
        /// Extracts information out of the path parts for a fake URL that has had its substitution markers replaced with
        /// real values by Leaflet.
        /// </summary>
        /// <param name="pathParts">A collection of strings that represent the folders in a URL's path. The filename
        /// and scheme are missing. An empty collection indicates that the request was for root.</param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public FakeUrlEncodedValues ExtractEncodedValuesFromUrlParts(IEnumerable <string> pathParts, string fileName)
        {
            FakeUrlEncodedValues result = null;

            if (pathParts != null && String.Equals(pathParts.FirstOrDefault(), PageName, StringComparison.OrdinalIgnoreCase))
            {
                result = new FakeUrlEncodedValues();

                foreach (var pathPart in pathParts)
                {
                    var hyphenIdx = pathPart.IndexOf('-');
                    if (hyphenIdx > 0)
                    {
                        var name  = pathPart.Substring(0, hyphenIdx);
                        var value = pathPart.Substring(hyphenIdx + 1);

                        if (name.StartsWith(VariablePrefix))
                        {
                            var substitutionMarker = name.Substring(VariablePrefix.Length);
                            switch (substitutionMarker)
                            {
                            case "r":   result.Retina = value; break;

                            case "x":   result.X = value; break;

                            case "y":   result.Y = value; break;

                            case "z":   result.Zoom = value; break;

                            default:    result.OtherValues.Add(substitutionMarker, value); break;
                            }
                        }
                        else
                        {
                            switch (name)
                            {
                            case MapProviderName:
                                if (int.TryParse(value, out var mp) && Enum.IsDefined(typeof(MapProvider), mp))
                                {
                                    result.MapProvider = (MapProvider)mp;
                                }
                                break;

                            case TileServerName:
                                result.Name = value.Trim();
                                break;
                            }
                        }
                    }
                }

                result.TileImageExtension = String.IsNullOrEmpty(fileName) ? ".png" : Path.GetExtension(fileName);
            }

            return(result);
        }
Beispiel #2
0
 internal void CopyUrlValues(FakeUrlEncodedValues urlValues)
 {
     if (urlValues != null)
     {
         TileServerName = urlValues.Name;
         Zoom           = urlValues.Zoom;
         X      = urlValues.X;
         Y      = urlValues.Y;
         Retina = urlValues.Retina;
     }
 }
Beispiel #3
0
 /// <summary>
 /// Returns the cached tile image or null if no such image exists.
 /// </summary>
 /// <param name="urlValues"></param>
 /// <returns></returns>
 public static CachedTile GetCachedTile(FakeUrlEncodedValues urlValues)
 {
     return(GetCachedTile(
                urlValues.MapProvider,
                urlValues.Name,
                urlValues.Zoom,
                urlValues.X,
                urlValues.Y,
                urlValues.Retina,
                urlValues.TileImageExtension
                ));
 }
Beispiel #4
0
 /// <summary>
 /// Saves the image bytes.
 /// </summary>
 /// <param name="urlValues"></param>
 /// <param name="content"></param>
 public static void SaveTile(FakeUrlEncodedValues urlValues, byte[] content)
 {
     SaveTile(
         urlValues.MapProvider,
         urlValues.Name,
         urlValues.Zoom,
         urlValues.X,
         urlValues.Y,
         urlValues.Retina,
         urlValues.TileImageExtension,
         content
         );
 }
Beispiel #5
0
        /// <summary>
        /// Subtitutes the values from a fake encoded URL into a real tile server URL.
        /// </summary>
        /// <param name="urlWithMarkers"></param>
        /// <param name="values"></param>
        /// <param name="subdomains">Leaflet-style list of subdomains to substitute into the {s} parameter (if present). Defaults to abc if null / empty.</param>
        /// <returns></returns>
        public string ExpandUrlParameters(string urlWithMarkers, FakeUrlEncodedValues values, string subdomains)
        {
            var result = new StringBuilder(urlWithMarkers ?? "");

            if (String.IsNullOrEmpty(subdomains))
            {
                subdomains = "abc";
            }

            foreach (var match in _MatchSubstitutionMarker.Matches(result.ToString()).OfType <Match>().OrderByDescending(r => r.Index))
            {
                var value  = "";
                var start  = match.Groups[1].Index;
                var length = match.Groups[1].Length;
                var marker = match.Groups[2].Value;

                switch (marker)
                {
                case "r":   value = values.Retina; break;

                case "x":   value = values.X; break;

                case "y":   value = values.Y; break;

                case "z":   value = values.Zoom; break;

                case "s":
                    var random = new Random();
                    var idx    = random.Next(subdomains.Length);
                    value = new String(subdomains[idx], 1);
                    break;

                default:
                    if (values.OtherValues.TryGetValue(marker, out var otherValue))
                    {
                        value = otherValue;
                    }
                    break;
                }

                result.Remove(start, length);
                result.Insert(start, value ?? "");
            }

            return(result.ToString());
        }
Beispiel #6
0
        /// <summary>
        /// Downloads the tile image using the URL values passed across.
        /// </summary>
        /// <param name="options"></param>
        /// <param name="urlValues"></param>
        /// <param name="clientEndpoint"></param>
        /// <param name="headers"></param>
        /// <param name="outcome"></param>
        /// <param name="displayOutcome"></param>
        /// <returns></returns>
        private void FetchTileServerImage(Options options, FakeUrlEncodedValues urlValues, IPAddress clientEndpoint, HeadersDictionary headers, WebRequestOutcome outcome, RequestOutcome displayOutcome)
        {
            var tileServerSettings = Plugin.TileServerSettingsManagerWrapper.GetRealTileServerSettings(
                urlValues.MapProvider,
                urlValues.Name
                );

            if (tileServerSettings != null)
            {
                var tileImageUrl = _TileServerUrlTranslator.ExpandUrlParameters(
                    tileServerSettings.Url,
                    urlValues,
                    tileServerSettings.Subdomains
                    );

                var request = (HttpWebRequest)HttpWebRequest.Create(tileImageUrl);
                request.Method = "GET";
                request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
                foreach (var headerKey in headers.Keys)
                {
                    var value = headers[headerKey];
                    switch (headerKey.ToLower())
                    {
                    case "accept":              request.Accept = value; break;

                    case "accept-encoding":     break;

                    case "connection":          break;

                    case "content-length":      break;

                    case "content-type":        request.ContentType = value; break;

                    case "date":                break;

                    case "expect":              request.Expect = value; break;

                    case "host":                break;

                    case "if-modified-since":   break;

                    case "proxy-connection":    break;

                    case "range":               break;

                    case "referer":             request.Referer = value; break;

                    case "transfer-encoding":   request.TransferEncoding = value; break;

                    case "user-agent":          request.UserAgent = value; break;

                    default:
                        request.Headers[headerKey] = value;
                        break;
                    }
                }
                request.AuthenticationLevel   = AuthenticationLevel.None;
                request.Credentials           = null;
                request.UseDefaultCredentials = false;
                request.KeepAlive             = true;
                request.Timeout = 1000 * options.TileServerTimeoutSeconds;

                lock (_SyncLock) {
                    if (!_TileServerNameToCookieCollection.TryGetValue(urlValues.Name, out var cookies))
                    {
                        cookies = new CookieCollection();
                        _TileServerNameToCookieCollection.Add(urlValues.Name, cookies);
                    }
                    foreach (Cookie cookie in cookies)
                    {
                        request.CookieContainer.Add(cookie);
                    }
                }

                var forwarded = request.Headers["Forwarded"] ?? "";
                if (forwarded.Length > 0)
                {
                    forwarded = $"{forwarded}, ";
                }
                forwarded = $"{forwarded}for={clientEndpoint}";
                request.Headers["Forwarded"] = forwarded;

                try {
                    using (var response = (HttpWebResponse)request.GetResponse()) {
                        using (var memoryStream = new MemoryStream()) {
                            using (var responseStream = response.GetResponseStream()) {
                                var buffer    = new byte[1024];
                                var bytesRead = 0;
                                do
                                {
                                    bytesRead = responseStream.Read(buffer, 0, buffer.Length);
                                    if (bytesRead > 0)
                                    {
                                        memoryStream.Write(buffer, 0, bytesRead);
                                    }
                                } while(bytesRead > 0);
                            }

                            outcome.ImageBytes = memoryStream.ToArray();
                            displayOutcome.FetchedFromTileServer        = true;
                            displayOutcome.TileServerResponseStatusCode = (int)response.StatusCode;
                        }

                        var cookies = new CookieCollection();
                        foreach (Cookie cookie in response.Cookies)
                        {
                            cookies.Add(cookie);
                        }
                        lock (_SyncLock) {
                            _TileServerNameToCookieCollection[urlValues.Name] = cookies;
                        }
                    }
                } catch (WebException ex) {
                    if (ex.Status == WebExceptionStatus.Timeout)
                    {
                        displayOutcome.TimedOut = true;
                    }
                    else
                    {
                        displayOutcome.WebExceptionErrorMessage = ex.Message;

                        outcome.StatusCode = HttpStatusCode.InternalServerError;
                        if (ex.Response is HttpWebResponse httpResponse)
                        {
                            if (httpResponse.StatusCode != HttpStatusCode.OK)
                            {
                                outcome.StatusCode = httpResponse.StatusCode;
                                displayOutcome.TileServerResponseStatusCode = (int)httpResponse.StatusCode;
                            }
                        }
                    }
                }
            }
        }