public int GetFileIndex( ArtifactLocation fileLocation, bool addToFilesTableIfNotPresent = true, OptionallyEmittedData dataToInsert = OptionallyEmittedData.None, Encoding encoding = null) { if (fileLocation == null) { throw new ArgumentNullException(nameof(fileLocation)); } if (this.Artifacts?.Count == 0) { if (!addToFilesTableIfNotPresent) { return(-1); } } if (_fileToIndexMap == null) { InitializeFileToIndexMap(); } if (fileLocation.Uri == null) { // We only have a file index, so just return it. return(fileLocation.Index); } // Strictly speaking, some elements that may contribute to a files table // key are case sensitive, e.g., everything but the schema and protocol of a // web URI. We don't have a proper comparer implementation that can handle // all cases. For now, we cover the Windows happy path, which assumes that // most URIs in log files are file paths (which are case-insensitive) // // Tracking item for an improved comparer: // https://github.com/Microsoft/sarif-sdk/issues/973 // When we perform a files table look-up, only the uri and uriBaseId // are relevant; these properties together comprise the unique identity // of the file object. The file index, of course, does not relate to the // file identity. We consciously exclude the properties bag as well. // We will normalize the input fileLocation.Uri to make URIs more consistent // throughout the emitted log. fileLocation.Uri = new Uri(UriHelper.MakeValidUri(fileLocation.Uri.OriginalString), UriKind.RelativeOrAbsolute); var filesTableKey = new ArtifactLocation { Uri = fileLocation.Uri, UriBaseId = fileLocation.UriBaseId }; if (!_fileToIndexMap.TryGetValue(filesTableKey, out int fileIndex)) { if (addToFilesTableIfNotPresent) { this.Artifacts = this.Artifacts ?? new List <Artifact>(); fileIndex = this.Artifacts.Count; string mimeType = Writers.MimeType.DetermineFromFileExtension(filesTableKey.Uri.ToString()); var fileData = Artifact.Create( filesTableKey.Uri, dataToInsert, mimeType: mimeType, encoding); fileData.Location = fileLocation; this.Artifacts.Add(fileData); _fileToIndexMap[filesTableKey] = fileIndex; } else { // We did not find the item. The call was not configured to add the entry. // Return the default value that indicates the item isn't present. fileIndex = -1; } } fileLocation.Index = fileIndex; return(fileIndex); }
public Artifact(Microsoft.CodeAnalysis.Sarif.Artifact artifact) { File = artifact.Location.Uri.ToString(); Size = artifact.Length; }
public static Artifact Create( Uri uri, OptionallyEmittedData dataToInsert = OptionallyEmittedData.None, Encoding encoding = null, HashData hashData = null, IFileSystem fileSystem = null) { if (uri == null) { throw new ArgumentNullException(nameof(uri)); } fileSystem = fileSystem ?? new FileSystem(); var artifact = new Artifact() { Encoding = encoding?.WebName, }; string mimeType = SarifWriters.MimeType.DetermineFromFileExtension(uri); // Attempt to persist file contents and/or compute file hash and persist // this information to the log file. In the event that there is some issue // accessing the file, for example, due to ACLs applied to a directory, // we currently swallow these exceptions without populating any requested // data or putting a notification in the log file that a problem // occurred. Something to discuss moving forward. try { bool workTodo = dataToInsert.HasFlag(OptionallyEmittedData.Hashes) || dataToInsert.HasFlag(OptionallyEmittedData.TextFiles) || dataToInsert.HasFlag(OptionallyEmittedData.BinaryFiles); if (!workTodo || !uri.IsAbsoluteUri || !uri.IsFile || !fileSystem.FileExists(uri.LocalPath)) { return(artifact); } string filePath = uri.LocalPath; if (dataToInsert.HasFlag(OptionallyEmittedData.BinaryFiles) && SarifWriters.MimeType.IsBinaryMimeType(mimeType)) { artifact.Contents = GetEncodedFileContents(fileSystem, filePath, mimeType, encoding); } if (dataToInsert.HasFlag(OptionallyEmittedData.TextFiles) && SarifWriters.MimeType.IsTextualMimeType(mimeType)) { artifact.Contents = GetEncodedFileContents(fileSystem, filePath, mimeType, encoding); } if (dataToInsert.HasFlag(OptionallyEmittedData.Hashes)) { HashData hashes = hashData ?? HashUtilities.ComputeHashes(filePath); artifact.Hashes = new Dictionary <string, string> { { "md5", hashes.MD5 }, { "sha-1", hashes.Sha1 }, { "sha-256", hashes.Sha256 }, }; } } catch (Exception e) when(e is IOException || e is UnauthorizedAccessException) { } return(artifact); }
public bool ValueEquals(Artifact other) => ValueComparer.Equals(this, other);
public void Artifact_DeserializeMultipleFileRoles() { Artifact actual = JsonConvert.DeserializeObject("{\"roles\":[\"responseFile\",\"resultFile\"],\"mimeType\":\"text/x-csharp\"}", typeof(Artifact)) as Artifact; actual.Roles.Should().Be(ArtifactRoles.ResponseFile | ArtifactRoles.ResultFile); }
public void Artifact_DeserializeSingleFileRole() { Artifact actual = JsonConvert.DeserializeObject("{\"roles\":[\"analysisTarget\"],\"mimeType\":\"text/x-csharp\"}", typeof(Artifact)) as Artifact; actual.Roles.Should().Be(ArtifactRoles.AnalysisTarget); }
public void Artifact_Create_NullUri() { Action action = () => { Artifact.Create(null, OptionallyEmittedData.None); }; action.Should().Throw <ArgumentNullException>(); }