Beispiel #1
0
        /// <summary>
        /// Get the specified asset from the pak file
        /// </summary>
        public Stream GetAsset(string id, string assetPath)
        {
            var pkg = this.m_configuration.Repository.GetRepository().Get(id, null);

            if (pkg == null)
            {
                throw new KeyNotFoundException($"Package {id} not found");
            }

            // Open the package
            var unpack      = pkg.Unpack();
            var assetObject = unpack.Assets.FirstOrDefault(o => o.Name == $"{assetPath}");

            if (assetObject == null)
            {
                throw new FileNotFoundException();
            }


            RestOperationContext.Current.OutgoingResponse.ContentType = assetObject.MimeType;
            byte[] content;
            if (assetObject.Content is byte[] bytea)
            {
                content = bytea;
            }
            else if (assetObject.Content is String stra)
            {
                content = System.Text.Encoding.UTF8.GetBytes(stra);
            }
            else if (assetObject.Content is XElement xela)
            {
                content = System.Text.Encoding.UTF8.GetBytes(xela.ToString());
            }
            else if (assetObject.Content is AppletAssetHtml html)
            {
                content = System.Text.Encoding.UTF8.GetBytes(html.Html.ToString());
            }
            else
            {
                throw new InvalidOperationException("Cannot render this type of data");
            }

            if (Encoding.UTF8.GetString(content as byte[], 0, 4) == "LZIP")
            {
                using (var ms = new MemoryStream(content as byte[]))
                    using (var ls = new SharpCompress.Compressors.LZMA.LZipStream(ms, SharpCompress.Compressors.CompressionMode.Decompress))
                    {
                        var oms = new MemoryStream();
                        ls.CopyTo(oms);
                        oms.Seek(0, SeekOrigin.Begin);
                        return(oms);
                    }
            }
            else
            {
                return(new MemoryStream(content));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Compresses the Application and writes it into the Resource file.
        /// Also generates some code related to the Application launching.
        /// </summary>
        /// <param name="writer"></param>
        /// <returns></returns>
        private static string CompressApplication(ResourceWriter writer)
        {
            //this is what the application is called in the resource file.
            const string APPLICATION_NAME = "app";

            //generates a temporary file to compress into.
            FileStream stream = File.Open(outputFile + "temp_c.dat", FileMode.Create);

            //opens the input file (which has been merged with some other dlls).
            FileStream stream2 = File.OpenRead(outputFile + "_temp");

            //sets the mode to follow when it generates the code. It swaps between G-Zip and LZMA.
            string mode;
            long   appSize = stream2.Length;
            Stream gStream = null;

            if (gzOr7z)
            {
                // lzipstream
                gStream = new SharpCompress.Compressors.LZMA.LZipStream(stream, SharpCompress.Compressors.CompressionMode.Compress);
                mode    = "SharpCompress.Compressors.LZMA.LZipStream(memStr, SharpCompress.Compressors.CompressionMode.Decompress)";
            }
            else
            {
                //gzip
                gStream = new GZipStream(stream, CompressionLevel.Optimal);
                mode    = "GZipStream(memStr, CompressionMode.Decompress)";
                // gStream = stream;
                //mode = $"MemoryStream({Convert.ToInt32(stream2.Length)})";
            }

            //compresses, not the most efficient way to compress, I should buffer it, but it doesn't matter.
            while (stream2.Position < stream2.Length)
            {
                gStream.WriteByte((byte)stream2.ReadByte());
            }

            //closes each of the streams.
            gStream.Close();
            stream.Close(); //closing this one manually because some compression libraries don't have the wrapper close the stream passed into it.
            stream2.Close();

            //add the resource to the file.
            // writer.AddResource(APPLICATION_NAME, File.ReadAllBytes(outputFile + "temp_c.dat"));
            var s = Encoding.UTF8.GetString(File.ReadAllBytes(outputFile + "temp_c.dat"));

            appSize = s.Length;
            writer.AddResource(APPLICATION_NAME, s);



            //add the code.
            string code = manager.GetString("AppMethod").Replace("%appname%", APPLICATION_NAME).Replace("%appsize%", "" + appSize).Replace("%mode%", mode);

            return(code);
        }
Beispiel #3
0
 /// <summary>
 /// Compress content
 /// </summary>
 internal static byte[] CompressContent(object content)
 {
     using (var ms = new MemoryStream())
     {
         using (var cs = new SharpCompress.Compressors.LZMA.LZipStream(ms, SharpCompress.Compressors.CompressionMode.Compress))
         {
             byte[] data = content as byte[];
             if (data == null)
             {
                 data = System.Text.Encoding.UTF8.GetBytes(content.ToString());
             }
             cs.Write(data, 0, data.Length);
         }
         return(ms.ToArray());
     }
 }
        /// <summary>
        /// Render asset content
        /// </summary>
        public byte[] RenderAssetContent(AppletAsset asset, string preProcessLocalization = null, bool staticScriptRefs = true, bool allowCache = true, IDictionary <String, String> bindingParameters = null)
        {
            // TODO: This method needs to be cleaned up since it exists from the old/early OpenIZ days
            // First, is there an object already
            byte[] cacheObject = null;
            string assetPath   = String.Format("{0}?lang={1}", asset.ToString(), preProcessLocalization);

            var cacheKey = $"{assetPath};{String.Join(";", bindingParameters?.Select(o => $"{o.Key}={o.Value}") ?? new string[0] { })}";

            if (allowCache && this.CachePages && s_cache.TryGetValue(cacheKey, out cacheObject))
            {
                return(cacheObject);
            }

            // Resolve content
            var content = asset.Content;

            if (content == null && this.Resolver != null)
            {
                content = this.Resolver(asset);
            }

            if (content is String) // Content is a string
            {
                // Inject CSP
                if (asset.MimeType == "text/javascript" || asset.MimeType == "application/json")
                {
                    var retVal = content as String;
                    if (bindingParameters != null)
                    {
                        retVal = this.m_bindingRegex.Replace(retVal, (m) => bindingParameters.TryGetValue(m.Groups[1].Value, out string v) ? v : m.ToString());
                    }
                    cacheObject = Encoding.UTF8.GetBytes(retVal);
                    if (allowCache)
                    {
                        s_cache.TryAdd(cacheKey, cacheObject);
                    }
                    return(cacheObject);
                }
                else
                {
                    return(Encoding.UTF8.GetBytes(content as String));
                }
            }
            else if (content is byte[]) // Content is a binary asset
            {
                // is the content compressed?
                if (Encoding.UTF8.GetString(content as byte[], 0, 4) == "LZIP")
                {
                    using (var ms = new MemoryStream(content as byte[]))
                        using (var ls = new SharpCompress.Compressors.LZMA.LZipStream(new NonDisposingStream(ms), SharpCompress.Compressors.CompressionMode.Decompress))
                            using (var oms = new MemoryStream())
                            {
                                byte[] buffer = new byte[2048];
                                int    br     = 1;
                                while (br > 0)
                                {
                                    br = ls.Read(buffer, 0, 2048);
                                    oms.Write(buffer, 0, br);
                                }

                                content = oms.ToArray();
                                if (allowCache)
                                {
                                    s_cache.TryAdd(cacheKey, content as byte[]);
                                }
                                return(content as byte[]);
                            }
                }
                else
                {
                    return(content as byte[]);
                }
            }
            else if (content is XElement) // Content is XML
            {
                using (MemoryStream ms = new MemoryStream())
                    using (XmlWriter xw = XmlWriter.Create(ms))
                    {
                        (content as XElement).WriteTo(xw);
                        xw.Flush();
                        ms.Flush();
                        return(ms.ToArray());
                    }
            }
            else if (content is AppletAssetHtml) // Content is HTML
            {
                // Is the content HTML?
                var sourceAsset = content as AppletAssetHtml;
                var htmlAsset   = new AppletAssetHtml()
                {
                    Html   = new XElement(sourceAsset.Html),
                    Layout = sourceAsset.Layout,
                    Script = new List <AssetScriptReference>(sourceAsset.Script),
                    Titles = new List <LocaleString>(sourceAsset.Titles),
                    Style  = new List <string>(sourceAsset.Style)
                };
                XElement htmlContent = null;

                if (htmlAsset.Static)
                {
                    htmlContent = htmlAsset.Html as XElement;
                }
                else
                {
                    // Type of tag to render basic content
                    switch (htmlAsset.Html.Name.LocalName)
                    {
                    case "html":     // The content is a complete HTML page
                    {
                        htmlContent = htmlAsset.Html as XElement;
                        var headerInjection = this.GetInjectionHeaders(asset, htmlContent.DescendantNodes().OfType <XElement>().Any(o => o.Name == xs_xhtml + "ui-view"));

                        // STRIP - SanteDBJS references
                        var xel  = htmlContent.Descendants().OfType <XElement>().Where(o => o.Name == xs_xhtml + "script" && o.Attribute("src")?.Value.Contains("SanteDB") == true).ToArray();
                        var head = htmlContent.DescendantNodes().OfType <XElement>().FirstOrDefault(o => o.Name == xs_xhtml + "head");
                        if (head == null)
                        {
                            head = new XElement(xs_xhtml + "head");
                            htmlContent.Add(head);
                        }

                        head.Add(headerInjection.Where(o => !head.Elements(o.Name).Any(e => (e.Attributes("src") != null && (e.Attributes("src") == o.Attributes("src"))) || (e.Attributes("href") != null && (e.Attributes("href") == o.Attributes("href"))))));

                        // Inject any business rules as static refs
                        var body = htmlContent.DescendantNodes().OfType <XElement>().FirstOrDefault(o => o.Name == xs_xhtml + "body");
                        if (body != null)
                        {
                            body.Add(
                                this.SelectMany(o => o.Assets.Where(a => a.Name.StartsWith("rules/"))).Select(o => new XElement(xs_xhtml + "script", new XAttribute("src", $"/{o.Manifest.Info.Id}/{o.Name}"), new XAttribute("type", "text/javascript"), new XAttribute("nonce", bindingParameters.TryGetValue("csp_nonce", out string nonce) ? nonce : ""), new XText("// Script reference")))
                                );
                        }
                        //                            head.Add(headerInjection);
                        break;
                    }

                    case "body":     // The content is an HTML Body element, we must inject the HTML header
                    {
                        htmlContent = htmlAsset.Html as XElement;

                        // Inject special headers
                        var headerInjection = this.GetInjectionHeaders(asset, htmlContent.DescendantNodes().OfType <XElement>().Any(o => o.Name == xs_xhtml + "ui-view"));

                        // Render the bundles
                        var bodyElement = htmlAsset.Html as XElement;

                        htmlContent = new XElement(xs_xhtml + "html", new XAttribute("ng-app", asset.Name), new XElement(xs_xhtml + "head", headerInjection), bodyElement);
                    }
                    break;

                    default:
                    {
                        if (String.IsNullOrEmpty(htmlAsset.Layout))
                        {
                            htmlContent = htmlAsset.Html as XElement;
                        }
                        else
                        {
                            // Get the layout
                            var layoutAsset = this.ResolveAsset(htmlAsset.Layout, relativeAsset: asset);
                            if (layoutAsset == null)
                            {
                                throw new FileNotFoundException(String.Format("Layout asset {0} not found", htmlAsset.Layout));
                            }

                            using (MemoryStream ms = new MemoryStream(this.RenderAssetContent(layoutAsset, preProcessLocalization, bindingParameters: bindingParameters)))
                                htmlContent = XDocument.Load(ms).FirstNode as XElement;


                            // Find the <!--#include virtual="content" --> tag
                            var contentNode = htmlContent.DescendantNodes().OfType <XComment>().SingleOrDefault(o => o.Value.Trim() == "#include virtual=\"content\"");
                            if (contentNode != null)
                            {
                                contentNode.AddAfterSelf(htmlAsset.Html as XElement);
                                contentNode.Remove();
                            }

                            // Injection headers
                            var headerInjection = this.GetInjectionHeaders(asset, htmlContent.DescendantNodes().OfType <XElement>().Any(o => o.Name == xs_xhtml + "ui-view"));
                            var headElement     = (htmlContent.Element(xs_xhtml + "head") as XElement);
                            headElement?.Add(headerInjection.Where(o => !headElement.Elements(o.Name).Any(e => (e.Attributes("src") != null && (e.Attributes("src") == o.Attributes("src"))) || (e.Attributes("href") != null && (e.Attributes("href") == o.Attributes("href"))))));
                        }
                    }
                    break;
                    } // switch


                    // Now process SSI directives - <!--#include virtual="XXXXXXX" -->
                    var includes = htmlContent.DescendantNodes().OfType <XComment>().Where(o => o?.Value?.Trim().StartsWith("#include virtual=\"") == true).ToList();
                    foreach (var inc in includes)
                    {
                        String assetName = inc.Value.Trim().Substring(18); // HACK: Should be a REGEX
                        if (assetName.EndsWith("\""))
                        {
                            assetName = assetName.Substring(0, assetName.Length - 1);
                        }
                        if (assetName == "content")
                        {
                            continue;
                        }
                        var includeAsset = this.ResolveAsset(assetName, relativeAsset: asset);
                        if (includeAsset == null)
                        {
                            inc.AddAfterSelf(new XElement(xs_xhtml + "strong", new XText(String.Format("{0} NOT FOUND", assetName))));
                            inc.Remove();
                        }
                        else
                        {
                            using (MemoryStream ms = new MemoryStream(this.RenderAssetContent(includeAsset, preProcessLocalization, bindingParameters: bindingParameters)))
                            {
                                try
                                {
                                    var xel = XDocument.Load(ms).Elements().First() as XElement;
                                    if (xel.Name == xs_xhtml + "html")
                                    {
                                        inc.AddAfterSelf(xel.Element(xs_xhtml + "body").Elements());
                                    }
                                    else
                                    {
                                        //var headerInjection = this.GetInjectionHeaders(includeAsset);

                                        //var headElement = htmlContent.Element(xs_xhtml + "head");
                                        //headElement?.Add(headerInjection.Where(o => !headElement.Elements(o.Name).Any(e => (e.Attributes("src") != null && (e.Attributes("src") == o.Attributes("src"))) || (e.Attributes("href") != null && (e.Attributes("href") == o.Attributes("href"))))));

                                        inc.AddAfterSelf(xel);
                                    }
                                    inc.Remove();
                                }
                                catch (Exception e)
                                {
                                    throw new XmlException($"Error in Asset: {includeAsset}", e);
                                }
                            }
                        }
                    }

                    // Re-write
                    foreach (var itm in htmlContent.DescendantNodes().OfType <XElement>().SelectMany(o => o.Attributes()).Where(o => o.Value.StartsWith("~")))
                    {
                        itm.Value = String.Format("/{0}/{1}", asset.Manifest.Info.Id, itm.Value.Substring(2));
                        //itm.Value = itm.Value.Replace(APPLET_SCHEME, this.AppletBase).Replace(ASSET_SCHEME, this.AssetBase).Replace(DRAWABLE_SCHEME, this.DrawableBase);
                    }

                    // Render Title
                    var headTitle = htmlContent.DescendantNodes().OfType <XElement>().FirstOrDefault(o => o.Name == xs_xhtml + "head");
                    var title     = htmlAsset.GetTitle(preProcessLocalization);
                    if (headTitle != null && !String.IsNullOrEmpty(title))
                    {
                        headTitle.Add(new XElement(xs_xhtml + "title", new XText(title)));
                    }
                }

                // Render out the content
                using (StringWriter sw = new StringWriter())
                    using (XmlWriter xw = XmlWriter.Create(sw, new XmlWriterSettings()
                    {
                        OmitXmlDeclaration = true
                    }))
                    {
                        htmlContent.WriteTo(xw);
                        xw.Flush();

                        String retVal = sw.ToString();
                        if (!String.IsNullOrEmpty(preProcessLocalization))
                        {
                            var assetString = ApplicationServiceContext.Current.GetService <ILocalizationService>().GetStrings(preProcessLocalization);
                            retVal = this.m_localizationRegex.Replace(retVal, (m) => assetString.FirstOrDefault(o => o.Key == m.Groups[1].Value).Value ?? m.Groups[1].Value);
                        }

                        // Binding objects
                        if (bindingParameters != null)
                        {
                            retVal = this.m_bindingRegex.Replace(retVal, (m) => bindingParameters.TryGetValue(m.Groups[1].Value, out string v) ? v : m.ToString());
                        }
                        var byteData = Encoding.UTF8.GetBytes(retVal);
                        // Add to cache
                        if (allowCache)
                        {
                            s_cache.TryAdd(cacheKey, byteData);
                        }

                        return(byteData);
                    }
            }
            else if (content is AppletAssetVirtual virtualContent) // Virtual asset
            {
                if (!s_cache.TryGetValue(assetPath, out byte[] data))