#!/usr/bin/perl
#
# $Id: DataStore.pm,v 1.12 2001/11/24 02:55:56 levine Exp $
#
# Copyright (C) 2000  James D. Levine (jdl@vinecorp.com)
#
#
#   This program is free software; you can redistribute it and/or
#   modify it under the terms of the GNU General Public License
#   as published by the Free Software Foundation; either version 2
#   of the License, or (at your option) any later version.
# 
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
# 
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 
#   02111-1307, USA.
#
####################################################################

#
# Base class for installable data store back-ends.  Requires some
# refinement in order to allow arbitrary back-ends to really work.
#


package PortScan::DataStore;
 
use strict;
no strict 'refs';


use PortScan::ScanSet;
use PortScan::ScanContext;


sub new
{
    my ($type) = @_;

    my $self = 
    {
	user_properties => {},	# user-supplied props for this DataStore
    };

    bless $self, $type;

    return $self;
}


# Returns the ScanSet associated with the supplied tag
# or undef.

sub retrieve_scanset
{
    my  $tag = shift;


#    ($scanset) || undef
}

#
# Inserts the supplied ScanSet into the store; the associated tag
# is taken from the ScanSet::tag() method
#
sub put_scanset
{
    my ($self, $scanset) = @_;
}


#
# Creates a DataStore of the type configured as default in
# the ScanContext.
#
sub create_default_type
{
    my $t = &PortScan::ScanContext::default_data_store_type();

    eval "use $t";
    my $ds = new $t;

    $ds->set_user_properties(&PortScan::ScanContext::default_data_store_props() );

    $ds;
}

#
# Returns a DataStore instance of the default type linked to
# the supplied tag.  Eventually will allow user-specification of the
# DataStore in question, in a format like <type>:<store name>:<ScanSet tag>

sub data_store_for
{
    my $tag = shift;
    
    $tag = prepare_tag($tag);

    if ($tag =~ /^:/)		# tag starts with ':', treat as an opaque data source
    {
	$tag =~ s/^://g;
	return ($tag, create_default_type());
    }
    else			# treat tag as a filename of an nmap file
    {
	use PortScan::NmapFile;
	my $ds = new PortScan::NmapFile;

	$ds->attach_file($tag);
	$ds->attach_metafile($tag . ".info");
	return ($tag, $ds);
    }
}


#
# Performs % substitutions on a tag.
#

sub prepare_tag
{
    my $t = shift;
    my $host = `hostname`; chomp $host;

    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    $year += 1900;
    $mon += 1;

    $sec = sprintf "%02d", $sec;
    $min = sprintf "%02d", $min;
    $hour = sprintf "%02d", $hour;

    $t =~ s/%S/$sec/g;
    $t =~ s/%M/$min/g;
    $t =~ s/%H/$hour/g;

    $mday = sprintf "%02d", $mday;
    $mon = sprintf "%02d", $mon;
    $year = sprintf "%04d", $year;
    $wday = sprintf "%d", $wday;
    $yday = sprintf "%03d", $yday;

    $t =~ s/%D/$mday/g;
    $t =~ s/%m/$mon/g;
    $t =~ s/%Y/$year/g;

    $t =~ s/%j/$yday/g;
    $t =~ s/%w/$wday/g;

    $t =~ s/%F/$host/g;

    $t;
}

#
# populates a DataStore's user-specified properties.  
# The properites are implementation-dependent, in the format
# of k1=v1,k2=v2,...,kN=vN
#
# user properties are intended for DataStore-specific configurations.
# For example, an NmapFile DataStore puts all files in a single
# directory; the directory would be a user property.  Likewise a database
# DataStore would have host/port information of the database server.

sub set_user_properties 
{
    my ($self, $propstring) = @_;
    $self->{user_properties} = split_property_string($propstring);
}

#
# Generates a hash from a string in the form of of k1=v1,k2=v2,...,kN=vN
#

sub split_property_string
{
    my $prop_string = shift;
    $prop_string =~ s/,/=/g;

    return { split /=/, $prop_string }
}


# retrieves a user property by name

sub get_user_property
{
    my ($self, $k) = @_;
    return $self->{user_properties}->{$k};
}

#
# returns a list of tags for all scansets managed by the DataStore
#
sub enumerate_scansets
{
# $[list of scansets] || undef
}

1;









