internal string HandleHttpFileDownloadRequest(Uri uri, string workingDirectory, string localRelativePath = null) { if (!SarifViewerPackage.IsUnitTesting) { #pragma warning disable VSTHRD108 // Assert thread affinity unconditionally ThreadHelper.ThrowIfNotOnUIThread(); #pragma warning restore VSTHRD108 } bool allow = this._allowedDownloadHosts.Contains(uri.Host); // File needs to be downloaded, prompt for confirmation if host is not already allowed if (!allow) { MessageDialogCommand result = MessageDialog.Show(Resources.ConfirmDownloadDialog_Title, string.Format(Resources.ConfirmDownloadDialog_Message, uri), MessageDialogCommandSet.YesNo, string.Format(Resources.ConfirmDownloadDialog_CheckboxLabel, uri.Host), out bool alwaysAllow); if (result != MessageDialogCommand.No) { allow = true; if (alwaysAllow) { this.AddAllowedDownloadHost(uri.Host); } } } if (allow) { try { workingDirectory = string.IsNullOrWhiteSpace(workingDirectory) ? Path.Combine(Path.GetTempPath(), this.CurrentRunIndex.ToString()) : workingDirectory; return(this.DownloadFile(workingDirectory, uri.ToString(), localRelativePath)); } catch (Exception ex) { VsShellUtilities.ShowMessageBox(ServiceProvider.GlobalProvider, Resources.DownloadFail_DialogMessage + Environment.NewLine + ex.Message, null, // title OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); Trace.WriteLine($"DownloadFile {uri.ToString()} threw exception: {ex.Message}"); } } return(null); }
public bool TryResolveFilePath(int resultId, int runIndex, string uriBaseId, string relativePath, out string resolvedPath) { resolvedPath = null; if (!SarifViewerPackage.IsUnitTesting) { #pragma warning disable VSTHRD108 // Assert thread affinity unconditionally ThreadHelper.ThrowIfNotOnUIThread(); #pragma warning restore VSTHRD108 } if (!this.RunIndexToRunDataCache.TryGetValue(runIndex, out RunDataCache dataCache)) { return(false); } SarifErrorListItem sarifErrorListItem = dataCache.SarifErrors.FirstOrDefault(sarifResult => sarifResult.ResultId == resultId); if (sarifErrorListItem == null) { return(false); } if (dataCache.FileDetails.ContainsKey(relativePath)) { // File contents embedded in SARIF. resolvedPath = this.CreateFileFromContents(dataCache.FileDetails, relativePath); } else { if (uriBaseId != null && dataCache.OriginalUriBasePaths.TryGetValue(uriBaseId, out Uri baseUri) && Uri.TryCreate(baseUri, relativePath, out Uri uri) && uri.IsHttpScheme()) { bool allow = this._allowedDownloadHosts.Contains(uri.Host); // File needs to be downloaded, prompt for confirmation if host is not already allowed if (!allow) { MessageDialogCommand result = MessageDialog.Show(Resources.ConfirmDownloadDialog_Title, string.Format(Resources.ConfirmDownloadDialog_Message, uri), MessageDialogCommandSet.YesNo, string.Format(Resources.ConfirmDownloadDialog_CheckboxLabel, uri.Host), out bool alwaysAllow); if (result != MessageDialogCommand.No) { allow = true; if (alwaysAllow) { this.AddAllowedDownloadHost(uri.Host); } } } if (allow) { try { resolvedPath = this.DownloadFile(sarifErrorListItem, uri.ToString()); } catch (WebException wex) { VsShellUtilities.ShowMessageBox(ServiceProvider.GlobalProvider, Resources.DownloadFail_DialogMessage + Environment.NewLine + wex.Message, null, // title OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return(false); } } } else { string solutionPath = null; DTE2 dte = (DTE2)Package.GetGlobalService(typeof(DTE)); if (dte.Solution != null && dte.Solution.IsOpen) { solutionPath = dte.Solution.FullName; } // User needs to locate file. resolvedPath = this.GetRebaselinedFileName(sarifErrorListItem, uriBaseId, relativePath, dataCache, solutionPath); } if (string.IsNullOrEmpty(resolvedPath) || relativePath.Equals(resolvedPath, StringComparison.OrdinalIgnoreCase)) { return(false); } } // Update all the paths in this run. this.RemapFilePaths(dataCache.SarifErrors, relativePath, resolvedPath); return(true); }
public static void ProcessLogFile(string filePath, Solution solution, string toolFormat = ToolFormat.None, bool promptOnLogConversions = true) { SarifLog log = null; string logText; string outputPath = null; bool saveOutputFile = true; if (toolFormat.MatchesToolFormat(ToolFormat.None)) { logText = File.ReadAllText(filePath); Match match = MatchVersionProperty(logText); if (match.Success) { string inputVersion = match.Groups["version"].Value; if (inputVersion == SarifUtilities.V1_0_0) { // They're opening a v1 log, so we need to transform it. // Ask if they'd like to save the v2 log. MessageDialogCommand response = promptOnLogConversions ? PromptToSaveProcessedLog(Resources.TransformV1_DialogMessage) : MessageDialogCommand.No; if (response == MessageDialogCommand.Cancel) { return; } JsonSerializerSettings settingsV1 = new JsonSerializerSettings() { ContractResolver = SarifContractResolverVersionOne.Instance }; SarifLogVersionOne v1Log = JsonConvert.DeserializeObject <SarifLogVersionOne>(logText, settingsV1); var transformer = new SarifVersionOneToCurrentVisitor(); transformer.VisitSarifLogVersionOne(v1Log); log = transformer.SarifLog; if (response == MessageDialogCommand.Yes) { // Prompt for a location to save the transformed log. outputPath = PromptForFileSaveLocation(Resources.SaveTransformedV1Log_DialogTitle, filePath); if (string.IsNullOrEmpty(outputPath)) { return; } } logText = JsonConvert.SerializeObject(log); } else if (inputVersion != VersionConstants.StableSarifVersion) { // It's an older v2 version, so send it through the pre-release compat transformer. // Ask if they'd like to save the transformed log. MessageDialogCommand response = promptOnLogConversions ? PromptToSaveProcessedLog(string.Format(Resources.TransformPrereleaseV2_DialogMessage, VersionConstants.StableSarifVersion)) : MessageDialogCommand.No; if (response == MessageDialogCommand.Cancel) { return; } log = PrereleaseCompatibilityTransformer.UpdateToCurrentVersion(logText, Formatting.Indented, out logText); if (response == MessageDialogCommand.Yes) { // Prompt for a location to save the transformed log. outputPath = PromptForFileSaveLocation(Resources.SaveTransformedPrereleaseV2Log_DialogTitle, filePath); if (string.IsNullOrEmpty(outputPath)) { return; } } } else { // Since we didn't do any pre-processing, we don't need to write to a temp location. outputPath = filePath; saveOutputFile = false; } } else { // The version property wasn't found within the first 100 characters. // Per the spec, it should appear first in the sarifLog object. VsShellUtilities.ShowMessageBox(SarifViewerPackage.ServiceProvider, Resources.VersionPropertyNotFound_DialogTitle, null, // title OLEMSGICON.OLEMSGICON_QUERY, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return; } } else { // They're opening a non-SARIF log, so we need to convert it. // Ask if they'd like to save the converted log. MessageDialogCommand response = promptOnLogConversions ? PromptToSaveProcessedLog(Resources.ConvertNonSarifLog_DialogMessage) : MessageDialogCommand.No; if (response == MessageDialogCommand.Cancel) { return; } var converter = new ToolFormatConverter(); var sb = new StringBuilder(); using (var input = new MemoryStream(File.ReadAllBytes(filePath))) { var outputTextWriter = new StringWriter(sb); var outputJson = new JsonTextWriter(outputTextWriter); var output = new ResultLogJsonWriter(outputJson); input.Seek(0, SeekOrigin.Begin); converter.ConvertToStandardFormat(toolFormat, input, output); // This is serving as a flush mechanism. output.Dispose(); logText = sb.ToString(); if (response == MessageDialogCommand.Yes) { // Prompt for a location to save the converted log. outputPath = PromptForFileSaveLocation(Resources.SaveConvertedLog_DialogTitle, filePath); } } } if (string.IsNullOrEmpty(outputPath)) { outputPath = Path.GetTempFileName() + ".sarif"; } if (saveOutputFile) { SaveLogFile(outputPath, logText); } if (log == null) { log = JsonConvert.DeserializeObject <SarifLog>(logText); } ProcessSarifLog(log, outputPath, solution, showMessageOnNoResults: promptOnLogConversions); SarifTableDataSource.Instance.BringToFront(); }
public bool TryRebaselineAllSarifErrors(string uriBaseId, string originalFilename) { if (CurrentSarifResult == null) { return(false); } string rebaselinedFile = null; if (FileDetails.ContainsKey(originalFilename)) { // File contents embedded in SARIF. rebaselinedFile = CreateFileFromContents(originalFilename); } else { Uri uri = null; if (Uri.TryCreate(originalFilename, UriKind.Absolute, out uri) && uri.IsHttpScheme()) { bool allow = _allowedDownloadHosts.Contains(uri.Host); // File needs to be downloaded, prompt for confirmation if host is not already allowed if (!allow) { bool alwaysAllow; MessageDialogCommand result = MessageDialog.Show(Resources.ConfirmDownloadDialog_Title, string.Format(Resources.ConfirmDownloadDialog_Message, uri), MessageDialogCommandSet.YesNo, string.Format(Resources.ConfirmDownloadDialog_CheckboxLabel, uri.Host), out alwaysAllow); if (result != MessageDialogCommand.No) { allow = true; if (alwaysAllow) { AddAllowedDownloadHost(uri.Host); } } } if (allow) { rebaselinedFile = DownloadFile(originalFilename); } } else { // User needs to locate file. rebaselinedFile = GetRebaselinedFileName(uriBaseId, originalFilename); } if (String.IsNullOrEmpty(rebaselinedFile) || originalFilename.Equals(rebaselinedFile, StringComparison.OrdinalIgnoreCase)) { return(false); } } // Update all the paths in this result set RemapFileNames(originalFilename, rebaselinedFile); return(true); }
public bool TryRebaselineAllSarifErrors(int runId, string uriBaseId, string originalFilename) { if (CurrentSarifResult == null) { return(false); } RunDataCache dataCache = RunDataCaches[runId]; string rebaselinedFileName = null; if (dataCache.FileDetails.ContainsKey(originalFilename)) { // File contents embedded in SARIF. rebaselinedFileName = CreateFileFromContents(dataCache.FileDetails, originalFilename); } else { if (uriBaseId != null && dataCache.OriginalUriBasePaths.TryGetValue(uriBaseId, out Uri baseUri) && Uri.TryCreate(baseUri, originalFilename, out Uri uri) && uri.IsHttpScheme()) { bool allow = _allowedDownloadHosts.Contains(uri.Host); // File needs to be downloaded, prompt for confirmation if host is not already allowed if (!allow) { MessageDialogCommand result = MessageDialog.Show(Resources.ConfirmDownloadDialog_Title, string.Format(Resources.ConfirmDownloadDialog_Message, uri), MessageDialogCommandSet.YesNo, string.Format(Resources.ConfirmDownloadDialog_CheckboxLabel, uri.Host), out bool alwaysAllow); if (result != MessageDialogCommand.No) { allow = true; if (alwaysAllow) { AddAllowedDownloadHost(uri.Host); } } } if (allow) { try { rebaselinedFileName = DownloadFile(uri.ToString()); } catch (WebException wex) { VsShellUtilities.ShowMessageBox(SarifViewerPackage.ServiceProvider, Resources.DownloadFail_DialogMessage + Environment.NewLine + wex.Message, null, // title OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return(false); } } } else { // User needs to locate file. rebaselinedFileName = GetRebaselinedFileName(uriBaseId, originalFilename, dataCache); } if (String.IsNullOrEmpty(rebaselinedFileName) || originalFilename.Equals(rebaselinedFileName, StringComparison.OrdinalIgnoreCase)) { return(false); } } // Update all the paths in this run RemapFileNames(dataCache.SarifErrors, originalFilename, rebaselinedFileName); return(true); }
public static void ProcessLogFile(string filePath, Solution solution, string toolFormat = ToolFormat.None) { SarifLog log = null; JsonSerializerSettings settingsV2 = new JsonSerializerSettings() { ContractResolver = SarifContractResolver.Instance, }; string logText; if (toolFormat.MatchesToolFormat(ToolFormat.None)) { logText = File.ReadAllText(filePath); string pattern = @"""version""\s*:\s*""1.0.0"""; Match match = Regex.Match(logText, pattern, RegexOptions.Compiled | RegexOptions.Multiline); if (match.Success) { // They're opening a v1 log, so we need to transform it. // Ask if they'd like to save the v2 log. int result = VsShellUtilities.ShowMessageBox(SarifViewerPackage.ServiceProvider, Resources.TransformV1_DialogMessage, null, // title OLEMSGICON.OLEMSGICON_QUERY, OLEMSGBUTTON.OLEMSGBUTTON_YESNOCANCEL, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); MessageDialogCommand response = (MessageDialogCommand)Enum.Parse(typeof(MessageDialogCommand), result.ToString()); if (response == MessageDialogCommand.Cancel) { return; } JsonSerializerSettings settingsV1 = new JsonSerializerSettings() { ContractResolver = SarifContractResolverVersionOne.Instance, }; SarifLogVersionOne v1Log = JsonConvert.DeserializeObject <SarifLogVersionOne>(logText, settingsV1); var transformer = new SarifVersionOneToCurrentVisitor(); transformer.VisitSarifLogVersionOne(v1Log); log = transformer.SarifLog; if (response == MessageDialogCommand.Yes) { // Prompt for a location to save the transformed log. var saveFileDialog = new SaveFileDialog(); saveFileDialog.Title = Resources.SaveTransformedV1Log_DialogTitle; saveFileDialog.Filter = "SARIF log files (*.sarif)|*.sarif"; saveFileDialog.RestoreDirectory = true; filePath = Path.GetFileNameWithoutExtension(filePath) + ".v2.sarif"; saveFileDialog.FileName = Path.GetFileName(filePath); saveFileDialog.InitialDirectory = Path.GetDirectoryName(filePath); if (saveFileDialog.ShowDialog() != DialogResult.OK) { return; } filePath = saveFileDialog.FileName; string error = null; try { File.WriteAllText(filePath, JsonConvert.SerializeObject(log, settingsV2)); } catch (UnauthorizedAccessException) { error = string.Format(Resources.SaveTransformedV1LogFail_Access_DialogMessage, filePath); } catch (SecurityException) { error = string.Format(Resources.SaveTransformedV1LogFail_Access_DialogMessage, filePath); } catch (Exception ex) { error = string.Format(Resources.SaveTransformedV1LogFail_General_Dialog, ex.Message); } if (error != null) { VsShellUtilities.ShowMessageBox(SarifViewerPackage.ServiceProvider, error, null, // title OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); } } } } else { // We have conversion to do var converter = new ToolFormatConverter(); var sb = new StringBuilder(); using (var input = new MemoryStream(File.ReadAllBytes(filePath))) { var outputTextWriter = new StringWriter(sb); var outputJson = new JsonTextWriter(outputTextWriter); var output = new ResultLogJsonWriter(outputJson); input.Seek(0, SeekOrigin.Begin); converter.ConvertToStandardFormat(toolFormat, input, output); // This is serving as a flush mechanism output.Dispose(); logText = sb.ToString(); } } if (log == null) { log = JsonConvert.DeserializeObject <SarifLog>(logText, settingsV2); } ProcessSarifLog(log, filePath, solution); SarifTableDataSource.Instance.BringToFront(); }
public static async Task ProcessLogFileCoreAsync(string filePath, string toolFormat, bool promptOnLogConversions, bool cleanErrors, bool openInEditor) { SarifLog log = null; string logText = null; string outputPath = null; bool saveOutputFile = true; if (toolFormat.MatchesToolFormat(ToolFormat.None)) { await RetryInvokeAsync( async() => { using (var logStreamReader = new StreamReader(filePath, Encoding.UTF8)) { logText = await logStreamReader.ReadToEndAsync().ConfigureAwait(continueOnCapturedContext: false); } }, retryInterval : TimeSpan.FromMilliseconds(300), maxAttemptCount : 5); Match match = MatchVersionProperty(logText); if (match.Success) { string inputVersion = match.Groups["version"].Value; if (inputVersion == SarifUtilities.V1_0_0) { // They're opening a v1 log, so we need to transform it. // Ask if they'd like to save the v2 log. MessageDialogCommand response = promptOnLogConversions ? await PromptToSaveProcessedLogAsync(Resources.TransformV1_DialogMessage).ConfigureAwait(continueOnCapturedContext: false) : MessageDialogCommand.No; if (response == MessageDialogCommand.Cancel) { return; } var settingsV1 = new JsonSerializerSettings() { ContractResolver = SarifContractResolverVersionOne.Instance, }; SarifLogVersionOne v1Log = JsonConvert.DeserializeObject <SarifLogVersionOne>(logText, settingsV1); var transformer = new SarifVersionOneToCurrentVisitor(); transformer.VisitSarifLogVersionOne(v1Log); log = transformer.SarifLog; if (response == MessageDialogCommand.Yes) { // Prompt for a location to save the transformed log. outputPath = await PromptForFileSaveLocationAsync(Resources.SaveTransformedV1Log_DialogTitle, filePath).ConfigureAwait(continueOnCapturedContext: false); if (string.IsNullOrEmpty(outputPath)) { return; } } logText = JsonConvert.SerializeObject(log); } else if (inputVersion != VersionConstants.StableSarifVersion) { // It's an older v2 version, so send it through the pre-release compat transformer. // Ask if they'd like to save the transformed log. MessageDialogCommand response = promptOnLogConversions ? await PromptToSaveProcessedLogAsync(string.Format(Resources.TransformPrereleaseV2_DialogMessage, VersionConstants.StableSarifVersion)).ConfigureAwait(continueOnCapturedContext: false) : MessageDialogCommand.No; if (response == MessageDialogCommand.Cancel) { return; } log = PrereleaseCompatibilityTransformer.UpdateToCurrentVersion(logText, Formatting.Indented, out logText); if (response == MessageDialogCommand.Yes) { // Prompt for a location to save the transformed log. outputPath = await PromptForFileSaveLocationAsync(Resources.SaveTransformedPrereleaseV2Log_DialogTitle, filePath).ConfigureAwait(continueOnCapturedContext: false); if (string.IsNullOrEmpty(outputPath)) { return; } } } else { // Since we didn't do any pre-processing, we don't need to write to a temp location. outputPath = filePath; saveOutputFile = false; } } else { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // The version property wasn't found within the first 100 characters. // Per the spec, it should appear first in the sarifLog object. VsShellUtilities.ShowMessageBox(ServiceProvider.GlobalProvider, Resources.VersionPropertyNotFound_DialogTitle, null, // title OLEMSGICON.OLEMSGICON_QUERY, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); return; } } else { // They're opening a non-SARIF log, so we need to convert it. // Ask if they'd like to save the converted log. MessageDialogCommand response = promptOnLogConversions ? await PromptToSaveProcessedLogAsync(Resources.ConvertNonSarifLog_DialogMessage).ConfigureAwait(continueOnCapturedContext: false) : MessageDialogCommand.No; if (response == MessageDialogCommand.Cancel) { return; } // The converter doesn't have async methods, so spin // up a task to do this. await System.Threading.Tasks.Task.Run(() => { var sb = new StringBuilder(); using (FileStream fileStream = File.OpenRead(filePath)) { using (var outputTextWriter = new StringWriter(sb)) using (var outputJson = new JsonTextWriter(outputTextWriter)) using (var output = new ResultLogJsonWriter(outputJson)) { var converter = new ToolFormatConverter(); converter.ConvertToStandardFormat(toolFormat, fileStream, output); } logText = sb.ToString(); if (response == MessageDialogCommand.Yes) { // Prompt for a location to save the converted log. outputPath = PromptForFileSaveLocationAsync(Resources.SaveConvertedLog_DialogTitle, filePath).Result; } } }).ConfigureAwait(continueOnCapturedContext: false); } if (string.IsNullOrEmpty(outputPath)) { outputPath = Path.GetTempFileName() + ".sarif"; } if (saveOutputFile) { await SaveLogFileAsync(outputPath, logText).ConfigureAwait(continueOnCapturedContext: false); } if (log == null) { log = JsonConvert.DeserializeObject <SarifLog>(logText); } await ProcessSarifLogAsync(log, outputPath, cleanErrors : cleanErrors, openInEditor : openInEditor).ConfigureAwait(continueOnCapturedContext: false); }