##
# db file parsing library
# Wilfredo Sanchez Jr. | tritan@mit.edu
# and Eric Mumpower    | nocturne@mit.edu
##
# Copyright 1995 Wilfredo Sanchez Jr. | tritan@mit.edu
# Written for the MIT SIPB webmasters | webmaster@mit.edu
##

package DB;

$default_home = '/afs/sipb.mit.edu/project/www/data/home.DATA';

sub ParseHome {
    # Parse a home pages data file
    # &DB::ParseHome($filename);
    #   $filename = valid home pages data file
    #               Standard Input is assumed unless ($filename)
    # Returns # records read, or 0 if error
    # File format is:
    #   - one entry per line
    #   - fields are: Username, URL, Full name, Index, Symlink, Date
    #   - fields are separated by  (Control-W, \cW in Perl)
    local($filename) = @_;

    local($dbfile) = STDIN;
    local($count)  = 0;

    ##
    # Open the input file
    ##
    if ($filename) {
	$dbfile = INFILE;
	unless (open($dbfile, $filename)) {
	    warn "$0: failed to open input file $filename.\n";
	    return 0;
	}
    }

    ##
    # Parse
    ##

    while ($input = <$dbfile>)
    {
	local($username, $url, $fullName, $index, $link, $date);

	$count++;

	chop $input;

	# Filter out comments
	next if ($input =~ /^\s*\#/); # Commented line
	$input =~ s/\#.*$//;	      # Comment at end of line

	# Read in a line
	($username, $url, $fullName, $index, $link, $date)
	    = split("\cW", $input);

	next unless $username;	# Account for blank lines

	# Store data in hashes
	warn "User $username repeated.\n" if $DB'index {$username};
	warn "Index $index repeated.\n"   if $DB'name  {$index};
	#warn "Name $fullName repeated.\n" if $DB'user  {$fullName};

	$DB'index {$username} = $index;
	$DB'user  {$fullName} = $username;
	$DB'name  {$index}    = $fullName;
	$DB'link  {$username} = $link;
	$DB'date  {$username} = $date;
	$DB'url   {$username} = $url;
    }

    close($dbfile);

    return $count;
}

sub ClearHome {
    # Clears memory. This is useful if the database was written to disk, and
    # may have been since modified by other programs, and so the memory
    # needs to be cleared before the database is re-read.
    # &DB::ClearHome();
    # Will erase database state
    undef %DB'index ;
    undef %DB'user  ;
    undef %DB'name  ;
    undef %DB'date  ;
    undef %DB'link  ;
    undef %DB'url   ;    
}

sub SpewHome {
    # Spew a home pages data file
    # &DB::SpewHome($filename);
    #   $filename = output file name
    #               standard output is assumed unless ($filename)
    local($filename) = @_;

    local($dbfile) = STDOUT;
    local($count)  = 0;

    ##
    # Open the output file
    ##
    if ($filename) {
	$dbfile = OUTFILE;
	unless (open($dbfile, ">$filename")) {
	    warn "$0: failed to open output file $filename.\n",
	         "Exiting.\n";
	    return 0;
	}
    }

    ##
    # Spew
    ##

    foreach $user (sort keys %DB'index) {
	print $dbfile "$user\cW$DB'url{$user}\cW$DB'name{$DB'index{$user}}\cW$DB'index{$user}\cW$DB'link{$user}\cW$DB'date{$user}\n";
        $count++;
    }

    close($dbfile);

    return $count;
}

sub AddUser {
    # Add a user to memory
    # &DB::AddUser($user, $url, $name, $index, $link, [$date]);
    #   $user  = User name
    #   $url   = URL
    #   $name  = Full name
    #   $index = Index
    #   $link  = symlink for user's web directory
    #            should be "" if the URL is not a local file
    #   $date  = last modification date (yymmdd)
    #            assumed to be today's date unless given
    local($user, $url, $name, $index, $link, $date) = @_;

    if ($date eq "") {
	$date = &_getDate;
    }

    warn "User $user repeated.\n"   if $DB'index {$user};
    warn "Index $index repeated.\n" if $DB'name  {$index};
    #warn "Name $name repeated.\n"   if $DB'user  {$name};

    $DB'index {$user}  = $index;
    $DB'user  {$name}  = $user;
    $DB'name  {$index} = $name;
    $DB'date  {$user}  = $date;
    $DB'link  {$user}  = $link;
    $DB'url   {$user}  = $url;

    return 1;
}

sub DelUser {
    # Delete a user from memory
    # &DB::DelUser($user);
    # $user = User name
    local($user) = @_;

    unless ( $DB'index{$user} ) {
	warn "User $user does not exist.\n";
	return -1;
    }

    local($index) = $DB'index {$user };
    local($name)  = $DB'name  {$index};

    delete($DB'index {$user });
    delete($DB'date  {$user });
    delete($DB'url   {$user });
    delete($DB'user  {$name });
    delete($DB'link  {$name });
    delete($DB'name  {$index});

    return 1;
}

sub FetchUser {
    # Fetch a user's entry
    # &DB::FetchUser($user);
    #   $user = User name
    # Returns 5-element array of user data:
    #   ($url, $name, $index, $link, $date)
    #   If user doesn't exist, returns array of zeros.
    local($user) = @_;

    return (0, 0, 0, 0) if ($DB'index {$user} eq "");
    return ( $DB'url{$user},
             $DB'name{$DB'index{$user}},
             $DB'index{$user},
             $DB'link{$user},
             $DB'date{$user}
           );
}    

# the following routine was added by grant emery for various maintenance
# routines to keep form breaking the abstraction barrier

sub FetchUserList {
    # Fetches a list of all the usernames in the database
    # &DB::FetchUserList();
    # Returns an unordered list of all the users in the database

    return keys %DB'url;
}

##
# Internal Functions
##

sub _getDate {
    local(@t, $year, $month, $day);

    @t = localtime();
    $year  =  $t[5];
    $month = ($t[4] + 1);
    $day   =  $t[3];

    return &_padzero($year) . &_padzero($month) . &_padzero($day);
}    

sub _padzero {
    local($n) = @_;

    ($n < 10) ? ('0' . $n) : $n;
}

1;
