Skip to content

Instantly share code, notes, and snippets.

@tohsa

tohsa/stepOne.cs Secret

Last active January 19, 2019 03:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tohsa/2d906942f8712abdfc7df72128479c0a to your computer and use it in GitHub Desktop.
Save tohsa/2d906942f8712abdfc7df72128479c0a to your computer and use it in GitHub Desktop.
// 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