#!/usr/bin/perl
#------------------------------------------------------------------------------
# Copyright (C) 2001 Thomax Kaulmann
# 
# 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.

use lib '../config';
use CGI;
use DBI;
use OMA;
use XML::Parser;
use HTTP::Date qw(str2time time2isoz);
use Unicode::String qw(utf8 latin1 utf16);
use Net::HTTP;
use XML::Mini;
use XML::Mini::Document;

# define media types
@types = ('ota','ora','ova','opa','reboot');

CGI::ReadParse();
my $query = new CGI();
print $query->header('text/xml');
$db = OMA::opendb();





                                        ######
                                         ##  ##
  ####  ## ###  ## ###    ####  ## ###   ##  ##  ####     #####   ####
 ##  ##  ### ##  ### ##  ##  ##  ### ##  #####      ##   ##  ##  ##  ##
 ######  ##      ##      ##  ##  ##      ##      #####   ##  ##  ######
 ##      ##      ##      ##  ##  ##      ##     ##  ##    #####  ##
  ####  ####    ####      ####  ####    ####     ### ##      ##   ####
                                                         #####
sub errorPage {
	my $code = shift;
	my $message = shift;

	my $xmldoc = XML::Mini::Document->new();
	my $oailist = $xmldoc->getRoot();

	my $oaipmh = $oailist->createChild('OAI-PMH');
	$oaipmh->attribute('xmlns','http://www.openarchives.org/OAI/2.0/');
	$oaipmh->attribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
	$oaipmh->attribute('xmlns:schemaLocation','http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd');

	my $tdate = time2isoz(time); $tdate =~ s/\ /T/;
	$oaipmh->createChild('responseDate')->text($tdate);

	my $ttag = $oaipmh->createChild('request');
	$ttag->attribute('verb',$in{verb}) if($in{'verb'});
	$ttag->text("http://archive.b.lab.net/oma-bin/oma-oai");

	$ttag = $oaipmh->createChild('error');
	$ttag->attribute('code',$code);
	$ttag->text($message);

	print $xmldoc->toString($XML::Mini::NoWhiteSpaces);
#	print $xmldoc->toString();

	exit;
}



                  ##                       ##
                  ##
  #####   ####   #####    ####   ####     ###    ## ##   ####   ## ###
 ##  ##  ##  ##   ##     ##  ##     ##     ##   #######     ##   ##  ##
 ##  ##  ######   ##     ##  ##  #####     ##   ## # ##  #####   ##  ##
  #####  ##       ## ##  ##  ## ##  ##     ##   ## # ## ##  ##   #####
     ##   ####     ###    ####   ### ##   ####  ##   ##  ### ##  ##
 #####                                                          ####
sub getoaimap {
    my @row;
    my $st;

    $st=$db->prepare("SELECT * FROM treemap");
    $st->execute();

    while(@row=$st->fetchrow()) {
        $row[1] =~ s/\//:/g;
        $row[1] =~ s/^://;
        $treemap{$row[0]} = $row[1];
        $nodemap{$row[1]} = $row[0];
    }
    $st->finish();
}



                  ##       ###                            ##
                  ##        ##                            ##
  #####   ####   #####   #####    ####    ####    ####   #####
 ##  ##  ##  ##   ##    ##  ##   ##  ##  ##      ##  ##   ##
 ##  ##  ######   ##    ##  ##   ##       ####   ######   ##
  #####  ##       ## ## ##  ##   ##  ##      ##  ##       ## ##
     ##   ####     ###   ### ##   ####   #####    ####     ###
 #####
