-
-
Save tohsa/2d906942f8712abdfc7df72128479c0a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this is an example for building the tree for a single page and it was part of my original proof of | |
// concept code for my team so it's not the prettiest in the world. I added comments to help you. | |
static void Main(string[] args) | |
{ | |
string rootDirectory = @"some root directory containing a bunch of pages"; | |
string pathToRoot = @"path to a single markup page for testing"; | |
var parser = new AspxParser(rootDirectory); | |
// every entry in the below Sets must be absolute (resolved) | |
var unexaminedReferences = new HashSet<string>() { ResolveFilePath(pathToRoot, rootDirectory) }; | |
var examinedReferences = new HashSet<string>() { }; | |
// here is the start of the main tree traversal - its not really a BFS though because I just want to fully | |
// explore the tree and dont care too much about order - HashSet instead of list makes the traversal unordered | |
// The root of the main tree is the file containing the aspx page. All nodes in the tree are subcontrols on that page | |
// or subcontrols of subcontrols etc. | |
while (unexaminedReferences.Count != 0) | |
{ | |
var unexaminedReference = unexaminedReferences.First(); | |
// parse the file that the current node in our main traversal represents | |
AspxParseResult aspxTree = parser.Parse(unexaminedReference); | |
// each file is actually another tree so here is another tree traversal where we examine the parse tree | |
// of the current file and find references to other files. This traversal uses a standard DepthFirstSearch | |
var discoveredReferences = GetListOfReferences(aspxTree.RootNode); | |
foreach (var reference in discoveredReferences) | |
{ | |
var normalizedFilePath = ResolveFilePath(reference, rootDirectory, unexaminedReference); | |
if (!examinedReferences.Contains(normalizedFilePath)) | |
{ | |
unexaminedReferences.Add(normalizedFilePath); | |
} | |
} | |
examinedReferences.Add(unexaminedReference); | |
unexaminedReferences.Remove(unexaminedReference); | |
} | |
foreach (var reference in examinedReferences) | |
{ | |
Console.WriteLine(reference); | |
} | |
Console.WriteLine(); | |
} | |
// this is very brittle right now - resolve virutal directories by reading directly out of IIS in the future | |
static string ResolveFilePath(string filePath, string rootDirectory, string curFilePath = "") | |
{ | |
if (filePath.Length == 0) | |
return filePath; | |
var result = filePath.Replace(@"\", @"/"); | |
if (filePath.StartsWith(rootDirectory)) | |
{ | |
// result is already correct | |
} | |
// relative path to current directory e.g. "REDACTED.ascx" or "/"REDACTED.ascx" | |
else if (filePath.First() == '/' || char.IsLetterOrDigit(filePath.First())) | |
{ | |
if (string.IsNullOrWhiteSpace(curFilePath)) | |
throw new Exception("Problem resolving file name."); | |
var directory = Path.GetDirectoryName(curFilePath); | |
// TODO: fix this - we should probably use the correct backslash for everything based on operating system | |
directory = directory.Replace(@"\", @"/"); | |
result = filePath.First() == '/' | |
? directory + filePath | |
: directory + @"/" + filePath; ; | |
} | |
else if (filePath.StartsWith(@"../REDACTED/")) | |
{ | |
result = rootDirectory + @"Redacted/Web" + filePath.Substring(@"../Redacted".Length); | |
} | |
else if (filePath.StartsWith(@"~/REDACTED")) | |
{ | |
result = rootDirectory + @"/REDACTED/Web" + filePath.Substring(@"~/REDACTED".Length); | |
} | |
//etc. | |
return result; | |
} | |
static HashSet<string> GetListOfReferences(AspxNode root) | |
{ | |
var result = new HashSet<string>(32); // TODO profile starting capacity | |
PopulateReferenceList(root, result); | |
return result; | |
} | |
static void PopulateReferenceList(AspxNode root, HashSet<string> result) | |
{ | |
if (root is AspxDirective aspxDirective && aspxDirective.Name.ToLower() == "register") | |
{ | |
if (aspxDirective.Attributes.ContainsKey("Src")) | |
{ | |
result.Add(aspxDirective.Attributes["Src"]); | |
} | |
} | |
foreach (var child in root.Children) | |
{ | |
PopulateReferenceList(child, result); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment