Example #1
0
        private string PromptForResolvedPath(SarifErrorListItem sarifErrorListItem, string pathFromLogFile)
        {
            // Opening the OpenFileDialog causes the TreeView to lose focus,
            // which in turn causes the TreeViewItem selection to be unpredictable
            // (because the selection event relies on the TreeViewItem focus.)
            // We'll save the element which currently has focus and then restore
            // focus after the OpenFileDialog is closed.
            var elementWithFocus = Keyboard.FocusedElement as UIElement;

            string fileName       = Path.GetFileName(pathFromLogFile);
            var    openFileDialog = new OpenFileDialog
            {
                Title            = string.Format(Resources.PromptForResolvedPathDialogTitle, pathFromLogFile),
                InitialDirectory = sarifErrorListItem != null?Path.GetDirectoryName(sarifErrorListItem.LogFilePath) : null,
                                       Filter           = $"{fileName}|{fileName}",
                                       RestoreDirectory = true,
            };

            try
            {
                bool?dialogResult = openFileDialog.ShowDialog();

                return(dialogResult == true ? openFileDialog.FileName : null);
            }
            finally
            {
                elementWithFocus?.Focus();
            }
        }
        // return false means cannot resolve local file and will use embedded file.
        internal bool VerifyFileWithArtifactHash(SarifErrorListItem sarifErrorListItem, string pathFromLogFile, RunDataCache dataCache, string resolvedPath, string embeddedTempFilePath, out string newResolvedPath)
        {
            newResolvedPath = null;

            if (string.IsNullOrEmpty(resolvedPath))
            {
                // cannot find corresponding file in local, then use embedded file
                newResolvedPath = embeddedTempFilePath;
                return(true);
            }

            if (!dataCache.FileDetails.TryGetValue(pathFromLogFile, out ArtifactDetailsModel fileData))
            {
                // has no embedded file, return the path resolved till now
                newResolvedPath = resolvedPath;
                return(true);
            }

            string fileHash = this.GetFileHash(this._fileSystem, resolvedPath);

            if (fileHash.Equals(fileData.Sha256Hash, StringComparison.OrdinalIgnoreCase))
            {
                // found a file in file system which has same hashcode as embeded content.
                newResolvedPath = resolvedPath;
                return(true);
            }

            bool hasEmbeddedContent = !string.IsNullOrEmpty(embeddedTempFilePath);
            ResolveEmbeddedFileDialogResult dialogResult = this._promptForEmbeddedFileDelegate(sarifErrorListItem.LogFilePath, hasEmbeddedContent, this.userDialogPreference);

            switch (dialogResult)
            {
            case ResolveEmbeddedFileDialogResult.None:
                // dialog is cancelled.
                newResolvedPath = null;
                return(false);

            case ResolveEmbeddedFileDialogResult.OpenEmbeddedFileContent:
                newResolvedPath = embeddedTempFilePath;
                return(true);

            case ResolveEmbeddedFileDialogResult.OpenLocalFileFromSolution:
                newResolvedPath = resolvedPath;
                return(true);

            case ResolveEmbeddedFileDialogResult.BrowseAlternateLocation:
                // if returns null means user cancelled the open file dialog.
                newResolvedPath = this._promptForResolvedPathDelegate(sarifErrorListItem, pathFromLogFile);
                return(!string.IsNullOrEmpty(newResolvedPath));

            default:
                return(false);
            }
        }
