#!/usr/bin/perl
#
# SDUtil is only use by SDClone, not for a standalone use...
# You don't have to modify this script...
#
####################################################################

#################################################
$mainDir="/mp3share";    		        # directory to find files to share
$followLink="true";				# unset to stop follow links
$Trigger="dccserv";				# trigger to use (your nick is also a trigger). NO SPACE ALLOWED
$useMOTD="true";                                # enable/disable "Message Of The Day" in your list, it will appears just
$noUnderscore="true";                           # convert _ to space in filenames in your list (not on disk !)
$MOTDfile="sdclone-motd.txt";                   # MOTD file, load from where we also put our list
$useZIP="true";		        		# true zip your list, false leave it as a text file
$listShowSize="true";                           # Build your list with filesize show or hidden
$listChars=100;                                     # Define how many "----" we put in our list
                                                # use for "!trigger afilename.test ---------- 12m", see your list for a real example
#$cfgFile="sdclone.cfg";				# filename to save our config
#$lstFile="sdque.cfg";				# filename to save our que
$Ver="1.0";                                 # version number
$Author="dccserv";                              # hey it's just me :-)
$buildingList=0;				# set to 1 if we are building list
$newList="";
$zipList="";					# to keep the zip file name
$oldList="";					# save in cfg to clean the list when building a new one
$listShowInfo="true";
%internalList=();		# hold values pointing to files
%externalList=();		# hold values for the list itself (the one send to other)
#@sd_buffer=();                  # our buffer for output
@MOTD=();                               # for loading MOTD
$mlist1="";
$mlist2="";
$MOTDL=0;
$mainCount=0;
@zipinfo=();

# finding homepath taken from xdcc 1.3.3.pl
open (FIND, "ls -d ~ |");
@test = <FIND>;
close (FIND);
chop($test[0]);
$myhomepath = $test[0]."/.xchat/sdclone/";       # v1.1 sdclone locate now in ~/.xchat/sdclone
chomp($myhomepath);
$mlist1=$myhomepath."listmake";
$mlist2=$myhomepath."listready";
if (open(LISTIN,"<".$mlist1))
        {
        my $list = <LISTIN>;
        my @lister = split(';;;;',$list);
        $mainDir=$lister[0];
        $useMOTD=$lister[1];
        $MOTDfile=$lister[2];
        $followLink=$lister[3];
        $Trigger=$lister[4];
        $useZIP=$lister[5];
        $oldList=$lister[6];
        $newList=$lister[7];
        $noUnderscore=$lister[8];
        $listShowSize=$lister[9];
        $listChars=$lister[10];
        $stuck1=$lister[11];
        $stuck2=$lister[12];
        $stuck3=$lister[13];
        &sd_mtask_build_list;
        close(LISTIN);
        }
  else  {
        print("SDUtil v$Ver by $Author init...\n");
        print("FATAL ERROR: SDUtil isn't a standalone application.\n");
        exit;
        }

sub sd_get_file_information
# return information about a file
# on enter File
# on exit File information
{
my $SDFileTag='"'.shift(@_).'"';
my $infoget = `file $SDFileTag`;      # take info from file linux cmd
my @finf=split ":",$infoget,0;     # parse info taken from file
$infoget=@finf[1];                 # now we have the info into $infoget
print("$infoget \n");
return $infoget;
}

sub sd_load_motd
# Use to load a file to use as MOTD
# \r\n is add to everylines to help windows reading
{
$MOTDL=0;
while (@MOTD > 0)  { pop @MOTD; }     # clear the table
if (open(fileOut,"<".$myhomepath.$MOTDfile))
        {
        while (!eof(fileOut))   { push @MOTD, <fileOut>; }
        my $count = @MOTD;
        for (my $kkk=0; $kkk < $count; $kkk++)
                {
	  chomp($MOTD[$kkk]);
	  chomp($MOTD[$kkk]);
	  $MOTD[$kkk]=$MOTD[$kkk]."\r\n";
                }
        close(fileOut);
        }
$MOTDL=@MOTD;
}

