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); } }
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 }); }
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 }); }
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()); }