public void AddFile(string filename, byte[] bytes)
        {
#if false
            // Help in debugging checksum errors.
            if (filename == "References\\DataSources.json")
            {
                var path = @"C:\temp\a1.json";
                var str  = JsonNormalizer.Normalize(Encoding.UTF8.GetString(bytes));
                bytes = Encoding.UTF8.GetBytes(str);
                File.WriteAllBytes(path, bytes);
            }
#endif

            if (filename.EndsWith(ChecksumName, StringComparison.OrdinalIgnoreCase))
            {
                // Ignore the checksum file, else we'd have a circular reference.
                return;
            }

            if (filename.EndsWith(".json", StringComparison.OrdinalIgnoreCase) ||
                filename.EndsWith(".sarif", StringComparison.OrdinalIgnoreCase))
            {
                AddJsonFile(filename, bytes);
            }
            else
            {
                _files.Add(filename, bytes);
            }
        }
Esempio n. 2
0
        public void WriteAllJson <T>(string subdir, FilePath filename, T obj)
        {
            var text = JsonSerializer.Serialize <T>(obj, Utilities._jsonOpts);

            text = JsonNormalizer.Normalize(text);
            WriteAllText(subdir, filename, text);
        }
        internal static FileEntry ToFile <T>(FileKind kind, T value)
        {
            var filename = FileEntry.GetFilenameForKind(kind);

            string output;

            if (Utilities.IsYamlFile(filename))
            {
                StringWriter tw = new StringWriter();
                YamlPocoSerializer.CanonicalWrite(tw, value);
                output = tw.ToString();
            }
            else
            {
                var jsonStr = JsonSerializer.Serialize(value, Utilities._jsonOpts);

                output = JsonNormalizer.Normalize(jsonStr);
            }

            var bytes = Encoding.UTF8.GetBytes(output);

            return(new FileEntry {
                Name = filename, RawBytes = bytes
            });
        }
Esempio n. 4
0
        internal static FileEntry ToFile <T>(FileKind kind, T value)
        {
            var filename = FileEntry.GetFilenameForKind(kind);

            var jsonStr = JsonSerializer.Serialize(value, Utilities._jsonOpts);

            jsonStr = JsonNormalizer.Normalize(jsonStr);

            var bytes = Encoding.UTF8.GetBytes(jsonStr);

            return(new FileEntry {
                Name = filename, RawBytes = bytes
            });
        }
