/// <summary>
        /// Parse the Data inline image.
        /// </summary>
        private HtmlImageInfo ReadDataUri(string src)
        {
            if (DataUri.TryCreate(src, out DataUri dataUri))
            {
                Size size;
                knownContentType.TryGetValue(dataUri.Mime, out ImagePartType type);
                var ipart = mainPart.AddImagePart(type);
                using (var outputStream = ipart.GetStream(FileMode.Create))
                {
                    outputStream.Write(dataUri.Data, 0, dataUri.Data.Length);

                    outputStream.Seek(0L, SeekOrigin.Begin);
                    size = GetImageSize(outputStream);
                }

                return(new HtmlImageInfo()
                {
                    Source = src,
                    ImagePartId = mainPart.GetIdOfPart(ipart),
                    Size = size
                });
            }

            return(null);
        }
        //____________________________________________________________________
        //
        // Public Functionality

        /// <summary>
        /// Download the remote or local image located at the specified url.
        /// </summary>
        public HtmlImageInfo Download(string imageUri)
        {
            if (prefetchedImages.Contains(imageUri))
            {
                return(prefetchedImages[imageUri]);
            }

            if (DataUri.IsWellFormed(imageUri)) // data inline, encoded in base64
            {
                return(ReadDataUri(imageUri));
            }

            return(DownloadRemoteImage(imageUri));
        }
Esempio n. 3
0
        /// <summary>
        /// Parse an instance of the Data URI scheme.
        /// </summary>
        /// <param name="uri">The inline Data URI to parse.</param>
        /// <param name="result">When this method returns, contains a DataUri constructed
        /// from <paramref name="uri"/>. This parameter is passed uninitialized.</param>
        /// <returns>A <see cref="Boolean"/> value that is true if the DataUri was
        /// successfully created; otherwise, false.</returns>
        public static bool TryCreate(string uri, out DataUri result)
        {
            // expected format: data:[<MIME-type>][;charset=<encoding>][;base64],<data>
            // The encoding is indicated by ;base64. If it's present the data is encoded as base64. Without it the data (as a sequence of octets)
            // is represented using ASCII encoding for octets inside the range of safe URL characters and using the standard %xx hex encoding
            // of URLs for octets outside that range. If <MIME-type> is omitted, it defaults to text/plain;charset=US-ASCII.
            // (As a shorthand, the type can be omitted but the charset parameter supplied.)
            // Some browsers (Chrome, Opera, Safari, Firefox) accept a non-standard ordering if both ;base64 and ;charset are supplied,
            // while Internet Explorer requires that the charset's specification must precede the base64 token.
            // http://en.wikipedia.org/wiki/Data_URI_scheme

            // We will stick for IE compliance for the moment...

            Match match = dataUriRegex.Match(uri);

            result = null;

            if (!match.Success)
            {
                return(false);
            }

            byte[]   rawData;
            string   mime;
            Encoding charSet = Encoding.ASCII;

            // if mime is omitted, set default value as it stands in the norm
            if (match.Groups["mime"].Length == 0)
            {
                mime = "text/plain";
            }
            else
            {
                mime = match.Groups["mime"].Value;
            }

            if (match.Groups["charset"].Length > 0)
            {
                try
                {
                    charSet = Encoding.GetEncoding(match.Groups["charset"].Value);
                }
                catch (ArgumentException)
                {
                    // charSet was not recognized
                    return(false);
                }
            }

            // is it encoded in base64?
            if (match.Groups["base64"].Length > 0)
            {
                // be careful that the raw data is encoded for url (standard %xx hex encoding)
                string base64 = HttpUtility.HtmlDecode(match.Groups["data"].Value);

                try
                {
                    rawData = Convert.FromBase64String(base64);
                }
                catch (FormatException)
                {
                    // Base64 data is invalid
                    return(false);
                }
            }
            else
            {
                // the <data> represents some text (like html snippet) and must be decoded.
                string raw = HttpUtility.UrlDecode(match.Groups["data"].Value);
                try
                {
                    // we convert back to UTF-8 for easier processing later and to have a "referential" encoding
                    rawData = Encoding.Convert(charSet, Encoding.UTF8, charSet.GetBytes(raw));
                }
                catch (ArgumentException)
                {
                    // UTF-8 Encoded data is invalid
                    return(false);
                }
            }

            result = new DataUri(mime, rawData);
            return(true);
        }