Example #3
0
        private void UpdateDataContext(SarifErrorListItem sarifErrorListItem)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            if (this.Control.DataContext is SarifErrorListItem previousSarifErrorListItem)
            {
                previousSarifErrorListItem.Disposed -= this.SarifErrorListItem_Disposed;
            }

            // Resetting the data context to null causes the correct tab in the SARIF explorer
            // window to be selected when the data context is set back to a non-null value.
            this.Control.DataContext = null;
            this.Control.DataContext = sarifErrorListItem;

            if (sarifErrorListItem != null)
            {
                sarifErrorListItem.Disposed += this.SarifErrorListItem_Disposed;
            }

            this.UpdateSelectionList(sarifErrorListItem);
        }
        internal string GetFilePathFromHttp(SarifErrorListItem sarifErrorListItem, string uriBaseId, RunDataCache dataCache, string pathFromLogFile)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            Uri uri = null;

            if ((uriBaseId != null &&
                 dataCache.OriginalUriBasePaths.TryGetValue(uriBaseId, out Uri baseUri) &&
                 Uri.TryCreate(baseUri, pathFromLogFile, out uri) &&
                 uri.IsHttpScheme()) ||

                // if result location uri is an absolute http url
                (Uri.TryCreate(pathFromLogFile, UriKind.Absolute, out uri) &&
                 uri.IsHttpScheme()))
            {
                return(this.HandleHttpFileDownloadRequest(
                           VersionControlParserFactory.ConvertToRawFileLink(uri),
                           sarifErrorListItem.WorkingDirectory));
            }

            return(null);
        }
Example #5
0
        internal string DownloadFile(SarifErrorListItem sarifErrorListItem, string fileUrl)
        {
            if (string.IsNullOrEmpty(fileUrl))
            {
                return(fileUrl);
            }

            var sourceUri = new Uri(fileUrl);

            string destinationFile      = Path.Combine(sarifErrorListItem.WorkingDirectory, sourceUri.LocalPath.Replace('/', '\\').TrimStart('\\'));
            string destinationDirectory = Path.GetDirectoryName(destinationFile);

            Directory.CreateDirectory(destinationDirectory);

            if (!this._fileSystem.FileExists(destinationFile))
            {
                using (var client = new WebClient())
                {
                    client.DownloadFile(sourceUri, destinationFile);
                }
            }

            return(destinationFile);
        }