Esempio n. 5
0
 public void WriteAllJson <T>(string subdir, FilePath filename, T obj)
 {
     if (Utilities.IsYamlFile(filename))
     {
         using (var tw = new StringWriter())
         {
             YamlPocoSerializer.CanonicalWrite(tw, obj);
             WriteAllText(subdir, filename, tw.ToString());
         }
     }
     else
     {
         var text = JsonSerializer.Serialize <T>(obj, Utilities._jsonOpts);
         text = JsonNormalizer.Normalize(text);
         WriteAllText(subdir, filename, text);
     }
 }
        // Write out to a directory (this shards it)
        public static void SaveAsSource(CanvasDocument app, string directory2, ErrorContainer errors)
        {
            var dir = new DirectoryWriter(directory2);

            dir.DeleteAllSubdirs();

            // Shard templates, parse for default values
            var templateDefaults = new Dictionary <string, ControlTemplate>();

            foreach (var template in app._templates.UsedTemplates)
            {
                var filename = $"{template.Name}_{template.Version}.xml";
                dir.WriteAllXML(PackagesDir, filename, template.Template);
                if (!ControlTemplateParser.TryParseTemplate(app._templateStore, template.Template, app._properties.DocumentAppType, templateDefaults, out _, out _))
                {
                    throw new NotSupportedException($"Unable to parse template file {template.Name}");
                }
            }

            // Also add Screen and App templates (not xml, constructed in code on the server)
            GlobalTemplates.AddCodeOnlyTemplates(app._templateStore, templateDefaults, app._properties.DocumentAppType);

            var importedComponents = app.GetImportedComponents();

            foreach (var control in app._screens)
            {
                string controlName = control.Key;
                var    isTest      = controlName == AppTestControlName;
                var    subDir      = isTest ? TestDir : CodeDir;

                WriteTopParent(dir, app, control.Key, control.Value, subDir);
            }

            foreach (var control in app._components)
            {
                string controlName = control.Key;
                app._templateStore.TryGetTemplate(controlName, out var templateState);

                bool isImported = importedComponents.Contains(templateState.TemplateOriginalName);
                var  subDir     = (isImported) ? ComponentPackageDir : ComponentCodeDir;
                WriteTopParent(dir, app, control.Key, control.Value, subDir);
            }

            // Write out control templates at top level, skipping component templates which are written alongside components
            var nonComponentControlTemplates = app._templateStore.Contents.Where(kvp => !(kvp.Value.IsComponentTemplate ?? false)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);

            dir.WriteAllJson("", "ControlTemplates.json", nonComponentControlTemplates);

            if (app._checksum != null)
            {
                app._checksum.ClientBuildDetails = _buildVerJson;
                dir.WriteAllJson(EntropyDir, FileKind.Checksum, app._checksum);
            }

            if (app._appCheckerResultJson != null)
            {
                dir.WriteAllJson(EntropyDir, FileKind.AppCheckerResult, app._appCheckerResultJson);
            }

            foreach (var file in app._assetFiles.Values)
            {
                dir.WriteAllBytes(AssetsDir, file.Name, file.RawBytes);
            }

            if (app._logoFile != null)
            {
                dir.WriteAllBytes(AssetsDir, app._logoFile.Name, app._logoFile.RawBytes);
            }

            if (app._themes != null)
            {
                dir.WriteAllJson(CodeDir, "Themes.json", app._themes);
            }

            if (app._resourcesJson != null)
            {
                dir.WriteAllJson(AssetsDir, "Resources.json", app._resourcesJson);
            }

            WriteDataSources(dir, app, errors);

            // Loose files.
            foreach (FileEntry file in app._unknownFiles.Values)
            {
                // Standardize the .json files so they're determinsitc and comparable
                if (file.Name.EndsWith(".json", StringComparison.OrdinalIgnoreCase))
                {
                    ReadOnlyMemory <byte> span = file.RawBytes;
                    var je      = JsonDocument.Parse(span).RootElement;
                    var jsonStr = JsonNormalizer.Normalize(je);
                    dir.WriteAllText(OtherDir, file.Name, jsonStr);
                }
                else
                {
                    dir.WriteAllBytes(OtherDir, file.Name, file.RawBytes);
                }
            }

            var manifest = new CanvasManifestJson
            {
                FormatVersion = CurrentSourceVersion,
                Properties    = app._properties,
                Header        = app._header,
                PublishInfo   = app._publishInfo,
                ScreenOrder   = app._screenOrder
            };

            dir.WriteAllJson("", FileKind.CanvasManifest, manifest);

            if (app._connections != null)
            {
                dir.WriteAllJson(ConnectionDir, FileKind.Connections, app._connections);
            }

            if (app._libraryReferences != null)
            {
                dir.WriteAllJson("", FileKind.ComponentReferences, app._libraryReferences);
            }

            dir.WriteAllJson(EntropyDir, FileKind.Entropy, app._entropy);
        }
        // Get a hash for the MsApp file.
        // First pass adds file/hash to comp.
        // Second pass checks hash equality and removes files from comp.
        // AFter second pass, comp should be 0. any files in comp were missing from 2nd pass.
        public static string Test(string pathToZip, TextWriter log, Dictionary <string, string> comp, bool first)
        {
            StringBuilder sb = new StringBuilder();

            log.WriteLine($">> {pathToZip}");
            using (var z = ZipFile.OpenRead(pathToZip))
            {
                foreach (ZipArchiveEntry e in z.Entries.OrderBy(x => x.FullName))
                {
                    if (e.Name.EndsWith(ChecksumMaker.ChecksumName))
                    {
                        continue;
                    }
                    string str;

                    // Compute a "smart" hash. Tolerant to whitespace in Json serialization.
                    if (e.FullName.EndsWith(".json", StringComparison.OrdinalIgnoreCase) || e.FullName.EndsWith(".sarif", StringComparison.OrdinalIgnoreCase))
                    {
                        var je = e.ToJson();
                        str = JsonNormalizer.Normalize(je);
                    }
                    else
                    {
                        var bytes = e.ToBytes();
                        str = Convert.ToBase64String(bytes);
                    }

                    // Do easy diffs
                    {
                        if (first)
                        {
                            comp.Add(e.FullName, str);
                        }
                        else
                        {
                            string otherContents;
                            if (comp.TryGetValue(e.FullName, out otherContents))
                            {
                                if (otherContents != str)
                                {
                                    // Fail! Mismatch
                                    Console.WriteLine("FAIL: hash mismatch: " + e.FullName);

                                    // Write out normalized form. Easier to spot the diff.
                                    File.WriteAllText(@"c:\temp\a1.json", otherContents);
                                    File.WriteAllText(@"c:\temp\b1.json", str);

                                    // For debugging. Help find exactly where the difference is.
                                    for (int i = 0; i < otherContents.Length; i++)
                                    {
                                        if (i >= str.Length)
                                        {
                                            break;
                                        }
                                        if (otherContents[i] != str[i])
                                        {
                                        }
                                    }
                                }
                                else
                                {
                                    // success
                                }
                                comp.Remove(e.FullName);
                            }
                            else
                            {
                                // Missing file!
                                Console.WriteLine("FAIL: 2nd has added file: " + e.FullName);
                            }
                        }
                    }


                    var hash = str.GetHashCode().ToString();
                    log.WriteLine($"{e.FullName} ({hash})");

                    sb.Append($"{e.FullName},{hash};");
                }
            }
            log.WriteLine();

            return(sb.ToString());
        }