#!perl -w

use strict;

# How far into directories should the program probe?
my($LinkDirDepthLimit) = 15;

main();



# ===========================================================================
sub main
{
	my($Count, @Results) = LinkDir("C:\\Windows\\Favorites");
	my($Line);
	foreach $Line (@Results)
	{
		print $Line;
	}
}


# ===========================================================================
# LinkDir
#
# Arguments: Directory name and current depth
#            Can omit depth, it's used internally for smart indenting.
#
# Returns: The number of links found and an array of HTML code
#          The HTML code can be just printed in a simple foreach loop         
#
# LinkDir is recursive.  (Yippee).  It stops digging after $LinkDirDepthLimit levels.
sub LinkDir($, $)
{
	local *THISDIR; # This sucker is recursive, so scoping the directory pointer is key
	my($DirName, $Depth) = @_;
	if(!defined $Depth) { $Depth = 0; }
	my($FileName);
	my(@Lines);
	my($ChildLinks) = 0;

	my($Title) = ($DirName =~ /([^\\]+)$/o);

	if($Title eq "ActiveChannel")
	{ # ACTIVE CHANNEL? EEEEEEW
		return 0, @Lines;
	}

	if($Depth > $LinkDirDepthLimit)
	{ # This deep?  I'm suspicious that something isn't cool.
		return 0, @Lines;
	}
	




	if(!opendir(THISDIR, $DirName))
	{
		print STDERR "Unable to open directory '$DirName' because of $!\n";
		return 0, @Lines;
	}
	my(@Files) = sort readdir(THISDIR);
	closedir(THISDIR);

	my(@FilesTry);
	my(@DirsTry);

	foreach $FileName (@Files)
	{
		if($FileName =~ /^\.\.?$/o) { next; } # Skip . and ..
		my($FullFileName) = $DirName."\\".$FileName;

		if(-d $FullFileName)
		{
			push @DirsTry, $FullFileName;
		}
		else
		{
			push @FilesTry, $FullFileName;
		}
	}

	foreach $FileName (@DirsTry)
	{
		my($SubChildLinks, @ChildLines) = LinkDir($FileName, $Depth + 1);
		push @Lines, @ChildLines;
		$ChildLinks += $SubChildLinks;
	}

	foreach $FileName (@FilesTry)
	{
		my($Line) = ProcessFile($FileName, $Depth + 1);
		if(defined $Line)
		{
			push @Lines, $Line;
			$ChildLinks++;
		}
	}

	my(@RetLines);

	if($ChildLinks != 0)
	{
		push @RetLines, Indenter($Depth)."<DT><H3>$Title</H3>\n\n";
		push @RetLines, Indenter($Depth)."<DL>\n\n";
		push @RetLines, @Lines;
		push @RetLines, Indenter($Depth)."</DL>\n\n";
		
	}

	return $ChildLinks, @RetLines;
}


# ===========================================================================
#
# ProcessFile
#
# Arguments: Filename (full!) to file to scan and depth in tree.
#
# Returns: A string of the URL found, or undef if none is found
#
# called by LinkDir
sub ProcessFile($, $)
{
	my($FileName, $Depth) = @_;

	my($Title) = ($FileName =~ /([^\\]+)\.url/o);
	
	if(!defined $Title) { return undef; } # No URL extension?  Skip that.

	if(!open(FILE, $FileName))
	{
		print STDERR "Unable to open file '$FileName' because of $!\n";
		return undef;
	}

	my($Line);

	while($Line = <FILE>)
	{
		chomp $Line;
		my($URL) = ($Line =~ /^URL=(.+)$/o);

		if(!defined $URL) { next; } # Not this line?  Skip
		if($URL =~ /^file:\/\/.:\\/) { next; } # Skip local hard drive links

		close(FILE);
		return Indenter($Depth)."<DT><A HREF=\"$URL\">$Title</A>\n\n";
	}

	close(FILE);
	return undef;
}

# ===========================================================================
# Indenter
#
# Arguments: a number
#
# Indenter returns an indent of spaces.
sub Indenter($)
{
	return "  " x ($_[0] * 4);
}