Example #6
0
        // Internal rather than private for unit testability.
        internal string GetRebaselinedFileName(SarifErrorListItem sarifErrorListItem, string uriBaseId, string pathFromLogFile, RunDataCache dataCache, string solutionFullPath = null)
        {
            string originalPath = pathFromLogFile;
            Uri    relativeUri  = null;

            if (!string.IsNullOrEmpty(uriBaseId) && Uri.TryCreate(pathFromLogFile, UriKind.Relative, out relativeUri))
            {
                // If the relative file path is relative to an unknown root,
                // we need to strip the leading slash, so that we can relate
                // the file path to an arbitrary remapped disk location.
                if (pathFromLogFile.StartsWith("/"))
                {
                    pathFromLogFile = pathFromLogFile.Substring(1);
                }

                if (dataCache.RemappedUriBasePaths.ContainsKey(uriBaseId))
                {
                    pathFromLogFile = new Uri(dataCache.RemappedUriBasePaths[uriBaseId], pathFromLogFile).LocalPath;
                }
                else if (dataCache.OriginalUriBasePaths.ContainsKey(uriBaseId))
                {
                    pathFromLogFile = new Uri(dataCache.OriginalUriBasePaths[uriBaseId], pathFromLogFile).LocalPath;
                }

                if (this._fileSystem.FileExists(pathFromLogFile))
                {
                    return(pathFromLogFile);
                }
            }

            // Traverse our remappings and see if we can
            // make rebaseline from existing data
            foreach (Tuple <string, string> remapping in dataCache.RemappedPathPrefixes)
            {
                string remapped;
                if (!string.IsNullOrEmpty(remapping.Item1))
                {
                    remapped = pathFromLogFile.Replace(remapping.Item1, remapping.Item2);
                }
                else
                {
                    remapped = Path.Combine(remapping.Item2, pathFromLogFile);
                }

                if (this._fileSystem.FileExists(remapped))
                {
                    return(remapped);
                }
            }

            string resolvedPath = null;

            if (!string.IsNullOrEmpty(solutionFullPath))
            {
                this.TryResolveFilePathFromSolution(solutionFullPath, originalPath, this._fileSystem, out resolvedPath);
            }

            if (resolvedPath == null)
            {
                resolvedPath = this._promptForResolvedPathDelegate(sarifErrorListItem, pathFromLogFile);
            }

            if (resolvedPath == null)
            {
                return(pathFromLogFile);
            }

            string fullPathFromLogFile = pathFromLogFile;

            if (Uri.TryCreate(pathFromLogFile, UriKind.Absolute, out Uri absoluteUri))
            {
                fullPathFromLogFile = Path.GetFullPath(pathFromLogFile);
            }
            else
            {
                if (!fullPathFromLogFile.StartsWith("/"))
                {
                    fullPathFromLogFile = "/" + fullPathFromLogFile;
                }
            }

            string commonSuffix = GetCommonSuffix(fullPathFromLogFile.Replace("/", @"\"), resolvedPath);

            if (commonSuffix == null)
            {
                return(pathFromLogFile);
            }

            // Trim the common suffix from both paths, and add a remapping that converts
            // one prefix to the other.
            string originalPrefix = fullPathFromLogFile.Substring(0, fullPathFromLogFile.Length - commonSuffix.Length);
            string resolvedPrefix = resolvedPath.Substring(0, resolvedPath.Length - commonSuffix.Length);

            int uriBaseIdEndIndex = resolvedPath.IndexOf(originalPath.Replace("/", @"\"));

            if (relativeUri != null && uriBaseIdEndIndex >= 0)
            {
                // If we could determine the uriBaseId substitution value, then add it to the map.
                dataCache.RemappedUriBasePaths[uriBaseId] = new Uri(resolvedPath.Substring(0, uriBaseIdEndIndex), UriKind.Absolute);
            }
            else
            {
                // If there's no relativeUri/uriBaseId pair or we couldn't determine the uriBaseId value,
                // map the original prefix to the new prefix.
                dataCache.RemappedPathPrefixes.Add(new Tuple <string, string>(originalPrefix, resolvedPrefix));
            }

            return(resolvedPath);
        }
Example #7
0
        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);
        }
 internal static bool CanNavigateTo(SarifErrorListItem sarifError)
 {
     throw new NotImplementedException();
 }
        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);
            }

            string solutionPath = GetSolutionPath(
                (DTE2)Package.GetGlobalService(typeof(DTE)),
                ((IComponentModel)Package.GetGlobalService(typeof(SComponentModel))).GetService <IVsFolderWorkspaceService>());

            // File contents embedded in SARIF.
            bool   hasHash = dataCache.FileDetails.TryGetValue(relativePath, out ArtifactDetailsModel model) && !string.IsNullOrEmpty(model?.Sha256Hash);
            string embeddedTempFilePath = this.CreateFileFromContents(dataCache.FileDetails, relativePath);

            try
            {
                resolvedPath = this.GetFilePathFromHttp(sarifErrorListItem, uriBaseId, dataCache, relativePath);
            }
            catch (WebException)
            {
                // failed to download the file
                return(false);
            }

            if (string.IsNullOrEmpty(resolvedPath))
            {
                // resolve path, existing file in local disk
                resolvedPath = this.GetRebaselinedFileName(
                    uriBaseId: uriBaseId,
                    pathFromLogFile: relativePath,
                    dataCache: dataCache,
                    workingDirectory: sarifErrorListItem.WorkingDirectory,
                    solutionFullPath: solutionPath);
            }

            // verify resolved file with artifact's Hash
            if (hasHash)
            {
                string currentResolvedPath = resolvedPath;
                if (!this.VerifyFileWithArtifactHash(sarifErrorListItem, relativePath, dataCache, currentResolvedPath, embeddedTempFilePath, out resolvedPath))
                {
                    return(false);
                }
            }

            if (string.IsNullOrEmpty(resolvedPath))
            {
                // User needs to locate file.
                resolvedPath = this._promptForResolvedPathDelegate(sarifErrorListItem, relativePath);
            }

            if (!string.IsNullOrEmpty(resolvedPath))
            {
                // save resolved path to mapping
                if (!this.SaveResolvedPathToUriBaseMapping(uriBaseId, relativePath, relativePath, resolvedPath, dataCache))
                {
                    resolvedPath = relativePath;
                }
            }

            if (string.IsNullOrEmpty(resolvedPath) || relativePath.Equals(resolvedPath, StringComparison.OrdinalIgnoreCase))
            {
                resolvedPath = relativePath;
                return(false);
            }

            // Update all the paths in this run.
            this.RemapFilePaths(dataCache.SarifErrors, relativePath, resolvedPath);
            return(true);
        }