sub getdcset {
	my $xmlnode = shift;
	my $publisher = shift;
	my $media = shift;
	my $id = shift;
	my $st;
	my @row;
	my %hashrow;
	my $tdate;

#	$xmlnode->createChild('dc:publisher')->text($publisher);
	$st = $db->prepare("
			SELECT  *
			FROM    $media" . "_page
			WHERE   id=$id
			AND     location='$publisher'
	");
	$st->execute();
	$st->bind_columns(\(@hashrow{@{$st->{NAME_lc}}}));
	@row = $st->fetchrow();
	$st->finish();

	my $k;
	foreach $k (keys %hashrow) {
		if($hashrow{$k}) {
			$hashrow{$k} = utf8($hashrow{$k});
		}
	}

	$xmlnode->createChild('dc:title')->text($hashrow{dc__title})
		if($hashrow{dc__title});

	if($hashrow{dc__title__alternative}) {
		my $tmp = $xmlnode->createChild('dc:title');
		$tmp->attribute('type','alternative');
		$tmp->text($hashrow{dc__title__alternative});
	}
	

	$xmlnode->createChild('dc:publisher')->text($publisher);

	if($hashrow{dc__date__issued}) {
		$tdate = time2isoz($hashrow{dc__date__issued}); $tdate =~ s/\ /T/;
		my $tmp = $xmlnode->createChild('dc:date');
		$tmp->attribute('type','issued');
		$tmp->text($tdate);
	}

	if($hashrow{dc__date__created}) {
		$tdate = time2isoz($hashrow{dc__date__created}); $tdate =~ s/\ /T/;
		my $tmp = $xmlnode->createChild('dc:date');
		$tmp->attribute('type','created');
		$tmp->text($tdate);
	}
	if($hashrow{dc__date__digitized}) {
		$tdate = time2isoz($hashrow{dc__date__digitized}); $tdate =~ s/\ /T/;
		my $tmp = $xmlnode->createChild('dc:date');
		$tmp->attribute('type','digitized');
		$tmp->text($tdate);
	}

	if($hashrow{dc__format__extent}) {
		my $tmp = $xmlnode->createChild('dc:format');
		$tmp->attribute('type','extent');
		$tmp->text($hashrow{dc__format__extent});
	}
	if($hashrow{dc__format__medium}) {
		my $tmp = $xmlnode->createChild('dc:format');
		$tmp->attribute('type','medium');
		$tmp->text($hashrow{dc__format__medium});
	}
	if($hashrow{dc__format__encoding}) {
		my $tmp = $xmlnode->createChild('dc:format');
		$tmp->attribute('type','encoding');
		$tmp->text($hashrow{dc__format__encoding});
	}

	$xmlnode->createChild('dc:identifier')->text($hashrow{dc__identifier})
		if($hashrow{dc__identifier});

	$xmlnode->createChild('dc:source')->text($hashrow{dc__source})
		if($hashrow{dc__source});

	if($hashrow{dc__rights}) {
		my $tmp = $xmlnode->createChild('dc:rights');
		$tmp->attribute('license', XML::Mini->escapeEntities($hashrow{dc__rights__license})) if($hashrow{dc__rights__license});
		$tmp->text($hashrow{dc__rights});
	}

#	$xmlnode->createChild('dc:rights:license')->text($hashrow{dc__rights__license})
#		if($hashrow{dc__rights__license});


	if($hashrow{dc__description__abstract}) {
		my $tmp = $xmlnode->createChild('dc:description');
		$tmp->attribute('type','abstract');
		$tmp->text($hashrow{dc__description__abstract})
	}

	if($hashrow{dc__description__toc}) {
		my $tmp = $xmlnode->createChild('dc:description');
		$tmp->attribute('type','tableOfContent');
		$tmp->text($hashrow{dc__description__toc})
	}

	if($hashrow{dc__description__long}) {
		my $tmp = $xmlnode->createChild('dc:description');
		$tmp->attribute('type','long');
		$tmp->text($hashrow{dc__description__long})
	}

	$xmlnode->createChild('dc:type')->text($hashrow{dc__type})
		if($hashrow{dc__type});

	$xmlnode->createChild('dc:subject')->text($hashrow{dc__subject})
		if($hashrow{dc__subject});

	$xmlnode->createChild('dc:language')->text($hashrow{dc__language})
		if($hashrow{dc__language});

	if($hashrow{dc__coverage__spatial}) {
		my $tmp = $xmlnode->createChild('dc:coverage');
		$tmp->attribute('type','spatial');
		$tmp->text($hashrow{dc__coverage__spatial})
	}

	if($hashrow{dc__coverage__temporal}) {
		my $tmp = $xmlnode->createChild('dc:coverage');
		$tmp->attribute('type','temporal');
		$tmp->text($hashrow{dc__coverage__temporal})
	}

	$st = $db->prepare("
			SELECT  dc__creator,dc__creator__role
			FROM    reboot_creator
			WHERE   ID=$id
			AND     location='$publisher'
	");
	$st->execute();
	while(@row=$st->fetchrow()) {
		if($row[0]) {
			my $rel = $xmlnode->createChild('dc:creator');
			$rel->attribute("role",$row[1]);
			$rel->text($row[0]);
		}
	}
	$st->finish();

	$st = $db->prepare("
			SELECT  dc__contributor,dc__contributor__role
			FROM    reboot_contributor
			WHERE   ID=$id
			AND     location='$publisher'
	");
	$st->execute();
	while(@row=$st->fetchrow()) {
		if($row[0]) {
			my $rel = $xmlnode->createChild('dc:contributor');
			$rel->attribute("role",$row[1]);
			$rel->text($row[0]);
		}
	}
	$st->finish();

	$st = $db->prepare("
			SELECT  dc__relation__type,dc__relation__value
			FROM    reboot_relation
			WHERE   ID=$id
			AND     location='$publisher'
	");
	$st->execute();
	while(@row=$st->fetchrow()) {
		if($row[0]) {
			my $rel = $xmlnode->createChild('dc:relation');
			$rel->attribute("relation",$row[0]);
			$rel->text($row[1]);
		}
	}
	$st->finish();


	return($xmlnode);
}



  ###      ##             ##     ######    ###                    ##
   ##                     ##       ##       ##                    ##
   ##     ###     ####   #####     ##    #####    ####  ## ###   #####    ####
   ##      ##    ##       ##       ##   ##  ##   ##  ##  ##  ##   ##     ##
   ##      ##     ####    ##       ##   ##  ##   ######  ##  ##   ##      ####
   ##      ##        ##   ## ##    ##   ##  ##   ##      ##  ##   ## ##      ##
  ####    ####   #####     ###   ######  ### ##   ####   ##  ##    ###   #####
sub listIdentifiers {
	my $st;
	my @row;
	my $i=0;
	my $tmp;
	my $resumptionToken="";
	my $continue = 0;

	my $from = "";
	my $until= "";
	my $set= "";

	my $xmldoc = XML::Mini::Document->new();
	my $oailist = $xmldoc->getRoot();

	my $oaipmh = $oailist->createChild('OAI-PMH');
	$oaipmh->attribute('xmlns','http://www.openarchives.org/OAI/2.0/');
	$oaipmh->attribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
	$oaipmh->attribute('xmlns:schemaLocation','http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd');

	my $tdate = time2isoz(time); $tdate =~ s/\ /T/;
	$oaipmh->createChild('responseDate')->text($tdate);

	my $ttag = $oaipmh->createChild('request');
	$ttag->attribute('verb','ListIdents');
	$ttag->attribute('from',$in{'from'}) if($in{'from'});
	$ttag->attribute('until',$in{'until'}) if($in{'until'});
	$ttag->attribute('set',$in{'set'}) if($in{'set'});
	$ttag->attribute('metadataPrefix',$in{'metadataPrefix'}) if($in{'metadataPrefix'});
	$ttag->attribute('resumptionToken',$in{'resumptionToken'}) if($in{'resumptionToken'});
	$ttag->text("http://archive.b.lab.net/oma-bin/oma-oai");


	my $ListIdentifiers = $oaipmh->createChild('ListIdentifiers');


	$from = "AND THISTYPE_conn.THISTYPE_page >= ". (str2time($in{from})) if($in{'from'});
	$until = "AND THISTYPE_conn.THISTYPE_page <= ". (str2time($in{until})+86400+3600) if($in{'until'});
	$set = "AND item.node_sid=$nodemap{$in{'set'}}" if($in{'set'});

	
	foreach $n (@types) {
		my $myfrom = $from;
		my $myuntil = $until;

		if($in{resumptionToken}) {
			($oai,$provider,$tmp) = split(/:/,$in{resumptionToken});
			($media,$id) = split(/\//,$tmp);
			next if($media ne $n);
			$resumptionToken = $in{resumptionToken};
			delete($in{resumptionToken});
		} else {
			$continue=1;
		}

		$myfrom =~ s/THISTYPE/$n/g;
		$myuntil =~ s/THISTYPE/$n/g;

		$st = $db->prepare("
				SELECT	item.*, $n" . "_conn.*
				FROM	item, $n" . "_conn
				WHERE	item.sid=$n" . "_conn.item_sid
				AND		item.type='$n'
				$myfrom
				$myuntil
				$set
				ORDER BY $n" . "_conn.$n" . "_page
		");
		$st->execute();
		while(@row = $st->fetchrow()) {
			next if(($continue==0) && ("oai:$row[8]:$row[3]/$row[7]" ne $resumptionToken));
			if("oai:$row[8]:$row[3]/$row[7]" eq $resumptionToken) {
				$continue = 1;
				next;
			}
			if($i < 100) {
				my $header = $ListIdentifiers->createChild('header');
				my $date = time2isoz($row[7]);
				$date =~ s/ /T/;

				$resumptionToken = "oai%3a$row[8]%3a$row[3]%2f$row[7]";
				$header->createChild('identifier')->text("oai:$row[8]:$row[3]/$row[7]");
				$header->createChild('datestamp')->text("$date");
				$header->createChild('setSpec')->text($treemap{$row[1]});
			}
			$i++;
		}
	}
#	$ListIdentifiers->createChild('completeListSize')->text($i);
	$ListIdentifiers->createChild('resumptionToken')->text($resumptionToken) if($i>100);
	print $xmldoc->toString($XML::Mini::NoWhiteSpaces);
#	print $xmldoc->toString();
}





  ###      ##             ##    ######                                     ###
   ##                     ##     ##  ##                                     ##
   ##     ###     ####   #####   ##  ##   ####    ####    ####  ## ###   #####
   ##      ##    ##       ##     #####   ##  ##  ##  ##  ##  ##  ### ## ##  ##
   ##      ##     ####    ##     ## ##   ######  ##      ##  ##  ##     ##  ##
   ##      ##        ##   ## ##  ##  ##  ##      ##  ##  ##  ##  ##     ##  ##
  ####    ####   #####     ###  ###  ##   ####    ####    ####  ####     ### ##
sub listRecords {
	my $st;
	my @row;
	my $i=0;
	my $tmp;
	my $resumptionToken="";
	my $continue = 0;

	my $from = "";
	my $until= "";
	my $set= "";

	my $xmldoc = XML::Mini::Document->new();
	my $oailist = $xmldoc->getRoot();

	my $oaipmh = $oailist->createChild('OAI-PMH');
	$oaipmh->attribute('xmlns','http://www.openarchives.org/OAI/2.0/');
	$oaipmh->attribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
	$oaipmh->attribute('xmlns:schemaLocation','http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd');

	my $tdate = time2isoz(time); $tdate =~ s/\ /T/;
	$oaipmh->createChild('responseDate')->text($tdate);

	my $ttag = $oaipmh->createChild('request');
	$ttag->attribute('verb','ListRecords');
	$ttag->attribute('from',$in{'from'}) if($in{'from'});
	$ttag->attribute('until',$in{'until'}) if($in{'until'});
	$ttag->attribute('set',$in{'set'}) if($in{'set'});
	$ttag->attribute('metadataPrefix',$in{'metadataPrefix'}) if($in{'metadataPrefix'});
	$ttag->attribute('resumptionToken',$in{'resumptionToken'}) if($in{'resumptionToken'});
	$ttag->text("http://archive.b.lab.net/oma-bin/oma-oai");

	my $ListRecords = $oaipmh->createChild('ListRecords');


	$from = "AND THISTYPE_conn.THISTYPE_page >= ". (str2time($in{from})) if($in{'from'});
	$until = "AND THISTYPE_conn.THISTYPE_page <= ". (str2time($in{until})+86400+3600) if($in{'until'});
	$set = "AND item.node_sid=$nodemap{$in{'set'}}" if($in{'set'});

	
	foreach $n (@types) {
		my $myfrom = $from;
		my $myuntil = $until;

		if($in{resumptionToken}) {
			($oai,$provider,$tmp) = split(/:/,$in{resumptionToken});
			($media,$id) = split(/\//,$tmp);
			next if($media ne $n);
			$resumptionToken = $in{resumptionToken};
			delete($in{resumptionToken});
		} else {
			$continue=1;
		}

		$myfrom =~ s/THISTYPE/$n/g;
		$myuntil =~ s/THISTYPE/$n/g;

		$st = $db->prepare("
				SELECT	item.*, $n" . "_conn.*
				FROM	item, $n" . "_conn
				WHERE	item.sid=$n" . "_conn.item_sid
				AND		item.type='$n'
				$myfrom
				$myuntil
				$set
				ORDER BY $n" . "_conn.$n" . "_page
		");
		$st->execute();
		while(@row = $st->fetchrow()) {
			next if(($continue==0) && ("oai:$row[8]:$row[3]/$row[7]" ne $resumptionToken));
			if("oai:$row[8]:$row[3]/$row[7]" eq $resumptionToken) {
				$continue = 1;
				next;
			}
			if($i < 55) {
				my $record = $ListRecords->createChild('record');
				my $header = $record->createChild('header');
				my $metadata = $record->createChild('metadata');
				my $date = time2isoz($row[7]);
				$date =~ s/ /T/;

				$resumptionToken = "oai%3a$row[8]%3a$row[3]%2f$row[7]";
				$header->createChild('identifier')->text("oai:$row[8]:$row[3]/$row[7]");
				$header->createChild('datestamp')->text("$date");

				$record = getdcset($metadata,$row[8],$row[3],$row[7]);
			}
			$i++;
		}
	}
#	$ListRecords->createChild('completeListSize')->text($i);
	$ListRecords->createChild('resumptionToken')->text($resumptionToken) if($i>55);
	print $xmldoc->toString($XML::Mini::NoWhiteSpaces);
#	print $xmldoc->toString();
}



  ###      ##             ##    ##   ##           ##               ###
   ##                     ##    ### ###           ##                ##
   ##     ###     ####   #####  #######   ####   #####   ####    #####   ####
   ##      ##    ##       ##    #######  ##  ##   ##        ##  ##  ##      ##
   ##      ##     ####    ##    ## # ##  ######   ##     #####  ##  ##   #####
   ##      ##        ##   ## ## ##   ##  ##       ## ## ##  ##  ##  ##  ##  ##
  ####    ####   #####     ###  ##   ##   ####     ###   ### ##  ### ##  ### ##

  ##                    #######                                   ##
  ##                     ##   #                                   ##
 #####   ####            ## #     ####  ## ###   ## ##   ####    #####    ####
  ##        ##           ####    ##  ##  ### ## #######     ##    ##     ##
  ##     #####           ## #    ##  ##  ##     ## # ##  #####    ##      ####
  ## ## ##  ##           ##      ##  ##  ##     ## # ## ##  ##    ## ##      ##
   ###   ### ##         ####      ####  ####    ##   ##  ### ##    ###   #####
sub listMetadataFormats {

	my $xmldoc = XML::Mini::Document->new();
	my $oailist = $xmldoc->getRoot();

	my $oaipmh = $oailist->createChild('OAI-PMH');
	$oaipmh->attribute('xmlns','http://www.openarchives.org/OAI/2.0/');
	$oaipmh->attribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
	$oaipmh->attribute('xmlns:schemaLocation','http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd');

	my $tdate = time2isoz(time); $tdate =~ s/\ /T/;
	$oaipmh->createChild('responseDate')->text($tdate);

	my $ttag = $oaipmh->createChild('request');
	$ttag->attribute('verb','ListMetadataFormats');
	$ttag->attribute('metadataPrefix',$in{'metadataPrefix'}) if($in{'metadataPrefix'});
	$ttag->attribute('resumptionToken',$in{'resumptionToken'}) if($in{'resumptionToken'});
	$ttag->text("http://archive.b.lab.net/oma-bin/oma-oai");

	$ttmp = $oaipmh->createChild('ListMetadataFormats');
	$format = $ttmp->createChild('metadataFormat');
	$format->createChild('metadataPrefix')->text('oai_dc');
	$format->createChild('schema')->text('http://www.openarchives.org/OAI/2.0/oai_dc.xsd');
	$format->createChild('metadataNamespace')->text('http://www.openarchives.org/OAI/2.0/oai_dc/');

	print $xmldoc->toString($XML::Mini::NoWhiteSpaces);
#	print $xmldoc->toString();
}



  ###      ##             ##      ####            ##
   ##                     ##     ##  ##           ##
   ##     ###     ####   #####   ##       ####   #####    ####
   ##      ##    ##       ##      ####   ##  ##   ##     ##
   ##      ##     ####    ##         ##  ######   ##      ####
   ##      ##        ##   ## ##  ##  ##  ##       ## ##      ##
  ####    ####   #####     ###    ####    ####     ###   #####
sub listSets {

	my $xmldoc = XML::Mini::Document->new();
	my $oailist = $xmldoc->getRoot();

	my $oaipmh = $oailist->createChild('OAI-PMH');
	$oaipmh->attribute('xmlns','http://www.openarchives.org/OAI/2.0/');
	$oaipmh->attribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
	$oaipmh->attribute('xmlns:schemaLocation','http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd');
	my $tdate = time2isoz(time); $tdate =~ s/\ /T/;
	$oaipmh->createChild('responseDate')->text($tdate);
	my $ttag = $oaipmh->createChild('request');
	$ttag->attribute('verb','ListSets');
	$ttag->attribute('metadataPrefix',$in{'metadataPrefix'}) if($in{'metadataPrefix'});
	$ttag->attribute('resumptionToken',$in{'resumptionToken'}) if($in{'resumptionToken'});
	$ttag->text("http://archive.b.lab.net/oma-bin/oma-oai");

	$ttmp = $oaipmh->createChild('ListSets');
	foreach $k (keys %treemap) {
		$set = $ttmp->createChild('set');
		$set->createChild('setSpec')->text($treemap{$k});
		$set->createChild('setName')->text($treemap{$k});
	}

	print $xmldoc->toString($XML::Mini::NoWhiteSpaces);
#	print $xmldoc->toString();
}


   ##      ###                    ##       ##      ###
            ##                    ##              ## ##
  ###    #####    ####  ## ###   #####    ###     ##     ##  ##
   ##   ##  ##   ##  ##  ##  ##   ##       ##    ####    ##  ##
   ##   ##  ##   ######  ##  ##   ##       ##     ##     ##  ##
   ##   ##  ##   ##      ##  ##   ## ##    ##     ##      #####
  ####   ### ##   ####   ##  ##    ###    ####   ####        ##
                                                         #####
sub identify {

	my $xmldoc = XML::Mini::Document->new();
	my $oailist = $xmldoc->getRoot();

	my $oaipmh = $oailist->createChild('OAI-PMH');
	$oaipmh->attribute('xmlns','http://www.openarchives.org/OAI/2.0/');
	$oaipmh->attribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
	$oaipmh->attribute('xmlns:schemaLocation','http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd');
	my $tdate = time2isoz(time); $tdate =~ s/\ /T/;
	$oaipmh->createChild('responseDate')->text($tdate);
	my $ttag = $oaipmh->createChild('request');
	$ttag->attribute('verb','Identify');
	$ttag->text("http://archive.b.lab.net/oma-bin/oma-oai");

	my $ident = $oaipmh->createChild('Identify');
	$ident->createChild('repositoryName')->text('Open Meta Archive Backup Repository');
	$ident->createChild('baseURL')->text('http://archive.b.lab.net/oma-bin/oma-oai');
	$ident->createChild('adminEmail')->text('thomax@icf.de');
	$ident->createChild('earliestDatestamp')->text('2003-06-07T23:02:30Z');
	$ident->createChild('deletedRecord')->text('transient');
	$ident->createChild('protocolVersion')->text('2.0');
	$ident->createChild('granularity')->text('YYYY-MM-DDThh:mm:ssZ');

	$ttag = $ident->createChild('description');
	$oaiident = $ttag->createChild('oai-identifier');
	$oaiident->attribute('xmlns','http://www.openarchives.org/OAI/2.0/oai-identifier');
	$oaiident->attribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
	$oaiident->attribute('xmlns:schemaLocation','http://www.openarchives.org/OAI/2.0/oai-identifier http://www.openarchives.org/OAI/2.0/oai-identifier.xsd');
	$oaiident->createChild('schema')->text('oai');
	$oaiident->createChild('repositoryIdentifier')->text('archive.reboot.fm');
	$oaiident->createChild('delimiter')->text(':');
	$oaiident->createChild('sampleIdentifier')->text('oai:archive.reboot.fm:reboot/1055268060');

	$ttag = $ident->createChild('description');
	$oaiident = $ttag->createChild('friends');
	$oaiident->attribute('xmlns','http://www.openarchives.org/OAI/2.0/friends/');
	$oaiident->attribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
	$oaiident->attribute('xmlns:schemaLocation','http://www.openarchives.org/OAI/2.0/friends/ http://www.openarchives.org/OAI/2.0/friends.xsd');
	$oaiident->createChild('baseURL')->text('http://archive.b.lab.net/oma-bin/oma-oai');

	print $xmldoc->toString($XML::Mini::NoWhiteSpaces);
#	print $xmldoc->toString();
}



                  ##    ######                                     ###
                  ##     ##  ##                                     ##
  #####   ####   #####   ##  ##   ####    ####    ####  ## ###   #####
 ##  ##  ##  ##   ##     #####   ##  ##  ##  ##  ##  ##  ### ## ##  ##
 ##  ##  ######   ##     ## ##   ######  ##      ##  ##  ##     ##  ##
  #####  ##       ## ##  ##  ##  ##      ##  ##  ##  ##  ##     ##  ##
     ##   ####     ###  ###  ##   ####    ####    ####  ####     ### ##
 #####
sub getRecord {
	my $xmldoc = XML::Mini::Document->new();
	my $oairec = $xmldoc->getRoot();

	my $oaipmh = $oairec->createChild('OAI-PMH');
	$oaipmh->attribute('xmlns','http://www.openarchives.org/OAI/2.0/');
	$oaipmh->attribute('xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
	$oaipmh->attribute('xmlns:schemaLocation','http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd');
	my $tdate = time2isoz(time); $tdate =~ s/\ /T/;
	$oaipmh->createChild('responseDate')->text($tdate);
	my $ttag = $oaipmh->createChild('request');
	$ttag->attribute('verb','Identify');
	$ttag->text("http://archive.b.lab.net/oma-bin/oma-oai");

	$ttag = $oaipmh->createChild('GetRecord');
	my $record = $ttag->createChild('record');
	my $header = $record->createChild('header');
	my $metadata = $record->createChild('metadata');

	my ($oai,$provider,$tmp) = split(/:/,$in{identifier});
	my ($media,$id) = split(/\//,$tmp);

	$header->createChild('idenitifier')->text($in{'identifier'});
	my $st = $db->prepare("
				SELECT	item.*, $media" . "_conn.*
				FROM	item, $media" . "_conn
				WHERE	item.sid=$media" . "_conn.item_sid
				AND		item.type='$media'
				AND		$media" . "_conn.$media" . "_page=$id
				AND		$media" . "_conn.location='$provider'
	");
	$st->execute();
	my @row = $st->fetchrow();
	$st->finish();

	$header->createChild('setSpec')->text($treemap{$row[1]});

	getdcset($metadata,$row[8],$row[3],$row[7]);

	print $xmldoc->toString($XML::Mini::NoWhiteSpaces);
#	print $xmldoc->toString();

}


my %doubled;
undef(%doubled);
getoaimap;


print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n";

if(($in{verb} ne "ListIdentifiers") && ($in{verb} ne "ListRecords")
&& ($in{verb} ne "ListMetadataFormats") && ($in{verb} ne "ListSets")
&& ($in{verb} ne "Identify") && ($in{verb} ne "GetRecord")) {
	errorPage("badVerb","Bad OAI Verb: $in{verb} is not a valid verb");
}

foreach $k (keys %in) {
	if($k ne "verb" and $k ne "set" and $k ne "from"
			and $k ne "until" and $k ne "identifier"
			and $k ne "metadataPrefix" and $k ne "resumptionToken") {
		errorPage("badArgument","Bad OAI Argument");
	}
	if($in{$k} =~ /\000/) {
		errorPage("badArgument","Bad OAI Argument: Doubled arg $k");
	}
}


if($in{identifier}) {
	my ($oai,$provider,$tmp) = split(/:/,$in{identifier});
	my ($media,$id) = split(/\//,$tmp);
	if($oai ne "oai" || !$provider || !$media || $id <= 0) {
		errorPage("badArgument","Bad OAI Argument: Wrong identifier format");
	}
}
if($in{from}) {
	if(str2time($in{from}) <=0) {
		errorPage("badArgument","Bad OAI Argument: Wrong from time format");
	}
}
if($in{until}) {
	if(str2time($in{until}) <=0) {
		errorPage("badArgument","Bad OAI Argument: Wrong until time format");
	}
}
if($in{from} && $in{until}) {
	if(str2time($in{from}) > str2time($in{until})) {
		errorPage("badArgument","Bad OAI Argument: until before from");
	}
	if(length($in{from}) < length($in{until})) {
		errorPage("badArgument","Bad OAI Argument: Unequal granularity");
	}
}
if($in{set}) {
	if(!$nodemap{$in{set}}) {
		errorPage("badArgument","Bad OAI Argument: Set not found");
	}
}
if($in{metadataPrefix}) {
	if($in{metadataPrefix} ne "oai_dc") {
		errorPage("cannotDisseminateFormat","The metadataPrefix argument is not supported");
	}
}
if($in{verb} eq "GetRecord") {
	if(!$in{metadataPrefix} || !$in{identifier}) {
		errorPage("badArgument","Bad OAI Argument: GetRecord without identifier or metadataPrefix");
	}
}
if($in{verb} eq "ListIdentifiers" || $in{verb} eq "ListRecords") {
	if($in{resumptionToken} && $in{metadataPrefix}) {
		errorPage("badArgument","Bad OAI Argument: metadataPrefix not expected");
	} else {
		if(!$in{resumptionToken} && !$in{metadataPrefix}) {
			errorPage("badArgument","Bad OAI Argument: metadataPrefix not expected");
		}
	}
}



listIdentifiers if($in{'verb'} eq "ListIdentifiers");
listRecords if($in{'verb'} eq "ListRecords");
listMetadataFormats if($in{'verb'} eq "ListMetadataFormats");
listSets if($in{'verb'} eq "ListSets");
identify if($in{'verb'} eq "Identify");
getRecord if($in{'verb'} eq "GetRecord");


