-
Notifications
You must be signed in to change notification settings - Fork 1
Handle absolute paths #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,4 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using System; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using System; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using System.Collections.Generic; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using System.IO; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using System.Linq; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -14,10 +14,23 @@ public class CatalogPlugin : PluginBase | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public static void Process(CatalogOptions options) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //Validate and display arguments | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var currentDirectory = Directory.GetCurrentDirectory(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var fileEntries = Directory.GetFiles(currentDirectory, options.InputPath, SearchOption.AllDirectories); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| string[] fileEntries = { }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //Absolute path | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Path.IsPathFullyQualified(options.InputPath)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| string path = options.InputPath.Replace("\\", "/"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| int pos = path.LastIndexOf('/'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (File.Exists(options.InputPath) || Directory.Exists(options.InputPath)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fileEntries = Directory.GetFiles(path[..pos], path[(pos + 1)..], SearchOption.AllDirectories); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+23
to
+27
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| string path = options.InputPath.Replace("\\", "/"); | |
| int pos = path.LastIndexOf('/'); | |
| if (File.Exists(options.InputPath) || Directory.Exists(options.InputPath)) | |
| fileEntries = Directory.GetFiles(path[..pos], path[(pos + 1)..], SearchOption.AllDirectories); | |
| string directoryPath; | |
| string searchPattern; | |
| // If the input path is an existing directory, search for all .txt files under it. | |
| if (Directory.Exists(options.InputPath)) | |
| { | |
| directoryPath = options.InputPath; | |
| searchPattern = "*.txt"; | |
| } | |
| else | |
| { | |
| directoryPath = Path.GetDirectoryName(options.InputPath) ?? string.Empty; | |
| searchPattern = Path.GetFileName(options.InputPath); | |
| } | |
| if (!string.IsNullOrEmpty(directoryPath) && | |
| !string.IsNullOrEmpty(searchPattern) && | |
| Directory.Exists(directoryPath)) | |
| { | |
| fileEntries = Directory.GetFiles(directoryPath, searchPattern, SearchOption.AllDirectories); | |
| } |
Copilot
AI
Jan 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When File.Exists or Directory.Exists returns false on line 26, the condition fails but fileEntries remains as an empty array without any error message or alternative handling. This silent failure makes debugging difficult for users who provide an absolute path that doesn't exist, as they won't get the "No .txt files found" error until line 34, which may be misleading.
| if (File.Exists(options.InputPath) || Directory.Exists(options.InputPath)) | |
| fileEntries = Directory.GetFiles(path[..pos], path[(pos + 1)..], SearchOption.AllDirectories); | |
| if (File.Exists(options.InputPath) || Directory.Exists(options.InputPath)) | |
| { | |
| fileEntries = Directory.GetFiles(path[..pos], path[(pos + 1)..], SearchOption.AllDirectories); | |
| } | |
| else | |
| { | |
| WriteError($"Input path {options.InputPath} was not found."); | |
| return; | |
| } |
Copilot
AI
Jan 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The path splitting logic doesn't correctly handle all absolute path scenarios. If InputPath is an absolute directory path like "C:\Users\data" (without a wildcard pattern), this code splits it into directory="C:\Users" and pattern="data", which will search for files matching "data" pattern in "C:\Users" instead of searching all files in "C:\Users\data". The logic should check if InputPath is a directory and handle it differently from a file pattern.
| string path = options.InputPath.Replace("\\", "/"); | |
| int pos = path.LastIndexOf('/'); | |
| if (File.Exists(options.InputPath) || Directory.Exists(options.InputPath)) | |
| fileEntries = Directory.GetFiles(path[..pos], path[(pos + 1)..], SearchOption.AllDirectories); | |
| // If the input is an existing directory, search all files under it. | |
| if (Directory.Exists(options.InputPath)) | |
| { | |
| fileEntries = Directory.GetFiles(options.InputPath, "*", SearchOption.AllDirectories); | |
| } | |
| // If the input is an existing file, process just that file. | |
| else if (File.Exists(options.InputPath)) | |
| { | |
| fileEntries = new[] { options.InputPath }; | |
| } | |
| // Otherwise treat the input as an absolute path containing a file pattern. | |
| else | |
| { | |
| var directory = Path.GetDirectoryName(options.InputPath); | |
| var pattern = Path.GetFileName(options.InputPath); | |
| if (string.IsNullOrEmpty(directory)) | |
| { | |
| directory = currentDirectory; | |
| } | |
| fileEntries = Directory.GetFiles(directory, pattern, SearchOption.AllDirectories); | |
| } |
Copilot
AI
Jan 18, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic for handling absolute paths has several issues. First, if the path doesn't exist (line 26 check fails), fileEntries will remain as an empty array but execution continues, which differs from the relative path behavior. Second, the path splitting logic assumes the InputPath contains at least one path separator, but a fully qualified path like "C:" would cause LastIndexOf to return -1, leading to incorrect range operations on line 27. Third, if InputPath is a directory path (not a file pattern), the split logic will incorrectly separate the directory name from its parent.
| string path = options.InputPath.Replace("\\", "/"); | |
| int pos = path.LastIndexOf('/'); | |
| if (File.Exists(options.InputPath) || Directory.Exists(options.InputPath)) | |
| fileEntries = Directory.GetFiles(path[..pos], path[(pos + 1)..], SearchOption.AllDirectories); | |
| } | |
| //Relative path | |
| else | |
| fileEntries = Directory.GetFiles(currentDirectory, options.InputPath, SearchOption.AllDirectories); | |
| // If it's an existing file, just process that single file | |
| if (File.Exists(options.InputPath)) | |
| { | |
| fileEntries = new[] { options.InputPath }; | |
| } | |
| // If it's an existing directory, search all files within it | |
| else if (Directory.Exists(options.InputPath)) | |
| { | |
| fileEntries = Directory.GetFiles(options.InputPath, "*", SearchOption.AllDirectories); | |
| } | |
| else | |
| { | |
| // Treat as a pattern with directory and file mask components | |
| var directoryPart = Path.GetDirectoryName(options.InputPath); | |
| var patternPart = Path.GetFileName(options.InputPath); | |
| // If there is no directory part, the pattern is not rooted anywhere valid | |
| if (string.IsNullOrEmpty(directoryPart)) | |
| { | |
| WriteError($"Input path {options.InputPath} was not found."); | |
| return; | |
| } | |
| if (!Directory.Exists(directoryPart)) | |
| { | |
| WriteError($"Input folder {directoryPart} was not found."); | |
| return; | |
| } | |
| // If no explicit pattern, default to all files | |
| if (string.IsNullOrEmpty(patternPart)) | |
| { | |
| patternPart = "*"; | |
| } | |
| fileEntries = Directory.GetFiles(directoryPart, patternPart, SearchOption.AllDirectories); | |
| } | |
| } | |
| //Relative path | |
| else | |
| { | |
| fileEntries = Directory.GetFiles(currentDirectory, options.InputPath, SearchOption.AllDirectories); | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The absolute path handling lacks validation for path traversal attacks. An absolute path could potentially include ".." sequences that allow accessing files outside intended directories. Consider using Path.GetFullPath to normalize and validate the path before processing.