# the byte_converter function comes from xdcc1.3.3.pl
# Modify to make it compatible with xdcc1.3.3 script witch is a good utility script. I just dislike the way it share files
# Modify again to correct bug of region dependant divisor (. & ,)
sub sd_byte_converter
{
my $line = shift(@_);
my $sdtotmegsize2 = $line;
my $sdbegin="";
my $sdend="";
my $test = 100 / 3;           # English = 33.333333... -> support for . div countries
                              # French = 33,333333...  -> support for , div countries
                              # Other countries, add your support yourself
my $isPoint = "false";
if (index($test,".") >0)	{ $isPoint = "true"; }
if ($sdtotmegsize2 > 1000000000000000000000) {
$sdtotmegsize2 = $sdtotmegsize2 / 1000000000000000000000;
if ( $isPoint eq "true")
	{
	$sdtotmegsize2 =~ /(.*)\.(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
else	{
	$sdtotmegsize2 =~ /(.*)\,(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
$sdtotmegsize2 = "$sdbegin.$sdend"." Yottabytes";
} elsif ($sdtotmegsize2 > 1000000000000000000000) {
$sdtotmegsize2 = $sdtotmegsize2 / 1000000000000000000000;
if ( $isPoint eq "true")
	{
	$sdtotmegsize2 =~ /(.*)\.(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
else	{
	$sdtotmegsize2 =~ /(.*)\,(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
$sdtotmegsize2 = "$sdbegin.$sdend"." Zettabytes";
} elsif ($sdtotmegsize2 > 1000000000000000000) {
$sdtotmegsize2 = $sdtotmegsize2 / 1000000000000000000;
if ( $isPoint eq "true")
	{
	$sdtotmegsize2 =~ /(.*)\.(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
else	{
	$sdtotmegsize2 =~ /(.*)\,(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
$sdtotmegsize2 = "$sdbegin.$sdend"." Exabytes";
} elsif ($sdtotmegsize2 > 1000000000000000) {
$sdtotmegsize2 = $sdtotmegsize2 / 1000000000000000;
if ( $isPoint eq "true")
	{
	$sdtotmegsize2 =~ /(.*)\.(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
else	{
	$sdtotmegsize2 =~ /(.*)\,(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
$sdtotmegsize2 = "$sdbegin.$sdend"." Petabytes";
} elsif ($sdtotmegsize2 > 1000000000000) {
$sdtotmegsize2 = $sdtotmegsize2 / 1000000000000;
if ( $isPoint eq "true")
	{
	$sdtotmegsize2 =~ /(.*)\.(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
else	{
	$sdtotmegsize2 =~ /(.*)\,(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
$sdtotmegsize2 = "$sdbegin.$sdend"."T";
} elsif ($sdtotmegsize2 > 1000000000) {
$sdtotmegsize2 = $sdtotmegsize2 / 1000000000;
if ( $isPoint eq "true")
	{
	$sdtotmegsize2 =~ /(.*)\.(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
else	{
	$sdtotmegsize2 =~ /(.*)\,(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
$sdtotmegsize2 = "$sdbegin.$sdend"."G";
} elsif ($sdtotmegsize2 > 1000000) {
$sdtotmegsize2 = $sdtotmegsize2 / 1000000;
if ( $isPoint eq "true")
	{
	$sdtotmegsize2 =~ /(.*)\.(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
else	{
	$sdtotmegsize2 =~ /(.*)\,(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
$sdtotmegsize2 = "$sdbegin.$sdend"."M";
} elsif ($sdtotmegsize2 > 1000) {
$sdtotmegsize2 = $sdtotmegsize2 / 1000;
if ( $isPoint eq "true")
	{
	$sdtotmegsize2 =~ /(.*)\.(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
else	{
	$sdtotmegsize2 =~ /(.*)\,(.*)/;
	$sdbegin = $1;
	$sdend = (substr ($2, 0, 1));
	}
$sdtotmegsize2 = "$sdbegin.$sdend"."k";
} else {
$sdtotmegsize2 = $sdtotmegsize2."b";
}
return $sdtotmegsize2;
}

sub formatFilename
# on enter @_ is the filename
# on exit the filename with _ convert to space if needed
{
my $orig=shift(@_);
my $new=join " ", split("_",$orig);
if ($noUnderscore eq "true")    { $orig = $new; }
return $orig;
}

sub sd_mtask_build_list
# Really build the list
{
        if ($useMOTD eq "true")   { &sd_load_motd; }
	$totalFiles=0;
	$totalDir=0;
	$totalKB=0;
	my $L_mark1=time;   # get the time to 1/ get info 2/ treat them 3/ make the list with them
        my @sdtemp=();
        my $getlist="-l -R $mainDir";   # define command to get the list
        if ($followLink eq "true")      { $getlist="-L -l -R $mainDir"; }

        # new style here (faster)
        open (STATUS, "ls $getlist >&1 |");
        while (<STATUS>) { push @sdtemp, $_; }
        close STATUS;

        #old style for compare
        #@sdtemp=`ls $getlist`;

	$mainCount = @sdtemp;
        my $currentDir= $mainDir;
	while (@internalList > 0) { pop @internalList; }			# clear the array
	while (@externalList > 0) { pop @externalList; }
	my $extDir = $mainDir;
	my $intDir = $mainDir;
	my $cleanFilename = "";         # added to convert _ to space
	push @externalList, $stuck1."\r\n";
	push @externalList, $stuck2."\r\n";
	push @externalList, "\r\n";
	my $moo = @MOTD;
	for (my $mooc=0; $mooc < $moo; $mooc++)
	        {
	        push @externalList, $MOTD[$mooc];
	        }
	for ($i=0; $i < $mainCount; $i++)
		{
		my $firstchar = substr $sdtemp[$i], 0, 1;			# get first char of current line
		if ($firstchar eq '-')
			{							# File info
			$thefile = $sdtemp[$i];
			@fileTab = split ' ', $thefile,9;
			$totalFiles++;						# one more file
			$totalKB+=$fileTab[4];
			chomp($fileTab[8]);
			$cleanFileName=&formatFilename($fileTab[8]);
			my $extFilename .= "!" .+ $Trigger .+ " " .+ $cleanFileName;
			my $longLine=" -------------------------------------------------------------------------------------------";
			my $lengthValue=$listChars;     # build a custom value list
			if ($lengthValue < length($extFilename))        { $lengthValue = length($extFilename); }   # in case filename is > 90chars
			my $newL = substr($extFilename.$longLine.$longLine,0,$lengthValue);
			$longLine=sd_byte_converter($fileTab[4]);       # convert size
			if ($listShowSize eq "true")    { $extFilename=$newL." ".$longLine."\r\n"; }
			                else            { $extFileName=$extFileName."\r\n"; }

			my $intFilename .= $intDir.$fileTab[8];
			push @externalList, $extFilename;			# store !trigger + filename
                        #if ($listShowInfo eq "true") disable, output info on all files in the list
                         #       {
                          #      my $tt=sd_get_file_information($intFilename);
                           #     push @externalList, $tt;
                            #    }
			push @internalList, $cleanFileName;        		# store filename (as we found it)
			push @internalList, $intFilename;			# store filename with path
			push @internalList, "$fileTab[4]";			# store size
			}
		if ($firstchar eq '/')
			{      								# Directory info
			$totalDir++;
			$currentDir="";
			$currentDir=$sdtemp[$i];
			chop $currentDir;					# kill \n
			chop $currentDir;					# kill :
			my $tmpDir="";
			$tmpDir .= $currentDir .+ '/';				# add / to end
			$intDir = $tmpDir;
			my $z = length $mainDir;
			$currentDir = substr $tmpDir, $z, 1000;
			$z = length $currentDir;
			if (length($currentDir)>1) { chop $currentDir; }	# kill last /
			$extDir = $currentDir .+ "\r\n";
			push @externalList, "\r\n";
			my $uu1=$stuck3." ".$extDir;
			my $uu2="";
			for (my $uu3=0; $uu3 < length($uu1)-2; $uu3++)    { $uu2=$uu2."="; }
			push @externalList, $uu2."\r\n";
			push @externalList, $uu1;
			push @externalList, $uu2."\r\n";
			}
		}
        my $L_mark2=time; # 2nd mark, stop time
	$L_res1=$L_mark2-$L_mark1;
        if ($L_res1<1) { $L_res1 = 1; }
        $L_res2=$totalFiles / $L_res1;
        @sdtemp=`rm $mlist1`;   # kicking out working status
        #print("Removing in SDUtil -> $mlist1");
	my $tempremove= $myhomepath.$oldList;
	@sdtemp=`rm $tempremove`;			# kicking out old list from disk
        # again use of language dependant date
        $zipList=$newList.".zip";
        $newList=$newList.".txt";
	$refList=$Trigger."-list.ref";
	if (open(fileOut,">".$myhomepath.$newList))
		{
		for ($i=0; $i < @externalList; $i++)
			{
			print fileOut "$externalList[$i]";
			}
		close(fileOut);
		if ($useZIP eq "true")
			{
			my $looseIt=$myhomepath.$zipList." ".$myhomepath.$newList;
			$looseIt=`zip -9 -m -j $looseIt`;
			@zipinfo=split ":",$looseIt;
                        chomp($zipinfo[1]);
			$newList=$zipList;
			}
		$oldList=$newList;
		}
	else
		{
		}
	if (open(fileOut,">".$myhomepath.$refList))
		{
		for ($i=0; $i < @internalList; $i++)
			{
			print fileOut "$internalList[$i]\n";
			}
		close(fileOut);
		}
$buildingList=0;
open(FILEIN, ">".$mlist2);      # build result file
print FILEIN $newList.";;;;";
print FILEIN $oldList.";;;;";
print FILEIN $zipList.";;;;";
print FILEIN $L_res1.";;;;";
print FILEIN $L_res2.";;;;";
print FILEIN $mainCount.";;;;";
print FILEIN $totalFiles.";;;;";
print FILEIN $totalDir.";;;;";
print FILEIN $totalKB.";;;;";
print FILEIN $MOTDL.";;;;";
print FILEIN $zipinfo[1].";;;;";
close(FILEIN);
return 0;
}

